Страница 1 из 1
Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 10:47:33
ksv82
Есть проэктик на atmega32, где есть динамическая индикация - в главном цикле, и связь через rs-485. Все бы ничего, но для индикации используются два пина на порте D: pd3 и pd4. Для rs-485 требуется переключать направление передачи, что у меня делается через PD7. И вот тут появляются проблемы - команды в цикле динамической индикации
Код: Выделить всё
if((tmp_red & 1)==1)
PORTD |= (1<<PD3);
if((tmp_green & 1)==1)
PORTD |= (1<<PD4);
--задержка 20мс--
PORTD &= ~((1<<PD3) | (1<<PD4));
каким то образом устанавливают в 1 PD7. Если перед выполнением этих команд запретить прерывания, то все работает нормально. Что с этим можно сделать?
Re: Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 11:11:49
Мастер Ломастер
ksv82 писал(а):динамическая индикация - в главном цикле
если я верно понял, то это ужас какой-то...
ksv82 писал(а):Если перед выполнением этих команд запретить прерывания, то все работает нормально.
очевидно, что проблема не в этом куске кода, а в прерываниях: явно где-то в прерываниях происходит запись в
PORTD.
имхо, лучшим решением ваших проблем будет тщательное "причесывание" проекта, возможно, кардинальная переделка.
Re: Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 11:52:03
ksv82
Нет, проблема не в прерывании, тут все хитрее оказалось. Даже не ждал что удастся найти ответ так быстро.
При компиляции с ключем -O0 ассемблерный листинг выглядит вот так:
Код: Выделить всё
PORTD &= ~(1<<PD5)
9c: 82 e3 ldi r24, 0x32 ; 50
9e: 90 e0 ldi r25, 0x00 ; 0
a0: 22 e3 ldi r18, 0x32 ; 50
a2: 30 e0 ldi r19, 0x00 ; 0
a4: f9 01 movw r30, r18
a6: 20 81 ld r18, Z
a8: 2f 7d andi r18, 0xDF ; 223
aa: fc 01 movw r30, r24
ac: 20 83 st Z, r18
Тут даже команд out или cbi я не наблюдаю... и как оно работает?
Если пересобрать тот же код с ключем -Os, то все становиться гораздо интререснее:
Код: Выделить всё
PORTD &= ~(1<<PD5)
94: 95 98 cbi 0x12, 5 ; 18
Ну и работает соответственно без проблем.
Re: Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 12:16:16
Мастер Ломастер
я продолжаю настаивать на своем.
и с оптимизацией, и без компилятор генерирует 100% правильно работающий код, то, что вы его не понимаете, еще ни о чем не говорит. разумеется, неоптимизированный выполняется дольше, т.к. команд много, и при этом МЕЖДУ НИМИ могут возникать прерывания, которые ПОРТЯТ состояние порта ДО ТОГО, как этот многокомандный код закончит свои дела. включив оптимизацию, вы свели все к одной команде - это лишь частный случай вашего решения, проблема-то осталась: есть какое-то прерывание, которое тоже работает с портом. рано или поздно все повторится...
Re: Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 12:30:32
IfoR
ksv82 писал(а):
Тут даже команд out или cbi я не наблюдаю... и как оно работает?
Зато я вижу ld и st.

Re: Проблема с прерываниями в avr-gcc
Добавлено: Чт авг 11, 2011 12:42:21
ksv82
Тут ситуация маленько другая - с портом прерывание действительно работает, но в прерывании и в цыкле вывода индикации я меняю РАЗНЫЕ биты.
А с кодом компилятора я все таки разобрался:
Код: Выделить всё
9c: 82 e3 ldi r24, 0x32 ; 50
9e: 90 e0 ldi r25, 0x00 ; 0
a0: 22 e3 ldi r18, 0x32 ; 50 0x32 - адрес в памяти на который отражается порт D
a2: 30 e0 ldi r19, 0x00 ; 0
a4: f9 01 movw r30, r18 Загружаем в младшую половину регистра Z смещение на адрес порта в памяти
a6: 20 81 ld r18, Z Загружаем из порта D его значение
a8: 2f 7d andi r18, 0xDF ; 223 Изменяем нужный бит...
aa: fc 01 movw r30, r24 А вот тут как раз подходящее время для появления прерывания:))
Оно как раз с этим портом тоже работает.
ac: 20 83 st Z, r18 Пишем значение порта с измененным битом обратно ... ну и иногда затираем то что сделало прерывание:)