реклама на сайте
подробности

 
 
> tick_10=0; не обнуляет переменную
Dzhesertep
сообщение May 12 2010, 17:58
Сообщение #1





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Savrik
сообщение May 12 2010, 19:35
Сообщение #2


наблюдаю..
***

Группа: Свой
Сообщений: 291
Регистрация: 11-12-06
Из: Украина
Пользователь №: 23 369



так-так-так... tick_10 и Temporary глобальные переменные? а ну-ка код полностью в студиюsmile.gif

Сообщение отредактировал Savrik - May 12 2010, 19:36
Go to the top of the page
 
+Quote Post
Dzhesertep
сообщение May 12 2010, 20:20
Сообщение #3





Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222



Цитата(Savrik @ May 12 2010, 23:35) *
так-так-так... tick_10 и Temporary глобальные переменные? а ну-ка код полностью в студиюsmile.gif

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
Причина редактирования: Оформление цитаты исходника.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 13 2010, 13:22
Сообщение #4


неотягощённый злом
******

Группа: Свой
Сообщений: 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 где непоподя!!!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Dzhesertep
сообщение May 13 2010, 16:11
Сообщение #5





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
xemul
сообщение May 14 2010, 13:02
Сообщение #6



*****

Группа: Свой
Сообщений: 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]
Go to the top of the page
 
+Quote Post
Dzhesertep
сообщение May 14 2010, 19:31
Сообщение #7





Группа: Участник
Сообщений: 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.

Опять же уклоняемся от темы. Чувствую что вообще зря её создал, ибо на следующей недели появится дебаггер, а толку от него, как показывают ответы, намного больше.
Go to the top of the page
 
+Quote Post
rezident
сообщение May 14 2010, 20:15
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Dzhesertep @ May 15 2010, 01:31) *
В "букварях" обычно пишут что-то вроде "запрещает оптимизацию доступа". А на деле открываем дизассемблер и видим, что любая запись в переменную представляет собой просто прямое обращение к памяти посредством sts или st.
demiurg_spb вполне справедливо возразил вам. Типы переменных, под которые резервируется место в ОЗУ это глобальные и static. Переменные типа auto (локальные) образуются на стеке или в регистрах, как и тип register. Посмотрите раздел 6.7.1 Storage-class specifiers в стандарте C99 ISO/IEC 9899:1999. volatile это квалификатор типа, который не влияет на размещение переменной, но влияет на способ обращения к ней (запрещает "кэширование" значения).
Go to the top of the page
 
+Quote Post
Dzhesertep
сообщение May 14 2010, 20:57
Сообщение #9





Группа: Участник
Сообщений: 11
Регистрация: 12-05-10
Пользователь №: 57 222



Цитата(rezident @ May 15 2010, 00:15) *
demiurg_spb вполне справедливо возразил вам. Типы переменных, под которые резервируется место в ОЗУ это глобальные и static. Переменные типа auto (локальные) образуются на стеке или в регистрах, как и тип register. Посмотрите раздел 6.7.1 Storage-class specifiers в стандарте C99 ISO/IEC 9899:1999. volatile это квалификатор типа, который не влияет на размещение переменной, но влияет на способ обращения к ней (запрещает "кэширование" значения).

Это конечно так, но опять же, в данной ситуации это неважно, а точнее имеет место только постольку, поскольку ноль в такую переменную пишется командой из семейства st_ , которые берут и копируют регистр в память. Я, в данном случае, сказал только то, что видел в действиях компилятора. А компилятор при смене модификатора с auto на volatile запихнул её в память и стал использовать соответсвующие операции чтения/записи (естественно без кэширования доступа).

Кстати говоря, ещё никто не ткнул меня носом в конкретную функцию и не сказал:"Она ТАК НЕ может работать!". Учитывая, что все самоделки делались под конкретные задачи, то никто им не отдаёт параметры, выходящие за пределы работоспособности. В случае my_itoa самое большое поступающее число-это 59, в случае my_ltoa - 300000. В таком виде они (по коду) обязаны работать правильно.

Ключевой вопрос-как можно испортить регистр, ничего не делая с ним напрямую?

Сообщение отредактировал Dzhesertep - May 14 2010, 21:00
Go to the top of the page
 
+Quote Post
rezident
сообщение May 14 2010, 21:01
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Dzhesertep @ May 15 2010, 02:50) *
А компилятор при смене модификатора с auto на volatile запихнул её в память
Вот только память эта стековая видимо. laughing.gif
По сути вашей программы. Не следует в прерывании вычислять дату. В прерывании нужно только инкрементировать переменную миллисекунд на величину тика, выраженного в этих же миллисекундах. А дату вычислять нужно только при необходимости. Так гораздо проще и хранить, и корректировать, и обрабатывать дату/время. Потому, что обеспечить атомарность доступа одной переменной проще, чем целой группы переменных.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Dzhesertep   tick_10=0; не обнуляет переменную   May 12 2010, 17:58
- - SysRq   Цитата(Dzhesertep @ May 12 2010, 21:58) ....   May 12 2010, 18:34
|- - Dzhesertep   Цитата(SysRq @ May 12 2010, 22:34) А как ...   May 12 2010, 19:02
- - SasaVitebsk   Цитата(Dzhesertep @ May 12 2010, 20:58) П...   May 12 2010, 19:33
|- - demiurg_spb   Цитата(Dzhesertep @ May 13 2010, 20:11) Н...   May 14 2010, 09:19
||- - Dzhesertep   Цитата(demiurg_spb @ May 14 2010, 13:19) ...   May 14 2010, 13:43
||- - demiurg_spb   Цитата(Dzhesertep @ May 14 2010, 17:43) P...   May 14 2010, 16:16
|- - demiurg_spb   Цитата(Dzhesertep @ May 14 2010, 23:31) А...   May 14 2010, 20:14
|- - Dzhesertep   Цитата(rezident @ May 15 2010, 01:01) Вот...   May 14 2010, 21:14
|- - rezident   Цитата(Dzhesertep @ May 15 2010, 03:14) З...   May 14 2010, 21:29
- - SysRq   Цитата(Dzhesertep @ May 12 2010, 23:02) К...   May 13 2010, 16:02
- - Dzhesertep   Ну вот так сложилось, что на уарт строчку надо ото...   May 14 2010, 22:20
- - demiurg_spb   Цитата(Dzhesertep @ May 15 2010, 01:14) Н...   May 15 2010, 07:59
- - Dzhesertep   Цитата(demiurg_spb @ May 15 2010, 11:59) ...   May 15 2010, 09:09
- - Dzhesertep   Всё, тему можно закрывать, нашлась именно ошибка, ...   May 15 2010, 14:16


Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 22:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016