Проблема с прерываниями в avr-gcc

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
ksv82
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Пт мар 18, 2011 12:41:09

Проблема с прерываниями в avr-gcc

Сообщение 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. Если перед выполнением этих команд запретить прерывания, то все работает нормально. Что с этим можно сделать?
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: Проблема с прерываниями в avr-gcc

Сообщение Мастер Ломастер »

ksv82 писал(а):динамическая индикация - в главном цикле
если я верно понял, то это ужас какой-то...

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

имхо, лучшим решением ваших проблем будет тщательное "причесывание" проекта, возможно, кардинальная переделка.
битва с дураками проиграна, победители торжествуют. слава победителям!
ksv82
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Пт мар 18, 2011 12:41:09

Re: Проблема с прерываниями в avr-gcc

Сообщение 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

Ну и работает соответственно без проблем.
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: Проблема с прерываниями в avr-gcc

Сообщение Мастер Ломастер »

я продолжаю настаивать на своем.

и с оптимизацией, и без компилятор генерирует 100% правильно работающий код, то, что вы его не понимаете, еще ни о чем не говорит. разумеется, неоптимизированный выполняется дольше, т.к. команд много, и при этом МЕЖДУ НИМИ могут возникать прерывания, которые ПОРТЯТ состояние порта ДО ТОГО, как этот многокомандный код закончит свои дела. включив оптимизацию, вы свели все к одной команде - это лишь частный случай вашего решения, проблема-то осталась: есть какое-то прерывание, которое тоже работает с портом. рано или поздно все повторится...
битва с дураками проиграна, победители торжествуют. слава победителям!
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Re: Проблема с прерываниями в avr-gcc

Сообщение IfoR »

ksv82 писал(а):Тут даже команд out или cbi я не наблюдаю... и как оно работает?

Зато я вижу ld и st. :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
ksv82
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Пт мар 18, 2011 12:41:09

Re: Проблема с прерываниями в avr-gcc

Сообщение 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 Пишем значение порта с измененным битом обратно ...  ну и иногда затираем то                что сделало прерывание:)
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»