WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Переходит не по очереди 357,358, 370 а в произвольном порядке. Как на дизасме все идет, а ни как в листинге Си. То есть очередность команд нарушается. Сначала присваивается значение переменной, потом идет (не известно почему) InvBit(test), потом возвращается назад и потом только по очереди.
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Код: Выделить всё

1) _rfid_i = 0x08;
do{
2)   _rfid_i--;
3)   _rfid_j = 0x08;

4)   _byte_key = *((unsigned char *)&_rfid_to_sent_array + _rfid_i - 1);

   do{
      _rfid_j--;

      if((_byte_key & 0x80) == 0x80)    {ClrBit(TEST); NOP;}
       else                    {SetBit(TEST); NOP;}
   
      InvBit(TEST);
      NOP;   

      _byte_key = _byte_key << 1;
   }
}


А получается что он делает:

Код: Выделить всё

1)_rfid_i = 0x08;
2) _rfid_j = 0x08;
3) InvBit(TEST);
4) _rfid_i--;
5) _rfid_j = 0x08;


А потом в начало на do{...} и потом все подряд уже идет - как надо.
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

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

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

Мой уютный бложик... заходите!
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Самое интересное, что с любой оптимизацией и "чистым" мейкфайлом ни чего не меняется. Проблема "уходит", когда из тела функции выкидываю все циклы и тогда все идет как надо. Вообще это функция выплевывания кода карточки EM-marine в порт... Простейшая вроде бы задача когда все готово и остается только вывести результат.... Но вот такой затык произошел...
Еще как вариант, возможно ли, что такое возникает от неправильного (ну или еще какого-то) определения и пользования указателей? Хотя тогда причем тут циклы?... Я в недоумении... :roll:

Ах да, Из-за этих "оптимизаций" компилятора половина кода на выдаче съедается.... Т.е. начинается обработка функции, код начинает скакать, но потом видимо попадает в нужное место и все идет пучком.

P.S. Запрещаю все прерывания на время выполнения функции..

Полностью со всеми используемыми переменными функция выглядит так:


Код: Выделить всё

   volatile unsigned char   _rfid_timer_owf   = 0x00;         //переполнение таймера произошло N -раз
    unsigned char   _byte_key = 0;                              //побайтное чтение из ключа
    unsigned char   _rfid_i = 0, _rfid_j = 0, _rfid_k = 0;      //глобальные счетчики


   #define _rfid_def_timer   0xFF00;                           //стартовое значение таймера до переполнения  16 us при 16 МГц
   #define Timer_CS      TCCR3B = _BV(CS30)                  //предделитель на 1 (start)
   #define Timer_Def      TCNT3 = _rfid_def_timer               //0xFFFF = ~30.02 us owerflow для freq = 7.3728 MHz
   #define Timer_TOIE_ON   TIMSK = _BV(TOIE3)            //разрешить прерывание по переполнению
   #define Timer_TOIE_OFF   TIMSK &= ~TOIE3         //запретить прерывание по переполнению
   #define Timer_Start      {Timer_Def; Timer_CS;_rfid_timer_owf = 0x00; NOP;}      //присваиваю начальное значение таймера, обнуляю счетчик переполнений таймера и пускаю таймер
   #define Timer_Stop      TCCR3B = 0x00               //предделитель на 0 (stop)

   #define _rfid_mod_time   ((_rfid_time[0] + _rfid_time[1]) >> 1)
   #define _rfid_white_delay    {while(_rfid_timer_owf < _rfid_mod_time){if(_rfid_timer_owf == _rfid_mod_time) _rfid_timer_owf = 0;}}


void EEPROM_Read_Long(unsigned int addr, unsigned char * new_value){
 i = 8;
 do{
    i--;
    *(new_value+i) = EEPROM_Read_Byte((unsigned int)(addr+i));
 }while(i > 0);
 NOP;
}



void RFID_Sent_Key(void){
 Timer_TOIE_OFF;               //запретить прерывание по переполнению
 cli();

 EEPROM_Read_Long((unsigned int)&_rfid_to_sent_EEPROM, (unsigned char *)&_rfid_to_sent_array);   //записываю адрес ключа в еепром

 sei();                     //разрешаю все прерывания
 Timer_TOIE_ON;               //разрешить прерывание по переполнению
 Timer_Start;                  //запускаю счетчик на переполнение

 _rfid_i = 0x08;

 do{
    _rfid_i--;
   _rfid_j = 0x08;

    _byte_key = *((unsigned char *)&_rfid_to_sent_array + _rfid_i - 1);

    do{
      _rfid_j--;

       if((_byte_key & 0x80) == 0x80)    {ClrBit(TEST); NOP;}
       else                    {SetBit(TEST); NOP;}
   
      _rfid_white_delay;
       
       InvBit(TEST);
      NOP;
       _rfid_white_delay;   

       _byte_key = _byte_key << 1;
    }while(_rfid_j > 0x00);
 }while(_rfid_i > 0x00);

 Timer_TOIE_OFF;               //запретить прерывание по переполнению
}




Сильно не бить если где накосячил, у меня глаз замылен совсем...
Последний раз редактировалось MOHOXPOM Вт июн 22, 2010 12:23:07, всего редактировалось 1 раз.
Как зачем мне голова?! Я ей ем!!!
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: WinAvr в вопросах и ответах

Сообщение a_skr »

лень вникать, но что сразу бросается в глаза:
...
#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
если прерывание единственное, то ничего страшного (надо TIMSK |= _BV(TOIE3))

#define Timer_TOIE_OFF TIMSK ^= _BV(TOIE3) //запретить прерывание по переполнению
не запретить а "проинвертировать"
надо: TIMSK &= ~_BV(TOIE3)
...


void RFID_Sent_Key(void){
получается, что здесь разрешаем...
Timer_TOIE_OFF; //запретить прерывание по переполнению
...
здесь опять разрешаем...
Timer_TOIE_ON; //разрешить прерывание по переполнению
...
здесь запрещаем
Timer_TOIE_OFF; //запретить прерывание по переполнению
}
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Ну вы правы прерывание не единственное, так что надо ^ делать. Отключение, включение а потом снова отключение из-за того, что тот же таймер работает на обработку приема кода. И тайминги новые заводить не было смысла.
Как зачем мне голова?! Я ей ем!!!
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: WinAvr в вопросах и ответах

Сообщение a_skr »

MOHOXPOM писал(а):Ну вы правы прерывание не единственное, так что надо ^ делать. Отключение, включение а потом снова отключение из-за того, что тот же таймер работает на обработку приема кода. И тайминги новые заводить не было смысла.


Ваш первый "вызов" макро Timer_TOIE_OFF как раз ВКЛЮЧАЕТ прерывание.

операция XOR, она-же "исключающее ИЛИ", т.е. оператор "^" в Си в данном случае просто меняет 0 на 1 и наоборот.
Если надо установить бит - пишем: <РЕГИСТР> |= <НУЖНЫЙ БИТ, СДВИНУТЫЙ КУДА НАДО>, т.е. по "ИЛИ", не "портя" остальные биты.
если надо сбросить бит - пишем: <РЕГИСТР> &= ~ <СДВИНУТЫЙ БИТ, КУДА НАДО>.
В Вашем примере, как я написал изначально, Timer_TOIE_OFF просто меняет разрешение на запрещение прерывания при каждом "вызове", и наоборот. т.е. в Вашем случае:

func(){
Timer_TOIE_OFF; // включили прерывание
Timer_TOIE_OFF; // выключили прерывание
Timer_TOIE_OFF; // включили прерывание
Timer_TOIE_OFF; // выключили прерывание
...
}

не путайте битовые ИЛИ - |, И - & и ИСКЛЮЧАЮЩЕЕ ИЛИ - ^.

еще вопрос: а зачем куча NOP'ов?
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Ну в принципе, я использую сначала ON и потом OFF. Так что один раз ставлю бит, а потом его инвертирую. А NOPы округляют задержку до 17.5 us при данном значении кварца и устаканивается значение в порту. Т.е. следующее действие при работе с портом хоть как сразу не даст его изменить. Ну примерно так:

default PB0 = 0

1) Set PB0 - NOP - Clr PB0
будет 0 - 1 - (держим такт) - 0

2) Set PB0 - Clr PB0
будет 0 - 1 - 0
и тут оптимизация пройдет... и PB0 останется без изменений, т.е. = 0
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Но проблема этим не решилась и решиться не могла...
Вопрос еще. Как организовать задержку в функции на несколько переполнений таймера? Может есть отточенное решение? А то я через while() делаю в теле функции, который сравнивает значение каунтера декрементируемого в обработчике прерывания по переполнению счетчика.
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

MOHOXPOM писал(а):2) Set PB0 - Clr PB0
будет 0 - 1 - 0
и тут оптимизация пройдет... и PB0 останется без изменений, т.е. = 0
не понял... вы хотите сказать, что участок кода

Код: Выделить всё

PORTB |= _BV(PB0);
PORTB &= ~_BV(PB0);
будет оптимизатором выброшен за ненадобностью и PB0 не изменит своего значения?
этого не может быть, т.к. PORTB определен в WinAVR как volatile, поэтому никогда не будет затронут оптимизатором.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: WinAvr в вопросах и ответах

Сообщение a_skr »

я все пытаюсь сказать, что нужно написать вот так:

Код: Выделить всё

#define Timer_TOIE_ON TIMSK  |= _BV(TOIE3); //разрешить прерывание по переполнению
#define Timer_TOIE_OFF TIMSK &= ~_BV(TOIE3); //запретить прерывание по переполнению

а не так, как в приведенном исходном тексте:

Код: Выделить всё

#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
#define Timer_TOIE_OFF TIMSK ^= _BV(TOIE3) //запретить прерывание по переполнению

а то получается, что Timer_TOIE_OFF первым вызовом РАЗРЕШАЕТ прерывание
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Да поменял уже говорю. В предыдущем посте описал.
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

ARV писал(а):не понял... вы хотите сказать, что участок кода


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

Код: Выделить всё

 DDRB = 0xFF; NOP;
 PORTB = 0xFF; NOP;
 PORTB = 0x00; NOP;
 PORTB = 0xFF; NOP;
 PORTB = 0x00; NOP;


Ну или

Код: Выделить всё

 DDRB = 0xFF;
 PORTB = 0xFF;
 PORTB = 0x00;
 PORTB = 0xFF;
 PORTB = 0x00;


Иногда возникают трудности без нопов. Попробуйте просимулировать оба варианта и посмотретьна состояния портов в обоих случаях. Я на этом запнулся когда опрос и выдачу с одного порта делал. Теперь я лучше такт пропущу, но то что хотел точно в порту будет.
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

уважаемый МОНОХРОМ! я не стану маяться ерундой, проверяя в симуляторе то, в чем уверен на 100% - не первый день работаю с WinAVR и никогда не сталкивался с тем, чтобы работа с портом искажалась оптимизатором или чем-либо еще! думаю, и никто не сталкивался с этим. на всякий случай, сообщите, какая версия WinAVR у вас? у меня 20100110, но и с тремя предыдущими никаких проблем не было!

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

Мой уютный бложик... заходите!
Аватара пользователя
MOHOXPOM
Встал на лапы
Сообщения: 108
Зарегистрирован: Вт мар 18, 2008 08:25:31
Откуда: Красноярск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение MOHOXPOM »

Вот! Спасибо за ответ. Попробую переписать по другому, так как и на выходе тоже не то что должно быть. Вернее не все :)
А на счет исполнения по портам я и не спрашивал :) Всем спасибо за ответы на мой бред :)
Как зачем мне голова?! Я ей ем!!!
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение YS »

Товарищи, прошу не сильно кидать в меня подручными предметами, но вопрос такой - как рассчитать время (в тактах), затрачиваемое на выполнение участка кода на С? Есть ли какие-нибудь данные относительно того, за сколько тактов выполняется, скажем, присваивание, вызов подпрограммы, и постоянны ли эти значения вообще? Или просто надо анализировать дизассемблированный листинг, и другого пути нет?
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

разумеется, кроме анализа ассемблерного листинга ничего не поможет :) кроме протеуса или другого отладчика :) только надо быть осторожным, т.к. точки останова не всегда ставятся в начале какого-то оператора :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Callous
Встал на лапы
Сообщения: 115
Зарегистрирован: Вс апр 20, 2008 16:54:13
Откуда: Украина, Чернигов

Re: WinAvr в вопросах и ответах

Сообщение Callous »

столкнулся я с такой загогулиной, программа измеряет 4 напряжения преобразует и выводит на 7-сегментный индикатор. в дебагере все работает так как надо. в протеусе когда симулируется то в переменной adc[] значения располагаются 3-0-1-2 а должны так 0-1-2-3 (номера-каналы АЦП), соответственно значения преобразуются не правильно и наиндикатор выводится ересь. Итак вопрос: это глюки протеуса и в железе все будет ОК или я налагал в проге. Критика программы очень уместна, так как мне кажется она написана через Ж, так что советы как написать ее компактней, оптимальней и просто красивее очень даже не помешают.

WinAVR-20090313.
Вложения
8.c
(2.42 КБ) 393 скачивания
Последний раз редактировалось Callous Пн июл 05, 2010 23:45:23, всего редактировалось 1 раз.
Аватара пользователя
Aheir
Модератор
Сообщения: 4517
Зарегистрирован: Пн апр 03, 2006 11:43:25
Откуда: Санкт - Петербург
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение Aheir »

Код - вложением! Правила читаем, нет? :evil:
Оптимизм х (Опыт + Знания) = const
Аватара пользователя
Callous
Встал на лапы
Сообщения: 115
Зарегистрирован: Вс апр 20, 2008 16:54:13
Откуда: Украина, Чернигов

Re: WinAvr в вопросах и ответах

Сообщение Callous »

ну где же многоуважаемый ARV???? :cry:
Ответить

Вернуться в «AVR»