|
Проблема с прерываниями в Xmega |
|
|
|
Jun 14 2010, 19:40
|
Группа: Участник
Сообщений: 4
Регистрация: 18-11-09
Пользователь №: 53 726

|
Добрый день уважаемые форумчане. В данный момент активно активно разбираюсь с ATXmega 128A1. Суть проблемы. По ходу выполнения программы возникает прерывание по переполнению счетчика TCC1, соответ. переход в подпрограмму обработки этого прерывания, подпрограмма выполняется, а вот выход должен быть нештатным, т.е. не по команде reti, а переход по команде rjmp. Ранее, при работе с обычными мегами, вначале выполнения программы сохранял во временном рег. адрес указателя стека, разрешал прерывание по переполению, глобал. прерывания и т.д. Перед завершением подпрограммы обработки прерывания очишал флаг прерывания по переполнению счетчика, восстанавливал бит I в SREG и затем восстанавливал адрес указателя стека в рег. SPH/SPL и выполнял команду rjmp. Теперь о проблеме с XMega. Кроме разрешения прерывания по переполнеию выставляется так же уровень в регистре TCC1_INTCTRLA (например высокий), разрешение прерывание высокого уровня в регистре PMIC_CTRL, разрешаются глобальные прерывания в SREG. при возникновении прерывания возникает флаг в регистре PMIC_STATUS. Судя по описанию биты в данном регистре очишаются только при выполнении команды reti. Не очишенный флаг в регистре PMIC_STATUS блокирует возникновение этого перывания в дальнейшем. Возможно ли обойти данную проблему?
|
|
|
|
|
Jun 14 2010, 20:09
|
Группа: Участник
Сообщений: 4
Регистрация: 18-11-09
Пользователь №: 53 726

|
Цитата(demiurg_spb @ Jun 14 2010, 23:55)  Поделитесь, зачем такой хак используете? Без этого никак что-ли не обойтись? Программа обрабатывает сигналы от внешней микросхемы, при этом алгоритм достаточно сложный (например прием сигналов от беспроводного модуля), одновременно необходимо контролировать окно ожидания прихода пакетов и в случае переполнеия окна выполнять некоторые действия по завершению процесса приема и переход в другую ветку. Конечно можно контролировать флаг переполнения вручную , но это неудобно. Как то так. Цитата(Kantik @ Jun 15 2010, 00:01)  Программа обрабатывает сигналы от внешней микросхемы, при этом алгоритм достаточно сложный (например прием сигналов от беспроводного модуля), одновременно необходимо контролировать окно ожидания прихода пакетов и в случае переполнеия окна выполнять некоторые действия по завершению процесса приема и переход в другую ветку. Конечно можно контролировать флаг переполнения вручную , но это неудобно. Как то так. На самом деле проблема не в алгоритме, его можно модернизировать. Непонятна новая логика работы с прерываниями, получается все стало значительно менее гибко? А вот работа с Event system наоборот очень понравилась.
|
|
|
|
|
Jun 15 2010, 07:03
|

Профессионал
    
Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955

|
Только что решил аналогичную проблему. Без reti не обойтись, флаг обработки прерывания заданного уровня в PMIC никак не сбрасывается, только через reti. А если флаг не сброшен, система может войти только в прерывание более высокого уровня. Проверено на эмуляторе.
На самом деле это нормально, разработчики xmega проповедуют более строгий подход к программированию, что в конечном итоге даст более надежный код. Так что модифицируйте алгоритм. Лично я в проблемном прерывании выставляю флаг по его приходу, а обработку выставленного флага сосредотачиваю в основном цикле, вне прерываний. Внутри обработчиков - только критичные ко времени куски.
ЗЫ. Но если хочется обмануть систему, можно засунуть в стек требуемый адрес возврата, а потом выполнить reti. Однако со стеком шутки плохи.
Сообщение отредактировал V_G - Jun 15 2010, 07:14
|
|
|
|
|
Sep 18 2011, 16:50
|
Группа: Новичок
Сообщений: 8
Регистрация: 23-01-09
Пользователь №: 43 859

|
Добрый день. Аналогичная проблема возникла при адаптации многозадачной ОС для XMega. На обычных мегах операционка живёт уже десяток лет, но при запуске на XMeg-е отказалась работать. Работа системы в следующем: по прерываю таймера обработчик переключает задачи - сохраняет/восстанавливает регистры, стек, точки возврата и (ЭТО ВАЖНО!) регистр флагов SREG. При инициализации системы ячейки контекста задач, хранящие SREG неопределённые (как правило нулевые после сброса) - и это в принципе не важно, т.к. в процессе работы задачи флаги меняются - потом сохраняются и т.д. Выход из диспетчера задач (обработчика прерывания таймера) всегда завершается командой RETI, - т.е. I-бит в SREG поднимается - прерывания разрешаются. Что получилось в XMeg-е: При выходе из прерывания RETI не поднимал I-бит, прерывания оказались выключенными, ОС зависала на одной задаче. При детальном изучении поведения I бита и команды RETI выяснилось: код, не являющийся обработчиком прерывания CLI RETI поднимает бит I код RETI в обработчике прерывания НИКАК не влияет на I-бит. В общем, проблема решилась просто: добавил команду SEI перед RETI. Вывод: поведение RETI зависит от текущего состояния PMIC. Никакого волшебства. Однако, в атмел можно кинуть камень, за НЕОПИСАНИЕ такого поведения команды RETI в своих даташитах.
Сообщение отредактировал element - Sep 18 2011, 16:51
|
|
|
|
|
Sep 19 2011, 01:53
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(zombi @ Sep 18 2011, 23:48)  ... Т.е. для выхода из обработчика прерывания не достаточно одной команды RETI ? надо еще и SEI перед ним лепить? Шо то слабо верится в такой баг  Нет такого бага... В xmega бит I не сбрасывается при переходе на вектор прерывания, а запрещаются прерывания с более низким уровнем или равным уровнем. Не надо лепить...
Сообщение отредактировал IgorKossak - Sep 20 2011, 10:47
|
|
|
|
|
Sep 20 2011, 06:27
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080

|
Цитата(Navovvol @ Sep 20 2011, 09:34)  Вы где нашли таблицу векторов прерываний? всё излазил, ну нигде нет. ААА... всё нашел. Цитата(Палыч @ Sep 20 2011, 09:53)  В разделе "PMIC - Programmable Multi-level Interrupt Controller" Какая то странная теперь таблица векторов 0_о Это теперь для каждого прерывания добавлять смещение к адресу модуля ? Мда... это ппц самому всё прописывать, а если учитывать объем, то допустить ошибку в расчетах адреса проще простого.
|
|
|
|
|
Sep 20 2011, 07:17
|

Профессионал
    
Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955

|
Цитата(demiurg_spb @ Sep 19 2011, 15:38)  Цитата В общем, проблема решилась просто: добавил команду SEI перед RETI. Не в ассемблерной вставке на обычной меге это бы кончилось плачевно. Т.к. производить раскрутку стека (модифицировать SPL+SPH) надо атомарно. На Xmega это решено видимо как-то иначе? Написали же, xmegа в прерываниях не сбрасывает флаг I, и рецепт "добавил команду SEI перед RETI" не есть правильный. Случайно заработало, в следующий раз при аналогичной проблеме не заработает. Ни в mege, ни в xmege не стоит лишний раз дергать флаг I, тем более в прерываниях. У xmegи вообще трехуровневая система прерываний, и надо очень грамотно расставлять их изначальные приоритеты, не дергая I. Цитата(Navovvol @ Sep 20 2011, 17:27)  Это теперь для каждого прерывания добавлять смещение к адресу модуля ? Мда... это ппц самому всё прописывать, а если учитывать объем, то допустить ошибку в расчетах адреса проще простого. Что Вы имеете в виду? Адреса прерываний по-прежнему фиксированы, никаких проблем в ассемблере не встретил. Откройте из Студии (у меня 4 версия) файл ATxmega32A4def.inc (или другой под нужный проц), и в разделе "INTERRUPT VECTORS, ABSOLUTE ADDRESSES" увидите их все. Можно, конечно, добавлять смещение к базовому адресу модуля (в том же файле ниже), но я для себя пока такой необходимости не увидел
Сообщение отредактировал V_G - Sep 20 2011, 10:17
|
|
|
|
|
Sep 20 2011, 07:55
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080

|
Цитата(V_G @ Sep 20 2011, 11:17)  Что Вы имеете в виду? Адреса прерываний по-прежнему фиксированы, никаких проблем в ассемблере не встретил. Откройте из Студии (у меня 4 версия) файл ATxmega32A4def.inc (или другой под нужный проц), и в разделе "INTERRUPT VECTORS, ABSOLUTE ADDRESSES" увидите их все. Можно, конечно, добавлять смещение к базовому адресу модуля (в том же файле ниже), но я для себя пока такой необходимости не увидел Похоже, что я как то не рационально организовываю таблицу векторов на асме. Копирую таблицу из даташита, чуть-чуть редактирую и получается пример: .org $0000 rjmp RESET ; Переход на обработку сброса .org $0002 reti//jmp OSCF_INT_vect //Crystal Oscillator Failure Interrupt vector (NMI) .org $0004 reti//jmp PORTC_INT_base //Port C Interrupt base .org $0008 reti//jmp PORTR_INT_base //Port R Interrupt base .org $000C reti//jmp DMA_INT_base //DMA Controller Interrupt ............. Так вот, о смещении: у порта С два прерывания INT0 и INT1, значит: .org $0004 reti//jmp PORTC_INT0_vect // смещение 0х00 .org $0006 reti//jmp PORTC_INT1_vect// смещение 0х02 .org $0008 reti//jmp PORTR_INT_base //Port R Interrupt base ...... стандартными инклудами вообще не пользовался.... Я хз как надо и лучше, но так точно работает.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|