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

 
 
> ARM7 от Atmel. Запрет прерываний., почему он заходит в Spurious Interrupt
Shein
сообщение Jun 8 2012, 14:17
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 45
Регистрация: 4-03-07
Пользователь №: 25 855



Доброго всем времени суток.
Столкнулся с таким явлением как вызов обработчика Spurious Interrupt.
Суть вопроса:
Работа с UART через контроллер PDC. Обрабатываются прерывания END_RX и END_TX. Используются два кольцевых буфера, т.е. прием или передача по PDC идет непрерывно. Фактически работа с индексами этих буферов идет и из прерываний, и из основной программы.
Логично, что когда я, например, читаю из приемного буфера, то при обращении к индексам, запрещаю прерывания по приему END_RX. Аналогично, при записи в передающий буфер, при обращении к индексам, запрещаются прерывания передатчика END_TX.
Столкнулся с тем, что при интенсивном обмене данными, программа иногда залетает в Spurious Interrupt. Согласно даташиту, это происходит, если контроллер AIC выдал запрос на прерывание ядру, но на момент чтения вектора обработчика, запрос на прерывание уже был снят.
В процессе отладки программы эта версия абсолютно подтвердилась. Вход в Spurious Interrupt происходит если запрос на прерывание контроллеру AIC пришел в момент обработки инструкции запрета прерывания от приемника или передатчика. Соответственно запрет отрабатывается, бит interrupt pending снимается, и когда ядро читает вектор обработчика из AIC, получается что прерывания-то уже нет.

Собственно вопрос: это нормальная ситуация? Раньше у меня стояла заглушка (бесконечный цикл) на Spurious Interrupt и на всех неиспользуемых векторах в AIC. Когда на Spurious Interrupt поставил обработчик в котором просто формируется подтверждение (запись в AIC_EOICR) программа, в общем стала нормально работать. Но вызовы Spurious таки иногда наблюдаются. Вот я и думаю, оставить как есть, еле же есть некий корректный механизм, как запрещать прерывание без возникновения данного эффекта?
P.S. В догонку: наблюдал это явление на двух процессорах AT91RM3400 и AT91SAM7X256. Картина абсолютно идентичная.

Сообщение отредактировал Shein - Jun 8 2012, 14:21
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 23)
aaarrr
сообщение Jun 8 2012, 14:50
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Shein @ Jun 8 2012, 18:17) *
Собственно вопрос: это нормальная ситуация? Раньше у меня стояла заглушка (бесконечный цикл) на Spurious Interrupt и на всех неиспользуемых векторах в AIC. Когда на Spurious Interrupt поставил обработчик в котором просто формируется подтверждение (запись в AIC_EOICR) программа, в общем стала нормально работать.

Нормальная ситуация. Как раз заглушка с бесконечным циклом на Spurious - это совершенно не нормально.
Go to the top of the page
 
+Quote Post
Lotor
сообщение Jun 9 2012, 06:55
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Эти прерывания типичны не только для атмелов, мне понравилась объяснение в этом документе от nxp - Handling of spurious interrupts in the LPC2000.


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2012, 06:56
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Shein @ Jun 8 2012, 20:17) *
Вот я и думаю, оставить как есть, еле же есть некий корректный механизм, как запрещать прерывание без возникновения данного эффекта?

Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс?
Go to the top of the page
 
+Quote Post
Aaron
сообщение Jun 9 2012, 09:29
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



Если я не ошибаюсь, там же можно два буфера для передачи задавать. Один заполнился - читаем и обрабатываем его спокойно, а второй тем временем заполняется. Зачем запрещать прерывания? Ну и, конечно, из Spurious выходить надо - это по-любому, у меня в одном проекте много блокировок возможно из-за вложенных прерываний, дак там это SPU - обычное явление.
Go to the top of the page
 
+Quote Post
Shein
сообщение Jun 10 2012, 13:46
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 45
Регистрация: 4-03-07
Пользователь №: 25 855



Народ, спасибо всем большое! sm.gif Вы развеяли мои сомнения. А то ведь я пытался с этим бороться, два дня убил. smile3046.gif
Цитата(jcxz @ Jun 9 2012, 09:56) *
Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс?

По сути, почти так и есть, только для всяких проверок (на наличие принятых данных, заполнение буфера) приходится обращаться к индексам, которые изменяются в ISR. Ну и, можно сказать, перестраховался.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jun 10 2012, 14:15
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



А если вот такая ситуация к примеру:
1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.
3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.
4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.
5. Фоновый процесс инкрементирует индекс и записывает его в память.

Как Вам ситуация? sm.gif

ИМХО, запрещать прерывание нужно обязательно перед записью в буфер.


--------------------
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 15:53
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(prottoss @ Jun 10 2012, 20:15) *
А если вот такая ситуация к примеру:
1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.
3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.
4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.
5. Фоновый процесс инкрементирует индекс и записывает его в память.

Как Вам ситуация? sm.gif

Зачем же делать такое кривое FIFO??? crying.gif
Цитата(prottoss @ Jun 10 2012, 20:15) *
ИМХО, запрещать прерывание нужно обязательно перед записью в буфер.

Если иметь прямые руки и писать FIFO правильно - не нужно! sm.gif
Обычная реализация FIFO для межпроцессного (и даже - межпроцессорного взаимодействия):
Два индекса (у каждого процесса свой).
Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать. Один процесс - только пишет в FIFO, другой - только читает.
Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO).
Минус такой реализации - реальная ёмкость FIFO на 1 элемент меньше выделенного для него буфера. Если элементы - байты - это ерунда.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jun 10 2012, 15:56
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(jcxz @ Jun 10 2012, 21:53) *
Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO).
Ага, вот тут то и упрется, когда один процесс изменит, другой тож


--------------------
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 16:02
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Читайте внимательнее:
Цитата(jcxz @ Jun 10 2012, 21:53) *

Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать.

Go to the top of the page
 
+Quote Post
prottoss
сообщение Jun 10 2012, 16:05
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(jcxz @ Jun 10 2012, 22:02) *
Читайте внимательнее:
Читайте внимательнее. Никто не запрещает одному индексу переехать через другой.


--------------------
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 16:07
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(jcxz @ Jun 10 2012, 21:53) *

Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO).

Go to the top of the page
 
+Quote Post
prottoss
сообщение Jun 10 2012, 16:16
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(jcxz @ Jun 10 2012, 22:07) *
Ваши красные буквы ни как меня не смущают sm.gif Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данных


--------------------
Go to the top of the page
 
+Quote Post
MaslovVG
сообщение Jun 10 2012, 16:17
Сообщение #14


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

Группа: Свой
Сообщений: 1 210
Регистрация: 24-01-05
Из: Россия Волгодонск
Пользователь №: 2 134



Цитата(prottoss @ Jun 10 2012, 18:15) *
А если вот такая ситуация к примеру:
1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.
3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.
4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.
5. Фоновый процесс инкрементирует индекс и записывает его в память.

Здесь вы описываете не FIFO (очередь) а а стек (последний вышол первый вышел). Почитайте Кнут "основные алгоритмы".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 16:22
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(prottoss @ Jun 10 2012, 22:16) *
Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данных
Зачем???? И какие данные "общие"?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jun 10 2012, 16:24
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(MaslovVG @ Jun 10 2012, 22:17) *
Здесь вы описываете не FIFO (очередь) а а стек (последний вышол первый вышел). Почитайте Кнут "основные алгоритмы".
Не имеет значения. пусть будут два индекса - на чтение и на запись. Смысл один - нужно разрулить доступ к данным


--------------------
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 16:32
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Разруливается это двумя индексами - у каждого процесса - свой.
Вот типичная реализация (проанализируйте методы read() и write()):
CODE
class clas {
volatile size_t rpos, wpos;
u8 buf[N + 1];
public:
size_t write(int);
int read();
clas() { rpos = wpos = 0; }
}
int clas::read() //если нет данных - возвращает отрицательное
{
int i;
size_t j = rpos;
if (i = j - wpos) {
i = buf[j] + 1;
rpos = ((j) ? j: ncell(buf)) - 1;
}
return i - 1;
}
size_t clas::write(int c) //если не удалось записать (буфер полон) возвращает != 0
{
size_t i, i1, i2;
if (!(i1 = i2 = wpos)) i1 = ncell(buf);
if (i = (--i1 - rpos)) {
buf[i2] = c;
wpos = i1;
}
return i;
}
#define ncell(m) (sizeof(m) / sizeof((m)[0]))
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 10 2012, 16:53
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Жарко у вас тут sm.gif

Действительно, запрещать прерывания совсем не обязательно, если есть только два индекса.
Сам долго пользовался подобной реализацией, но потом все же отказался - ущерб от кратковременного запрета прерываний мизерный, а вот незадействованный элемент FIFO раздражает сильно.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 17:11
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Только когда пишет один процессор, а читает - другой, тут запрет прерываний не спасёт wink.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 10 2012, 17:17
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(jcxz @ Jun 10 2012, 21:11) *
Только когда пишет один процессор, а читает - другой, тут запрет прерываний не спасёт wink.gif

Ну, у нас тут пока только прерывания обсуждались вроде wink.gif
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jun 10 2012, 18:04
Сообщение #21


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата(aaarrr @ Jun 10 2012, 20:53) *
Действительно, запрещать прерывания совсем не обязательно, если есть только два индекса.

Это могут читать дети! Ваш совет применим, если индексы представлены типами данных, которые на процессоре атомарны.
В случае, когда индексы многобайтные, а компилятор выполняет операцию выборки или присваивания несколькми командами -
всё будет работать не так как ожидает программист.

Сообщение отредактировал Genadi Zawidowski - Jun 10 2012, 18:31
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2012, 18:17
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Смотрим на название форума sm.gif
В ARM все 8-/16-/32-разрядные команды сохранения атомарны. Ну если только преднамеренно не разместить их невыровненными...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 10 2012, 18:20
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Genadi Zawidowski @ Jun 10 2012, 22:04) *
Это могут читать дети!

Если "дети" пишут реализацию FIFO, то такие грабли только на пользу. Как заметили уже, на ARM такое придется делать специально.
Go to the top of the page
 
+Quote Post
Shein
сообщение Jun 11 2012, 22:31
Сообщение #24


Участник
*

Группа: Участник
Сообщений: 45
Регистрация: 4-03-07
Пользователь №: 25 855



Цитата(jcxz @ Jun 10 2012, 21:17) *
Смотрим на название форума sm.gif
В ARM все 8-/16-/32-разрядные команды сохранения атомарны. Ну если только преднамеренно не разместить их невыровненными...

Кстати, про атомарность этих операций на ARM'е я провтыкал самым позорным образом 01.gif Да-а, трудно иногда скакать, то AVR/PIC, то ARM...
Убрал запрет прерываний, а сделал просто двойное чтение: если результаты разнятся - перечитать. А выходит и это лишнее.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 20:44
Рейтинг@Mail.ru


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