Обсуждаем контроллеры компании Atmel.
Ответить

Портится память

Пт авг 11, 2017 16:15:47

Вообщем проблема в следующем. Создаю массив, забиваю его нулями. В последствии оказывается что там не везде нули. Никаких операций с указателями не делаю, переполсти за пределы массива тоже не должен. При изменении кода прокта (абсолютно постороних) значения в массиве меняются без видимых кореляций. Изменение опций оптимизации так же приводит к измению данных. Упростил код до безумия - не пойму. Второй день сижу, поглядите, плз.

Вот код
Код:
#include <avr/interrupt.h>
#include <util/delay.h>

#define SETBIT(x,y)    (x|=(1<<y))
#define CLRBIT(x,y)    (x&=~(1<<y))
#define INVBIT(x,y)     x ^= (1<<y)

#define RGB_PORT PORTD
#define RED_PIN PD4
#define GREEN_PIN PD5
#define BLUE_PIN PD3

#define RED_ON       SETBIT(RGB_PORT,RED_PIN)
#define RED_OFF    CLRBIT(RGB_PORT,RED_PIN)
#define GREEN_ON    SETBIT(RGB_PORT,GREEN_PIN)
#define GREEN_OFF    CLRBIT(RGB_PORT,GREEN_PIN)
#define BLUE_ON    SETBIT(RGB_PORT,BLUE_PIN)
#define BLUE_OFF    CLRBIT(RGB_PORT,BLUE_PIN)

#define EventCount 20

// Скорость обмена UART в бит/с
#define UART_BAUD   9600ul      
#include <uart.c>

volatile unsigned char cR=0, cB=0, cG=0;    /* текущие значения яркости каждого канала */
/* массивы времени (в минутах) и значений цвета по каналам */
volatile unsigned char aHour[EventCount];
volatile unsigned char aMin[EventCount];
volatile unsigned char aRed[EventCount];
volatile unsigned char aGreen[EventCount];
volatile unsigned char aBlue[EventCount];

volatile unsigned char gH,gM,gS;

volatile int T; /* текущее время*/

ISR(TIMER0_OVF_vect) { /* шим ленты */
   static unsigned char Tmr=0;
   if (Tmr<cR) RED_ON;
      else RED_OFF;
   if (Tmr<cG) GREEN_ON;
      else GREEN_OFF;
   if (Tmr<cB) BLUE_ON;
      else BLUE_OFF;
   Tmr++;
}

ISR(TIMER1_OVF_vect) { /* следим за временем и менем яркость ленты */

   unsigned char n=0,i;

   T=gH*60+gM;

   for (i=0;i<EventCount;i++) { /* узнаем каким должно быть текущее значение ленты*/
      if (T>=(aHour[i]*60+aMin[i])) n=i;
   }
UART_SendChar(T>>8 & 0xFF);
UART_SendChar(T & 0xFF);
UART_SendChar(gS);
UART_SendChar(cR);
UART_SendChar(aRed[n]);
UART_SendChar(cG);
UART_SendChar(aGreen[n]);
UART_SendChar(cB);
UART_SendChar(aBlue[n]);
UART_SendChar(n);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);

}

void Load_Raspisanie(void) {

   for (unsigned char j=0;j<EventCount;j++) {
      aHour[j]=0;
      aMin[j]=0;
      aRed[j]=0;
      aGreen[j]=0;
      aBlue[j]=0;      
   }
   
   aHour[17]=16;
   aMin[17]=27;
   
   aHour[18]=16;
   aMin[18]=28;

   aHour[19]=16;
   aMin[19]=29;
}

int main (void) {

UART_Init();

sei();

Load_Raspisanie();

TCCR1B = (0<<CS12)|(1<<CS11)|(0<<CS10);
TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера

   gH=16;
   gM=26;
   gS=0;
   while(1) {
      if (gS++>60) {
         gS=0;
         gM++;
      }
      _delay_ms(900);
   }
}


При запуске в функции LoadRaspisanie зачищаем массив. В полсдествии в перерывании выводим значения. Байт часов, байт минут, далее три пары байт, второй байт - значения массива. Потом индекс массива который выводится. И вот в третьей паре второй байт он не ноль.

ВиеАвр 20100110 avr-gcc 4.3.3
протеус 8.1 sp1 билд 17358

Добавлено after 34 seconds:
attiny2313
Вложения
Archive.zip
вот сам проект с исходниками
(120.4 KiB) Скачиваний: 234

Re: Портится память

Пт авг 11, 2017 16:33:19

А сколько ОЗУ в МК :wink: ?

Re: Портится память

Вс авг 13, 2017 19:16:37

То есть ему оперативки не хватает? А как то написать об этом он не должен? Если массивы сделать побольше, то при компиляции winavr пишет, что .data столько то и в процентах, если перебор, то больше 100. Но тут вроде все в допусках.

Re: Портится память

Пн авг 14, 2017 05:25:00

Вот именно что вроде. Когда используете память на грани, надо ее точно рассчитывать не забывая про стек.

Re: Портится память

Пн авг 14, 2017 17:56:15

положил массивы в еепром, вроде все нормализовалось. Но я этого прикола не понял. В изначальном варианте я уменьшал размеры массива и winavr писал что data занято на 90%. С какого момента вообще нужно "начинать считать"? Почему компилятор перезаписывает переменные? Это ведь не такая уж и травиальная задача посчитать нужны объем памяти, я уж молчу про стек... "как жить, как страной управлять" (с)

Re: Портится память

Пн авг 14, 2017 18:05:25

Трудновато будет стек посчитать программируя на ЯВУ. Надо смотреть скомпилированный код. Локальные переменные скорее всего там будут. В обработчике прерывания некое количество регистров будет скинуто. Кстати, можно поглядеть как скомпиллися вход в main, возможно командой rcall, а так как из main выхода не будет, можно поправить указатель стека, тем самым сэкономив два байта.

Если в еепром часто писать, то не долго проживет.
У Вас "цветные" массивы какие значения могут принимать? Наверняка можно что-то с оптимизировать.

Re: Портится память

Пн авг 14, 2017 19:57:33

экономия двух байтов ничего не даст. Я уменьшил массивы на 20 байт - такая же петрушка осталась.
Писать в еепром часто и не будется, там один раз записали и потом только читать. Просто чтение в прерывании и мне кажется более правильно с переменными работать. Там изначально предполагалось что массивы будут в еепром храниться, просто работать хотел с переменными.

значения от 0до255, оптимизировать можно первые два массива - часы и минуты. Можно там выкроить по паре бит, но это усложнит чтение и запись и я решил что оно того не стоит.

на самом деле меня больше сам факт удивляет: пишешь, компилируешь, все ок, а потом фигагс и пойми что там происходит. И это я еще заметил что что то не так, а если бы это вылазило бы не всегда (при некоторых изменениях он вроде нормально гонит, но я так понимаю это до поры до времени).

И самое главное - а как вот сейчас узнать что все в порядке. Массивы я убрал, оставил только один. винавр пишет что 40% озу занято...

PS Загнал проект в протеус (всмысле исходник), под отладчиком смотрел адреса переменных - не нашел что бы адреса совпадали, похоже реально стек рушит...

Re: Портится память

Пн авг 14, 2017 20:04:24

Не надо ждать чудес от компилятора, все он не просчитает. Если при 60% свободной памяти что-то не так, то это уже не стек.
А константы лучше хранить в памяти программ, собственно они и так там.

Re: Портится память

Пн авг 14, 2017 22:55:50

А константы лучше хранить в памяти программ

всмысле? В ОЗУ? В виде переменных?
У меня "по плану" так: все эти массивы хранятся в еепром. Массив со временем продублирован и хранится в ОЗУ в виде массива переменных. А значения RGB читаются из eeprom.
чтение из eeprom не изнашивает же его? Запись туда очень редко,а вот чтение будет регулярно....

Re: Портится память

Вт авг 15, 2017 06:51:06

Проведи тестирование каждого фрагмента автономно, затем в комплекте (присоединяя по одному дополнительному модулю на тест). Где-то "накладка" имеется. Или банальный общий сбой работы МК.
:wink:

Re: Портится память

Вт авг 15, 2017 10:31:36

Отключил уже все модули, упростил до невозможности. Похоже и вправду нахватает памяти и идёт перезапись переменных

Re: Портится память

Вт авг 15, 2017 10:42:41

С attiny2313 лучше под ассемблером работать...
8)

Re: Портится память

Вт авг 15, 2017 15:51:52

alex1126 писал(а):всмысле? В ОЗУ? В виде переменных?
Память программ - это память программ, та память в которой лежит программа, она же флешь. Если данные не планируется менять в процессе работы программы и не хватает ОЗУ, то зачем их дублировать в ОЗУ.

Код:
if (gS++>60) {
         gS=0;
         gM++;
      }
      _delay_ms(900);

Неудачный алгоритм счета времени. Не потому что у Вас в минуте 61 секунда. Время лучше считать от таймера, например в том же обработчике прерывания от него. А вот сличать текущее время с заданным можно и в основном цикле. Я там понимаю 900мс опытным путем навскидку подобрано?

--
ЕЕПРОМ от чтения не портится.

Re: Портится память

Вт авг 15, 2017 22:53:35

Если данные не планируется менять в процессе работы программы и не хватает ОЗУ, то зачем их дублировать в ОЗУ.

планируется, но очень редко. Впринципе хранить их в еепром меня устаривает.

Неудачный алгоритм счета времени. Не потому что у Вас в минуте 61 секунда. Время лучше считать от таймера, например в том же обработчике прерывания от него. А вот сличать текущее время с заданным можно и в основном цикле. Я там понимаю 900мс опытным путем навскидку подобрано?

это типа заглушки. В реальности там с ds1307 берется время, но при поиски ошибки я отключил все модули который касаються часов и собственно i2c.

Добавлено after 2 minutes 42 seconds:
С attiny2313 лучше под ассемблером работать...
8)

не читаем получается код :( Да и из 2кб можно много выжать, если постараться. Я туда запихивал софтовую реализацию юсб и еще на "работу" хватило. вот где битва за каждый байт была :)

Re: Портится память

Ср авг 16, 2017 08:22:26

Под ассемблером и "нечитаем"??
:shock:
Это конечно не алгоритмы под СИ, однако "надо уметь готовить" дабы чего после двух-трех месяцев после написания прочесть.
:wink:
...

Re: Портится память

Ср авг 16, 2017 15:55:10

Ну хорошо, скажу по другому - не так легко читаем. Вообще я стараюсь писать так, что бы одна функция помещалась на экране без перелистывания. На асме так сделать не просто. Там только написание цикла полэкрана займет - положим начальное значение, увеличим, сравним с конечным значением, переход туда, переход сюда...
И вообще мы как то от темы отдалились.
Ответить