|
tick_10=0; не обнуляет переменную |
|
|
|
May 12 2010, 17:58
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Прямое обнуление volatile переменных не работает, использую Winavr 20100110, дебаггера в данный момент нет, так что посмотреть что именно происходить с контроллером проблематично. После операции вида volatile unsigned char Temporary=0; переменной присваивается единица. Компилятор выдаёт следующее: tick_10=0;
a00: 10 92 e4 01 sts 0x01E4, r1
volatile unsigned char Temporary=0; 3d2: 19 82 std Y+1, r1 ; 0x01
При этом не нашел ни одной операции, которая бы инкримировала r1, при этом tick_10 обнуляется в прерывании и после сохранения реггистров идет команда 894: 11 24 eor r1, r1 так что в r1 просто обязан быть 0.
Сообщение отредактировал Dzhesertep - May 12 2010, 18:00
|
|
|
|
|
May 12 2010, 19:02
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Цитата(SysRq @ May 12 2010, 22:34)  А как вы это узнали? Каждые 10 секунд идет запись лога, т.е. обнуление происходит внутри Код if (tick_10==10) { //что-то там ещё tick_10=0; } Замена данной конструкции на if (tick_10==10) { //что-то там ещё tick_10=tick_10-10; } решает проблему. Во втором месте та же проблема возникает при копировании строки, за счёт того что переменная не обнуляется и копирование идёт не с a[0], а с a[1]. Я пока склоняюсь к тому, что кто-то портит содержимое r1, но прямой инструкции пока не нашел, да и должен же компилятор заботиться о сохранении контекста.
Сообщение отредактировал rezident - May 14 2010, 19:55
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 12 2010, 20:20
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Цитата(Savrik @ May 12 2010, 23:35)  так-так-так... tick_10 и Temporary глобальные переменные? а ну-ка код полностью в студию  tick_10 глобальная, Temporary локальная и volatil'ом обзывал её лишь для проверки предположения(т.е. чтоб ноль из r1 писался напрямую в память). Содержательная часть кода: CODE ISR (TIMER0_OVF_vect)//overflow interrupt vector { tick++; ++tick_10;
if (++t.second==60) //keep track of time, date, month, and year { t.second=0; if (++t.minute==60) { t.minute=0; if (++t.hour==24) { t.hour=0; if (++t.date==32) { t.month++; t.date=1; } else if (t.date==31) { if ((t.month==4) || (t.month==6) || (t.month==9) || (t.month==11)) { t.month++; t.date=1; } } else if (t.date==30) { if(t.month==2) { t.month++; t.date=1; } } else if (t.date==29) { if((t.month==2) && (not_leap())) { t.month++; t.date=1; } } if (t.month==13) { t.month=1; t.year++; } } } } if (tick_10==10) { unsigned char sreg; unsigned int i; /* Save global interrupt flag */ sreg = SREG; /* Read TCNTn into i */ i = TCNT1; TCNT1 = 0; /* Restore global interrupt flag */ SREG = sreg; pin_events_count_n=pin_events_count_n+i; pin_events_count=pin_events_count_n; pin_events_count_n=0; if (log_on) { prepare_string(); USART_SEND(); } tick_10=tick_10-10; //tick_10=0; } }
void prepare_string(void) { for (int i=0; i<30;i++) log_string[i]='\0'; if (t.date<10) { log_string[0]='0'; my_itoa(t.date, &log_string[1]); } else my_itoa(t.date, &log_string[0]); log_string[2]='.';
if (t.month<10) { log_string[3]='0'; my_itoa(t.month, &log_string[4]); } else my_itoa(t.month, &log_string[3]); log_string[5]='.';
my_itoa(t.year, &log_string[6]); log_string[10]=' '; if (t.hour<10) { log_string[11]='0'; my_itoa(t.hour, &log_string[12]); } else my_itoa(t.hour, &log_string[11]); log_string[13]=':';
if (t.minute<10) { log_string[14]='0'; my_itoa(t.minute, &log_string[15]); } else my_itoa(t.minute, &log_string[14]); log_string[16]=':'; if (t.second<10) { log_string[17]='0'; my_itoa(t.second, &log_string[18]); } else my_itoa(t.second, &log_string[17]); log_string[19]=' '; volatile unsigned char i=my_ltoa(pin_events_count, &log_string[20]); log_string[20+i]=log_string[19+i]; log_string[19+i]=','; log_string[21+i]='\r'; log_string[22+i]='\n'; }
void my_itoa(int i, char *Place) { volatile int C[3]; volatile unsigned char Temp=0, NumLen = 0; do { Temp++; C[Temp] = i % 10; i = i/10; } while (i); NumLen = Temp; for (Temp = NumLen; Temp>0; Temp--) {Place[NumLen-Temp]=C[Temp] + 48;}
}
unsigned char my_ltoa(long int i, char *Place) { volatile unsigned char C[10]; volatile unsigned char Temp=0, NumLen = 0; do { Temp++; C[Temp] = i % 10; i = i/10; } while (i); NumLen = Temp; for (Temp = NumLen; Temp>0; Temp--) {Place[NumLen-Temp]=C[Temp] + 48;} return NumLen; }
void USART_SEND(void) { unsigned char Temporary=0; do { ch=log_string[Temporary]; SendCharUart1(ch); Temporary++; } while((ch!='\n')&&(Temporary<30)); }
Кстати, ещё баг возникает именно при выполнении prepare_string();из прерывания, если находиться в while(1) в функции отличной от main и в строке volatile unsigned char i=my_ltoa(pin_events_count, &log_string[20]); отсутсвует volatile. Контроллер начинает творить что-то страшное, сначала выводя на экран какой-то непонятный мусор, но с этим разбираться планирую когда раздобуду нормальный дебаггер. P.S. То что подготовка строки тупая и вообще неизящная я знаю, но суть не в этом.
Сообщение отредактировал rezident - May 14 2010, 19:57
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 13 2010, 13:22
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Dzhesertep @ May 13 2010, 00:20)  Контроллер начинает творить что-то страшное, сначала выводя на экран какой-то непонятный мусор Логично... Первое, что бросилось в глаза это my_ltoa... Попробуйте так (не претендую на оптимальность): Код uint8_t my_ultoa(uint32_t x, char *dst) { #define STR_SIZE 10 // 2^32 - 1 = 4294967295
char str[STR_SIZE]; // str w/o null terminator uint8_t len = 0;
do { str[len++] = '0' + x % 10; } while ( (x/=10) );
for (uint8_t i=0; i<len; i++) { *dst++ = str[len-i]; }
dst[0] = '\n'; // null return len; // str len w/o null terminator } А зачем Вам нужно знать длину строки и чем не устраивает стандартная ultoa из stdlib.h? Никогда не изобретайте велосипед и регулярно читайте букварь по СИ до полного прояснения в голове! ЗЫЖ Не надо лепить volatile где непоподя!!!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 13 2010, 16:11
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Цитата(demiurg_spb @ May 13 2010, 17:22)  Логично... Первое, что бросилось в глаза это my_ltoa... Ну вот ни разу не логично. Во первых не увидел принципиальных отличий между моей функцией и вашей (ну кроме терминального \n, который мне вообще не нужен) , и в чём же может быть ошибка именно моей функции? Во вторых проблему библиотечные функции не решили. В третьих страшное твориться при отсутвии volatile именно в volatile unsigned char i=my_ltoa(pin_events_count, &log_string[20]); (с библиотечной ultoa та же ситуация) (но вообще здесь всё более или менее понятно) В четвертых volatil'ы в такие функции ставятся не от хорошей жизни, а как последняя мера, когда совсем уже ничего не понятно, и единственный вред который они могут принести-только снижение производительности и лишний объем занимаемой памяти. И в пятых, но на самом деле во первых, из любого "букваря по Си" следует, что после tick_10=0; tick_10 будет НОЛЬ! Цитата(SysRq @ May 13 2010, 20:02)  Запись лога происходит не через 10 секунд? Откуда вывод, что вместо 0 пишется 1? Не понятно... Согласен, сказал неудачно Запись лога ДОЛЖНА идти каждые 10 секунд, но из-за того что tick_10 не обнуляется лог стабильно ИДЕТ каждые 9 секунд. При этом в самом начале переменная ноль и первый лог приходит как положено, через 10 секунд после запуска, т.е. получается последовательность времени записи: 10, 19, 28, 37 и т.д. Если конструкция tick_10=0; меняется на tick_10=tick_10-10 всё становится нормально и получается последовательность времени записи:10, 20, 30, 40 и т.д. принципиальным тут считаю именно способ обнуления переменных, используемый компилятором т.е. sts <адрес>, r1. Сразу добавлю: Сейчас перепроверил предположение о испорченном r1 и оно оказалось верным. Вынеся tick_10=0; перед функциями подготовки строки и её отправки всё заработало как и должно, сейчас буду искать кто же именно может менять значение регистра.
Сообщение отредактировал Dzhesertep - May 13 2010, 16:18
|
|
|
|
|
May 14 2010, 09:19
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Dzhesertep @ May 13 2010, 20:11)  Ну вот ни разу не логично. Блажен кто верует... Как минимум, у Вас инкремент индекса массива Temp++; происходит до того как поместить данные в этот массив, что может вызвать выход за диапазон массива... Процедура у Вас как называется? Зачем путать и себя и остальных? Если она работает с беззнаковым числом, так и называйте её по образу и подобию stdlib.h. Повторюсь - не изобретайте велосипед и воспринимайте критику адекватно. Учитесь пока можете. Ваш код пока просто ужасен. Есть одно хорошее высказывание, которое звучит примерно так: "Если есть возможность испивать совершённую ошибку - то это была не ошибка." Цитата(Dzhesertep @ May 13 2010, 20:11)  ...терминального \n, который мне вообще не нужен) Повторюсь и в 3 раз - не изобретайте велосипед. Если стандартные функции с именами *toa возвращают строку, то и Ваша с таким же именем обязана делать также. В противном случае назовите её иначе например *toa_wo_null! И почитайте наконец что такое volatile и с чем его едят, а то Цитата volatile unsigned char C[10]; volatile unsigned char Temp=0, NumLen = 0; просто удручает, а Вы говорите нет разницы Цитата кроме терминального \n И это ещё я не начинал придираться.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 14 2010, 13:02
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Dzhesertep @ May 13 2010, 20:11)  Ну вот ни разу не логично. ... Нелогичен весь Ваш обработчик прерывания. Не пробовали оценить/измерить время его выполнения? имхо, в нём ничего кроме Код volatile bit tick_flag; volatile uint tick_time;
ISR (TIMER0_OVF_vect)//overflow interrupt vector { tick_flag = 1; tick_time = TCNT1; } быть не должно. Чтобы немножко ускорить процесс своими, но более разумными Xtoa(), на контроллере без аппаратного деления, воспользуйтесь чем-нить вроде Код Деление на 10: 8 bit: Y = (X * 0xCD) >> 11; 16 bit: Y = (X * 0xCCCD) >> 19; 32 bit: Y = (X * 0xCCCCCCCD) >> 35; (поиск по конфе Вам в помощь - обсуждалось не раз) ЗЫЖ оформляйте, плз, сорцы тэгами {code} {/code} (в [], а не в {}, естесно) ручками или пользуйтесь [attachment=44040:000_140510.JPG]
|
|
|
|
|
May 14 2010, 13:43
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Цитата(demiurg_spb @ May 14 2010, 13:19)  Если стандартные функции с именами *toa возвращают строку, то и Ваша с таким же именем обязана делать также. 1.Это кому же она что обязана? 2.Специально для чистоплюев она называется my_ltoa (sic!) 3. Баг в ней на данный момент только один-неиспользуемый c[0], выход за пределы массива исключен так как больше 10^8 значения функции не передаются. А то что значение 2^32-1 она не обработает-да мне этого от неё и не надо. Опять же повторюсь, что мы уходим от темы. Если кто что-то и обязан, так это tick_10=0; обязан обнулять tick_10. P.S. Я отлично понимаю что делает volatile. В данном случае volatile привязывает переменную к конкретному адресу памяти, не давая ей болтаться по регистрам и стэку как попало. И опять же повторюсь-volatile ставится не от хорошей жизни.(И вообще мотивы заставившие меня "изобретать велосипед" касаются только меня) P.P.S. Я сюда пришел, дабы получить помощь лишь в вопросе чётко обозначенном в теме, уж с преобразованиями чисел сам как-нибудь разберусь. Если кого-то коробит кривость подготовки строки(а здесь, признаюсь, я принимаю критику), то извините, нужно было сделать быстро и чтобы работало. P.P.P.S. Специально для demiurg_spb. Я тоже могу начать придираться и сразу скажу, что строка по стандартам завершается ну никак уж не '\n'. Если кто забыл основы - то терминатор строки всю жизнь был '\0'
|
|
|
|
|
May 14 2010, 16:16
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Dzhesertep @ May 14 2010, 17:43)  P.S. Я отлично понимаю что делает volatile. В данном случае volatile привязывает переменную к конкретному адресу памяти, не давая ей болтаться по регистрам и стэку как попало. Чушь и бред. Как собственно почти всё остальное вами сказанное. volatile ничего никуда не "привязывает", а для случая "привязывает переменную к конкретному адресу" вменяемые люди используют static. Последний раз советую вам начать читать букварь!!! Цитата(Dzhesertep @ May 14 2010, 17:43)  Если кто забыл основы - то терминатор строки всю жизнь был '\0' Это очень даже хорошо, когда есть что забывать... Ну никак не понимаете вы намёков и не хотите учиться. Даже скучно становится... "Тщеславие - мой любимый грех" (с) AL PACINO - "The Devil's Advocate" Цитата(Dzhesertep @ May 14 2010, 17:43)  P.P.S. Я сюда пришел, дабы получить помощь лишь в вопросе чётко обозначенном в теме, уж с преобразованиями чисел сам как-нибудь разберусь. Если кого-то коробит кривость подготовки строки(а здесь, признаюсь, я принимаю критику), то извините, нужно было сделать быстро и чтобы работало. Это всегда так начинается, а потом все удивляются почему так много говнокодеров. Приучайтесь к дисциплине, решайте и по возможности отлаживайте каждую задачку отдельно - это даст вам хороший результат в целом. Невозможно отладить всё разом - примите это как данность. Из кусков говна янтарной комнаты не слепишь. Удачи Вам!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
May 14 2010, 19:31
|
Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222

|
Цитата(xemul @ May 14 2010, 17:02)  Нелогичен весь Ваш обработчик прерывания. Не пробовали оценить/измерить время его выполнения? имхо, в нём ничего кроме Код volatile bit tick_flag; volatile uint tick_time; ISR (TIMER0_OVF_vect)//overflow interrupt vector { tick_flag = 1; tick_time = TCNT1; } Согласен, что, в идеале, больше ничего он не должен делать, но специфика железки преполагает именно такой вариант. Времена оценивал: 0,75 с занимает подготовка строки и около 0,01 секунды отправка, так что до следующего прерывания всё должно успевать отрабатывать, а с "подвисанием" на это время раз в 10 секунд можно мириться. Опять же непонятно, что портит регистр r1, а именно в нём явная загвоздка, судя по дизассемблеру. Цитата(demiurg_spb @ May 14 2010, 20:16)  Чушь и бред. Как собственно почти всё остальное вами сказанное. volatile ничего никуда не "привязывает", а для случая "привязывает переменную к конкретному адресу" вменяемые люди используют static. Последний раз советую вам начать читать букварь!!! Хы. Вот от вас не было ещё ни одного совета по существу. В "букварях" обычно пишут что-то вроде "запрещает оптимизацию доступа". А на деле открываем дизассемблер и видим, что любая запись в переменную представляет собой просто прямое обращение к памяти посредством sts или st. Опять же уклоняемся от темы. Чувствую что вообще зря её создал, ибо на следующей недели появится дебаггер, а толку от него, как показывают ответы, намного больше.
|
|
|
|
|
May 14 2010, 20:14
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Dzhesertep @ May 14 2010, 23:31)  А на деле открываем дизассемблер и видим так можно многое понять совершенно превратно... Цитата Опять же уклоняемся от темы. Ничуть. Вы выкиньте всё лишнее из вашей программы и "откройте дизассемблер" - 10 минут делов на поиски пустяковой ошибки. А тут уже целый день народ вам даёт дельные советы, а в ответ слышим что так и задумано, так и хорошо, мне так надо. Цитата Чувствую что вообще зря её создал... С таким умением слушать точно зря. Цитата ибо на следующей недели появится дебаггер, а толку от него, как показывают ответы, намного больше. Ни разу в жизни не испытывал надобности во внутрисхемной отладке программ для AVR. Этак лет около 10 назад дебажил асмовые проекты в эмуляторе на avr-студи, сейчас вообще об этом и не вспоминаю...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|