| Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
15.07.2010, 11:50
|
|
|
Заблокирован
Регистрация: 26.12.2009
Сообщений: 3,102
Сказал спасибо: 113
Сказали Спасибо 860 раз(а) в 610 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
Я в данном случае про WinAVR
Есть задача - получить готовую программу, выполняющую конкретные действия в конкретные временные рамки. При работе с CVAVR время тратится в основном на алгоритм работы программы, а не на изучение багов и особенностей компилятора при различных режимах оптимизации.
|
"Не хочу учиться, а хочу жениться."

"изучение багов и особенностей компилятора" неотъемлемая часть успешного программирования, как и чтение даташита и еррат, иначе весь ваш самовосхваляемый алгоритм - коту под хвост.
|
|
|
|
15.07.2010, 13:28
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от rear
|
не можно так делать, так как инт - для winavr - 16 битный тип.
нужно так:
register volatile unsigned char count asm("r4");
|
Смешно. Нам и НУЖНА 16 битная переменная. Так что косяка не было.
Сообщение от rear
|
вместо count = 0; в самом начале кода нужно написать
asm("clr r4"); Не могу сказать почему так, но иначе не работает.
|
Вот Вам кусочек листинга:
|
Код:
|
47: ACSR=0x80;
+00000047: E880 LDI R24,0x80 Load immediate
+00000048: B988 OUT 0x08,R24 Out to I/O location
49: count = 0;
+00000049: 2444 CLR R4 Clear Register
+0000004A: 2455 CLR R5 Clear Register |
Компилятор сам прекрасно справляется и костыли ему не нужны.
Сообщение от rear
|
|
и переменная count никуда не денется.
|
Вы свои листинги сами то смотрели?
|
Код:
|
main:
out $18, R1
out $17, R1
out $12, R1
ldi R24, $01
out $11, R24
clr R4
ldi R19, $00
ldi R18, $00
ldi R20, $01
l_001b:
out $12, R20
in R24, $16
mov R25, R24
andi R25, $10
lsr R24
andi R24, $10
cp R25, R19
breq l_0025
cp R25, R24
mov R19, R25
l_0025:
cp R24, R18
breq l_0029
cp R25, R24
mov R18, R24
l_0029:
out $12, R1
rjmp l_001b
l_002b:
cli
l_002c:
rjmp l_002c |
Это из opt_size.asm
Ну и где тут увеличение count? Вообще кроме clr R4 обращений к этому регистру больше нет! Ни на какие мысли не наводит?
|
|
|
|
15.07.2010, 14:58
|
|
|
Вид на жительство
Регистрация: 30.12.2006
Адрес: Junktown
Сообщений: 300
Сказал спасибо: 160
Сказали Спасибо 171 раз(а) в 59 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
да, здесь я лажанулся...
попробовал перекомпилировать на WinAVR 20060421, и компилятор выдал следующее предупреждение на строчку
register volatile unsigned int count asm("r4");
* enc1.c, line 6: warning: volatile register variables don't work as you might wish
можете пояснить, почему?
__________________
Всегда стремись к недоступному
|
|
|
|
15.07.2010, 15:27
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от rear
|
|
можете пояснить, почему?
|
А это старая версия, там volatile и register были совсем не совместимы.
А дальше они стали не совсем совместимыми.  При ожидании события компилятор делает копию такой переменной и контролирует именно ее, хотя и оригинал в регистре. Это известный баг. Но в данной ситуации volatile только для того, чтоб компилятор совсем count не выбросил, так что проявляться он не должен никак. Будет время и желание поинтересуюсь на электрониксе, там один из разработчиков порта GCC под АВР бывает. Я вот пользуюсь одной версией уже пару лет и забот не знаю  И хоть в новых код немного короче, но как ни странно ничуть не быстрее. Скорее наоборот. Берите WinAvr20071221, там GCC4.2.2. У меня и под АРМ эта же версия.
Я оказывается не один такой осторожный  - http://electronix.ru/forum/index.php...dpost&p=713864
И вот от разработчика - http://electronix.ru/forum/index.php...dpost&p=424999
Почитайте эту ветку с начала до конца.
Вообще глобальные переменные в регистрах - зло  Но для программ уровня мигалки на светодиоде это приемлемо.
Описание бага - http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00657.html
Он так и не пофиксен.
Последний раз редактировалось kison; 15.07.2010 в 15:51.
|
|
|
|
Эти 2 пользователя(ей) сказали Спасибо kison за это сообщение:
|
|
|
21.07.2010, 21:43
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Это не совсем относится к оптимизации, но всё же...
МК - ATmega64. Два USART. Используется только один.
Итак:
В обработчике прерывания от таймера 1 ( СТС, 1 сек) данные отправляются по USART0.
Данные - это volatile char глобальная переменная. После отправки она увеличивается на 1. То есть, каждую секунду по USART0 отправляется: 1, 2, 3...
Также включено прерывание по приёму байта по USART0. В нём ничё криминального не делается, просто меняется значение другой глобальной переменной и всё.
Всё работает. Но как только в прерывании по приёму от USART0 разрешаешь глобально прерывания, то всё перестаёт работать (на выходе рандом, причём с большими задержками, гораздо дольше 1 сек и каждый раз через разное время)...
Ах да, это в WinAVR. Разрешение прерываний глобально в теле прерывания в CodeVision не нарушает работоспособности программы.
В нормальном режиме на USART приходят данные (1 байт) каждые 16 мс.
Но я закорачивал RXD USART0 и на GND и на +5V. Всё равно программа выдавала рандом.
Программа уже написана, но без sei() внутри прерываний. Если очень потребуется, придётся писать заново и пытаться воспроизвести ситуацию. Глупо спрашивать, не предоставляя исходник, но может есть какой секрет? Уровни оптимизации не влияют. То есть не работает при любой оптимизации.
|
|
|
|
21.07.2010, 21:59
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
Всё равно программа выдавала рандом.
|
Кто выдавал то? Где рандом - из компорта выплевывает что попало вместо 1,2,3?
Сообщение от Godzilla82
|
|
Но как только в прерывании по приёму от USART0 разрешаешь глобально прерывания, то всё перестаёт работать (на выходе рандом, причём с большими задержками, гораздо дольше 1 сек и каждый раз через разное время)...
|
А как разрешаются прерывания? Там целый механизм есть
|
Код:
|
ISR(vector,ISR_NOBLOCK)
{
} |
Если же просто тупо sei() в коде, то перед выходом из прерывания нужно сделать cli(). Там модифицируется стек, операция не атомарная, а компилятор считает что прерываний быть не может. Так что придется перед всеми return вставлять cli(). Ну и перед выходом по умолчанию так же.
|
|
|
|
21.07.2010, 22:05
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от kison
|
|
Кто выдавал то? Где рандом - из компорта выплевывает что попало вместо 1,2,3?
|
Да. Но смена значений происходила рандомно, могло через 10 сек, могло через секунду. В основном всего несколько значений, никак не связанных с переменной-счётчиком. Но выдавались по прерыванию. То есть, каждую секунду.
Со скоростью приёмника и передатчика всё в порядке. Смотрел на осциллографе. То есть, то, что выдавалось, соответсвовало осциллограмме.
Сообщение от kison
|
А как разрешаются прерывания?
...
Если же просто тупо sei() в коде
|
Да, просто тупо в коде...
Сообщение от kison
|
|
Так что придется перед всеми return вставлять cli(). Ну и перед выходом по умолчанию так же.
|
Большое спасибо, не знал... В предыдущем проекте тупо разрешал прерывания внутри таймеров. Всё работало как надо. И намёка на подвох не было...
Сообщение от kison
|
|
Там модифицируется стек, операция не атомарная, а компилятор считает что прерываний быть не может.
|
А каким образом cli() влияет на стек? Или это вправляет мозги компилятору?
Последний раз редактировалось Godzilla82; 21.07.2010 в 22:12.
|
|
|
|
22.07.2010, 00:50
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
А каким образом cli() влияет на стек? Или это вправляет мозги компилятору?
|
Самым прямым. Если в обработчике прерывания есть локальные переменные созданные не в регистре, а на стеке, то при входе в прерывание под них выделяется место. У GCC стек один - и для данных и для адресов возврата, так что резервирование места это модификация SPL:SPH - указателя стека. Это происходит в самом начале обработчика еще до того, как пользователь сможет разблокировать прерывания. Соответственно это безопасно. А вот при выходе стек надо вернуть в исходное состояние. Т.е. снова модифицировать указатель стека. Если вложенные прерывания не разрешались, то это опять же безопасно. А если разрешались, то операция становится неатомарной, ведь указатель - два байта. И если после изменения одного из них произойдет прерывание, то может быть что угодно - неверная работа программы, сброс всего девайса, зависание и т.д. Со стеком шутки плохи. Так что надо выходить из обработчиков при запрещенных прерываниях, тогда эпилог ( именно так называются неявные инструкции завершения в функциях, к которым и обработчик относится) будет выполняться безопасно. В обычных функциях компилятор при создании переменных на стеке сам вставляет критические секции.
В маленьких обработчиках обычно все переменные влезают в регистры и проблем не должно быть в любом случае. Вот только такие обработчики обычно не вызывают желания разрешить в них вложенные прерывания. Кстати этот прием приводит еще к перерасходу памяти. Если один обработчик требует 30 байт на стеке и второй 40, то при разрешении вложенности они иногда будут занимать память одновременно - 70 байт. Немного? Иногда это всю работоспособность порушить может.
Последний раз редактировалось kison; 22.07.2010 в 00:58.
|
|
|
|
22.07.2010, 01:15
|
|
|
Гражданин KAZUS.RUN
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
И вообще, почитайте где-нибудь про атомарность доступа. Иногда это приводит к очень сложным ошибкам. Я, к примеру, узнал об этом при создании модема. Возникала ошибка, в среднем, одна на 20 мбайт передаваемых данных.  Как я замучился её ловить. Было это ещё на x51 и средств и форумов таких ещё не было.
Вкрадце - если размерность переменной превышает разрядность процессора, и она используется в голове и прерывании, то есть шанс вызова прерывания между модификацией одной части переременной и второй. А это может приводить к ошибкам.
|
|
|
|
22.07.2010, 01:45
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 30.06.2005
Сообщений: 3,392
Сказал спасибо: 5
Сказали Спасибо 429 раз(а) в 305 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от SasaVitebsk
|
И вообще, почитайте где-нибудь про атомарность доступа. Иногда это приводит к очень сложным ошибкам. Я, к примеру, узнал об этом при создании модема. Возникала ошибка, в среднем, одна на 20 мбайт передаваемых данных. Как я замучился её ловить. Было это ещё на x51 и средств и форумов таких ещё не было.
Вкрадце - если размерность переменной превышает разрядность процессора, и она используется в голове и прерывании, то есть шанс вызова прерывания между модификацией одной части переременной и второй. А это может приводить к ошибкам.
|
Собственно это ясно как божий день. Для этого либо прерывания запрещают либо работают с флагами и тд. В некоторых компиляторах даже варнинг соотвествующий есть.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 14:42.
|
|