реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Проблема с прерываниями в Xmega
Kantik
сообщение Jun 14 2010, 19:40
Сообщение #1





Группа: Участник
Сообщений: 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 блокирует возникновение этого перывания в дальнейшем. Возможно ли обойти данную проблему?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jun 14 2010, 19:55
Сообщение #2


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Kantik @ Jun 14 2010, 23:40) *
возникает прерывание по переполнению счетчика TCC1, соответ. переход в подпрограмму обработки этого прерывания, подпрограмма выполняется, а вот выход должен быть нештатным, т.е. не по команде reti, а переход по команде rjmp.
Поделитесь, зачем такой хак используете?
Без этого никак что-ли не обойтись?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Kantik
сообщение Jun 14 2010, 20:09
Сообщение #3





Группа: Участник
Сообщений: 4
Регистрация: 18-11-09
Пользователь №: 53 726



Цитата(demiurg_spb @ Jun 14 2010, 23:55) *
Поделитесь, зачем такой хак используете?
Без этого никак что-ли не обойтись?

Программа обрабатывает сигналы от внешней микросхемы, при этом алгоритм достаточно сложный (например прием сигналов от беспроводного модуля), одновременно необходимо контролировать окно ожидания прихода пакетов и в случае переполнеия окна выполнять некоторые действия по завершению процесса приема и переход в другую ветку. Конечно можно контролировать флаг переполнения вручную , но это неудобно. Как то так.

Цитата(Kantik @ Jun 15 2010, 00:01) *
Программа обрабатывает сигналы от внешней микросхемы, при этом алгоритм достаточно сложный (например прием сигналов от беспроводного модуля), одновременно необходимо контролировать окно ожидания прихода пакетов и в случае переполнеия окна выполнять некоторые действия по завершению процесса приема и переход в другую ветку. Конечно можно контролировать флаг переполнения вручную , но это неудобно. Как то так.

На самом деле проблема не в алгоритме, его можно модернизировать. Непонятна новая логика работы с прерываниями, получается все стало значительно менее гибко? А вот работа с Event system наоборот очень понравилась.
Go to the top of the page
 
+Quote Post
Duhas
сообщение Jun 14 2010, 20:30
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 227
Регистрация: 13-04-07
Пользователь №: 27 018



а выставить в прерывании флаг, а потом его обработать не пробовали?

вы по сути рвете программу на части.. она вам такой подход однажды не простит...
Go to the top of the page
 
+Quote Post
V_G
сообщение Jun 15 2010, 07:03
Сообщение #5


Профессионал
*****

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



Только что решил аналогичную проблему. Без reti не обойтись, флаг обработки прерывания заданного уровня в PMIC никак не сбрасывается, только через reti. А если флаг не сброшен, система может войти только в прерывание более высокого уровня. Проверено на эмуляторе.

На самом деле это нормально, разработчики xmega проповедуют более строгий подход к программированию, что в конечном итоге даст более надежный код. Так что модифицируйте алгоритм.
Лично я в проблемном прерывании выставляю флаг по его приходу, а обработку выставленного флага сосредотачиваю в основном цикле, вне прерываний. Внутри обработчиков - только критичные ко времени куски.

ЗЫ. Но если хочется обмануть систему, можно засунуть в стек требуемый адрес возврата, а потом выполнить reti. Однако со стеком шутки плохи.

Сообщение отредактировал V_G - Jun 15 2010, 07:14
Go to the top of the page
 
+Quote Post
element
сообщение Sep 18 2011, 16:50
Сообщение #6





Группа: Новичок
Сообщений: 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
Go to the top of the page
 
+Quote Post
zombi
сообщение Sep 18 2011, 20:48
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(element @ Sep 18 2011, 19:50) *
выяснилось:
код, не являющийся обработчиком прерывания
CLI
RETI
поднимает бит I
код
RETI
в обработчике прерывания НИКАК не влияет на I-бит.

...
Т.е. для выхода из обработчика прерывания не достаточно одной команды RETI ? надо еще и SEI перед ним лепить?

Шо то слабо верится в такой баг laughing.gif

Сообщение отредактировал IgorKossak - Sep 20 2011, 10:47
Причина редактирования: Ненужные эмоции
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 19 2011, 01:53
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(zombi @ Sep 18 2011, 23:48) *
...
Т.е. для выхода из обработчика прерывания не достаточно одной команды RETI ? надо еще и SEI перед ним лепить?

Шо то слабо верится в такой баг laughing.gif


Нет такого бага...
В xmega бит I не сбрасывается при переходе на вектор прерывания, а запрещаются прерывания с более низким уровнем или равным уровнем.

Не надо лепить...

Сообщение отредактировал IgorKossak - Sep 20 2011, 10:47
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 19 2011, 04:38
Сообщение #9


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(element @ Sep 18 2011, 20:50) *
В общем, проблема решилась просто: добавил команду SEI перед RETI.
Не в ассемблерной вставке на обычной меге это бы кончилось плачевно. Т.к. производить раскрутку стека (модифицировать SPL+SPH) надо атомарно.
На Xmega это решено видимо как-то иначе?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Navovvol
сообщение Sep 20 2011, 05:34
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080



Вы где нашли таблицу векторов прерываний? всё излазил, ну нигде нет.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Sep 20 2011, 05:53
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Navovvol @ Sep 20 2011, 09:34) *
Вы где нашли таблицу векторов прерываний? всё излазил, ну нигде нет.

В разделе "PMIC - Programmable Multi-level Interrupt Controller"
Go to the top of the page
 
+Quote Post
Navovvol
сообщение Sep 20 2011, 06:27
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080



Цитата(Navovvol @ Sep 20 2011, 09:34) *
Вы где нашли таблицу векторов прерываний? всё излазил, ну нигде нет.

ААА... всё нашел.

Цитата(Палыч @ Sep 20 2011, 09:53) *
В разделе "PMIC - Programmable Multi-level Interrupt Controller"

Какая то странная теперь таблица векторов 0_о
Это теперь для каждого прерывания добавлять смещение к адресу модуля ? Мда... это ппц самому всё прописывать, а если учитывать объем, то допустить ошибку в расчетах адреса проще простого.
Go to the top of the page
 
+Quote Post
V_G
сообщение Sep 20 2011, 07:17
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Navovvol
сообщение Sep 20 2011, 07:55
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 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
......

стандартными инклудами вообще не пользовался.... Я хз как надо и лучше, но так точно работает.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Sep 20 2011, 08:11
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



QUOTE (Navovvol @ Sep 20 2011, 11:55) *
Похоже, что я как то не рационально организовываю таблицу векторов на асме. Копирую таблицу из даташита, чуть-чуть редактирую и получается пример:
.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
......

стандартными инклудами вообще не пользовался.... Я хз как надо и лучше, но так точно работает.

Вы знаете зачем перед вектором прерывания стоит .org ? И что она делает?


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th June 2025 - 02:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016