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

 
 
 
Reply to this topicStart new topic
> Оптимизатор кода в WinAVR, сплошное непонятство
Panych
сообщение Aug 21 2006, 13:31
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Никак не могу понять, почему это требуется?: код без оптимизации работает, с оптимизацией по параметру "s" - приходится вставлять строки 170, 211 и 300.
Как они влияют на работу?
Смотрел листинг ассемблера - вроде ничего не меняется с их использованием, но ведь начинает работать!

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


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 21 2006, 13:48
Сообщение #2


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Эта.. А что у Вас не работает-то?

Цитата
Как они влияют на работу?

На первый взгляд их влияние - задержка на ~20-30 тактов между записью в порт и считыванием..

вероятно там будет достаточно одного _NOP в строках 211 и 300.
В 170 задержка скорее всего не нужна.

Сообщение отредактировал defunct - Aug 21 2006, 13:51
Go to the top of the page
 
+Quote Post
Panych
сообщение Aug 21 2006, 14:04
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Цитата(defunct @ Aug 21 2006, 17:48) *
Эта.. А что у Вас не работает-то?

индикатор должен писать код кнопки... так вот без строк 170 и 211 кнопка не считывается ( smile.gif да, смешно, но разными подстановками в программе именно это и вырисовывается smile.gif ), а без 300-й - не выводится на экран, хотя и считывается, причем вместо 300 можно подставить вызов любой другой функции, а вот подстановка NOP ничего не дает smile.gif

еще один прикол - при перестановке строк 169 и 170 порт так же не считывается, хотя и при этом ассемблерный код меняется адекватно - просто переставляются команды...

да, стоит WinAVR-20060421

Сообщение отредактировал Panych - Aug 21 2006, 14:05


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
Tiro
сообщение Aug 21 2006, 14:08
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



Есть две особенности, по-видимому, вами не учтенные :
1) ввод и вывод в АВР имеют встроенные синхронизаторы, что требует задержки в один такт перед считыванием пина _после изменения состояния соответствующего вывода_ (в дейташите раздел I/O-Ports -> Introduction)
2) любые _внешние по отношению к обработчику прерывания_ переменные, модифицируемые в прерывании (и в вызываемых из обработчика функциях), должны иметь модификатор volatile, чтобы запретить компилятору оптимизацию при работе с ними. Это не особенность WinAVR, а общее правило использования оптимизирующих компиляторов при написании обработчиков прерываний.

С уважением.

Сообщение отредактировал Tiro - Aug 21 2006, 14:12
Go to the top of the page
 
+Quote Post
Panych
сообщение Aug 21 2006, 14:20
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Цитата(Tiro @ Aug 21 2006, 18:08) *
1) ввод и вывод в АВР имеют встроенные синхронизаторы, что требует задержки в один такт перед считыванием пина _после изменения состояния соответствующего вывода_ (в дейташите раздел I/O-Ports -> Introduction)

так я вроде учел... непонятно, как на это может влиять перемена строк 169 и 170...
Цитата(Tiro @ Aug 21 2006, 18:08) *
2) любые _внешние по отношению к обработчику прерывания_ переменные, модифицируемые в прерывании (и в вызываемых из обработчика функциях), должны иметь модификатор volatile, чтобы запретить компилятору оптимизацию при работе с ними. Это не особенность WinAVR, а общее правило использования оптимизирующих компиляторов при написании обработчиков прерываний.

имеется в виду, что все дело в перегруженности прерываний?
надо строго в прерываниях выставлять флаги, обрабатываемые в основном теле программы, чтобы как можно более сократить тело прерываний и уменьшить количество и вложенность функций в них?


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
Tiro
сообщение Aug 21 2006, 14:44
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



1. Мне тоже непонятно, как влияет перестановка 169 и 170.
Зато понятно, как влияют друг на друга 172 и 173

169 DDRA = 0; // DATA_LCD_IO = 0;
170 NOP( 1 );
171 SETBIT( PORT_KN2, KN2 ); //включение
172 PORTB &= ~(1<<3);//CLEARBIT( PORT_KN1, KN1 ); //первого вывода
173 PORT_READ = PINA; // PORT_READ = READ_LCD; //считывание порта

которые скорее всего в ассемблере выглядят так
out portb, reg1
in reg2, porta
без задержки на такт, а она нужна.

2. Дело не в перегруженности прерываний, а в том, что компилятор может оптимизировать обращение к переменной, не объявленной как volatile

Пример:

int global_var;

ISR (vector)
{
global_var = 2;
}

int main (void)
{
for (;;)
{
global_var = 1;
// здесь произошло прерывание
if (global_var == 2)
{
printf ("Почему я не попал сюда? Надо использовать volatile");
}
}
}

Компилятор оптимизировал обращение к global_var в функции main и вообще удалил ветку с
if () как недостижимый код.

С уважением.

Сообщение отредактировал Tiro - Aug 21 2006, 14:59
Go to the top of the page
 
+Quote Post
Panych
сообщение Aug 21 2006, 14:52
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Цитата(Tiro @ Aug 21 2006, 18:44) *
Зато понятно, как влияют друг на друга 173 и 174

я понял мысль, но приложенная программа является рабочей...


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
Tiro
сообщение Aug 21 2006, 15:03
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



Извиняюсь.

Нажал табуляцию, потом еще что-то неглядя и все
отправилось.

А мы вообще об одних и тех же строках говорим? Какой микроконтроллер используется?

С уважением.
Go to the top of the page
 
+Quote Post
Panych
сообщение Aug 21 2006, 15:57
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Цитата(Tiro @ Aug 21 2006, 19:03) *
Нажал табуляцию, потом еще что-то неглядя и все
отправилось.

а я и смотрю сообщение рваное какое-то...
Цитата(Tiro @ Aug 21 2006, 19:03) *
А мы вообще об одних и тех же строках говорим? Какой микроконтроллер используется?

AtMega32...
и я говорил о строка текста программы по Programmer Notepad


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
Tiro
сообщение Aug 22 2006, 08:55
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



Переставил местами 169 и 170, откомпилировал с ключем -0s

Код

        void SCAN_KEY(void) {         //опрос кнопок
    161:            
    162:            uint8_t PORT_READ;     //временыый регистр для считанного из порта
    163:            
    164:            //настройка направлений портов    
    165:            SETBIT( DDR_KN1, KN1  ); //переводим выводы опроса
   \   01d6 BB9A              sbi 55-0x20,3
   166:            SETBIT( DDR_KN2, KN2 ); //кнопок на выход
   \   01d8 BC9A              sbi 55-0x20,4
    167:            SETBIT( PORT_KN2, KN2 );    //включение
   \   01da C49A              sbi 56-0x20,4
    168:            CLEARBIT( PORT_KN1, KN1 );    //первого вывода
   \   01dc C398              cbi 56-0x20,3
    169:            NOP( 1 );
   \   01de 81E0              ldi r24,lo8(1)
   \   01e0 0E94 0000         call NOP
    170:            DATA_LCD_IO = 0;
   \   01e4 1ABA              out 58-0x20,__zero_reg__
    171:            SETBIT( PORT_KN2, KN2 );    //включение
   \   01e6 C49A              sbi 56-0x20,4
   172:            CLEARBIT( PORT_KN1, KN1 );    //первого вывода
  \   01e8 C398              cbi 56-0x20,3
    173:            PORT_READ = READ_LCD;        //считывание порта
   \   01ea 89B3              in r24,57-0x20
    174:            if ( PORT_READ != 0xFF )
   \   01ec 8F3F              cpi r24,lo8(-1)
   \   01ee B1F1              breq .L49


Вот критичное место :

Код
172:            CLEARBIT( PORT_KN1, KN1 );    //первого вывода
  \   01e8 C398              cbi 56-0x20,3
    173:            PORT_READ = READ_LCD;        //считывание порта
   \   01ea 89B3              in r24,57-0x20


Однако, Вы утверждаете, что здесь все ОК, а влияет строка 169. Есть только одно предположение - сигналы у Вас вне микроконтроллера устанавливаются медленно,
и считываете вы значения, установленные в строках 167 и 168. Тогда 169 будет влиять, поскольку время установки сигналов будет определяться задержкой NOP.

Берите в руки осциллограф, пишите тестовую программу, например переключайте ножку в 1
и 0 поочередно и смотрите прохождение сигнала.

И объявите KEY так : volatile uint8_t KEY;

С уважением.
Go to the top of the page
 
+Quote Post
Laksus
сообщение Aug 23 2006, 22:04
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



А сюда смотрели? По моему похожая проблема.
AVR _ Странное поведение портов!
Автор: Sergio66 May 16 2006, 16:34
http://electronix.ru/forum/index.php?act=P...=10&t=16161
__________
Цитата
код без оптимизации работает, с оптимизацией по параметру "s" - приходится вставлять строки 170, 211 и 300. Как они влияют на работу?

Ну так на то она и оптимизация, быстрее получается.
Например переход со стр.171 (пины стали входами)
на стр.175 (читаем, что на этих пинах), (без NOP),
без оптимизации 12 тактов, с оптимизацией 5 тактов (в AVRStudio, чуть правленый код),
болше чем в 2 раза.
____
К проблеме не относится.Но.
Не надо при выходе из прерывания восстанавливать флаг I в SREG.
reti сама это сделает, даже в ассемблере.
А в Си, посмотрите листинг, SREG = 0b10000000;абсолютно бесполезна,
все равно SREG сохраняется при входе и восстановится при выходе.
_____
И еще, Вы уверены, что таймер1 у Вас выставлен правильно?
_________
Александр2006 08 24
Go to the top of the page
 
+Quote Post

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

 


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


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