|
IAR AVR - когда вредна оптимизация... |
|
|
|
Apr 29 2009, 16:46
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Вот, наткнулся на свои макросы... Хм, запрета прерывания нет, но работает... Ах, да... Я же WDT никогда не отключаю. Вот таким косвенным путем происходит обучение правильному использованию ресурсов контроллера Код #define WDT_OFF { __watchdog_reset(void); WDTCR |= (1<<WDTOE) | (1<<WDE); WDTCR=0; } #define WDT_ON { WDTCR=(1<<WDE);} #define WDT_RESET { __watchdog_reset(); }
--------------------
Уходя, оставьте свет...
|
|
|
|
|
May 5 2009, 12:01
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Цитата(tourist @ Apr 24 2009, 15:08)  При записи вида: Код WDTCSR |= (1 << WDCE) | (1 << WDE); Компилятор действительно генерит код не укладывающийся в 4 такта... Я решал проблему, описываемую автором темы, записью нужного числа непосредственно в регистр, типа того: Код WDTCSR |= 0x01; При этом (как ни странно) код получается нормальный, даже с полной оптимизацией, и число попадает в регистр без лишних тедлодвижений... ИМХО автор перемудрил с отключением оптимизации для функции... Вот именно, что все это очень странно. Насколько меня учили, порты в МК - это volatile-переменные, поэтому компилятор при оптимизации должен позаботиться о всех сторонних эффектах, если он претендует на совместимость со стандартом "С". Т.е. явное игнорирование разработчиками компилятора стандарта. Попросту говоря, баг. Или не так?
|
|
|
|
|
May 5 2009, 13:07
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Dir @ May 5 2009, 15:21)  но, по памяти, стандарт прямо запрещает оптимизацию ДАЖЕ по времени, если в этом принимают участие volatile-переменные. Освежите. В стандарте нет ни слова о времени. Компилятор обязан выполнить все указанные в программе обращения (на чтения и запись) к volatile-переменным и не имеет права нарушить их последовательность. Все. НА этом обязанности компилятора заканчиваются. Цитата(Dir @ May 5 2009, 15:21)  А тут работу препроцессора взял на себя компилятор и оптимизировал как хотел... Компилятор НЕ ИМЕЛ ПРАВА на такие вольности. Где оптимизация? Где работа препроцессора? Где вольности в конце концов? Компилятор сделал чтение-наложение маски-запись. Все как заказывали. С точки зрения стандарта никаких нарушений.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 5 2009, 14:12
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Цитата(Сергей Борщ @ May 5 2009, 16:07)  Освежите. В стандарте нет ни слова о времени. Компилятор обязан выполнить все указанные в программе обращения (на чтения и запись) к volatile-переменным и не имеет права нарушить их последовательность. Все. НА этом обязанности компилятора заканчиваются.Где оптимизация? Где работа препроцессора? Где вольности в конце концов? Компилятор сделал чтение-наложение маски-запись. Все как заказывали. С точки зрения стандарта никаких нарушений. Тогда вообще ничего не понятно. Почему, как указывалось в http://electronix.ru/forum/index.php?showt...st&p=583723"Код WDTCSR |= (1 << WDCE) | (1 << WDE); Компилятор действительно генерит код не укладывающийся в 4 такта... Я решал проблему, описываемую автором темы, записью нужного числа непосредственно в регистр, типа того: Код WDTCSR |= 0x01; При этом (как ни странно) код получается нормальный, даже с полной оптимизацией, и число попадает в регистр без лишних тедлодвижений..." Ведь после препроцессора компилятору попадает один и тот же код! Понятно, что препроцессор в стандарт не входит, но ведь получается, что "с точки зрения стандарта" компилятор вполне может разбить константное выражение и использовать его часть для своих оптимизационных ухищрений.
|
|
|
|
|
May 5 2009, 16:12
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Dir @ May 5 2009, 17:12)  Ведь после препроцессора компилятору попадает один и тот же код! Нет, разный. В одном случае установлен 1 бит, и компилятор генерит инструкцию sbi, во втором случае 2 бита, и иначе как через in, or, out не получится. А еще проще не использовать в этой конструкции "или" вообще - сразу писать нужное число. Потому что состояние остальных битов, как правило, известно заранее: Код WDTCR = (1<<WDCE)|(1<<WDE); WDTCR = (1<<WDP2)|(1<<WDP1);
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 5 2009, 17:57
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Цитата(Сергей Борщ @ May 5 2009, 19:12)  Нет, разный. В одном случае установлен 1 бит, и компилятор генерит инструкцию sbi, во втором случае 2 бита, и иначе как через in, or, out не получится. А еще проще не использовать в этой конструкции "или" вообще - сразу писать нужное число. Потому что состояние остальных битов, как правило, известно заранее: Код WDTCR = (1<<WDCE)|(1<<WDE); WDTCR = (1<<WDP2)|(1<<WDP1); Ну, я воспринял это просто как пример. Типа автору стало лень считать HEX-содержание своего кода.... и понесся обосновывать  А вот сейчас в спокойной обстановке дома решил исследовать что же на самом деле происходит и ... чешу затылок. Мне никак не удается при любых уровнях оптимизации и вообще без нее добиться того, чтобы компилятор по разному оттранслировал процедуру инициализации WDT. Т.е. вот такой код независимо от того стоит перед ним #pragma optimize=none или нет, написаны команды инициализации в виде команд препроцессору или в виде чисел (закоментарено) все равно транслируются одинаково. Код void test_WDT(void) { __watchdog_reset(); WDTCSR=(1<<WDCE)|(1<<WDE)|(1<<WDP0); WDTCSR=(1<<WDE)|(1<<WDP0); // WDTCSR=0x19; // WDTCSR=0x09; } ассемблерный код Код 7 __watchdog_reset(); \ 00000000 95A8 WDR 8 WDTCSR=(1<<WDCE)|(1<<WDE)|(1<<WDP0); \ 00000002 E109 LDI R16, 25 \ 00000004 93000060 STS 96, R16 9 WDTCSR=(1<<WDE)|(1<<WDP0); \ 00000008 E009 LDI R16, 9 \ 0000000A 93000060 STS 96, R16 Наверное поэтому никогда раньше не задумывался над этим вопросом, хотя по привычке всегда использовал #pragma optimize=none Может быть с оптимизацией таки можно заставить компилятор генерировать вызовы функций посредине двух WDTCSR = ..., но надо таки постараться не по детски  PS. Компилятор последний, 5.20, для примера взята mega48
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|