|
ARM7 от Atmel. Запрет прерываний., почему он заходит в Spurious Interrupt |
|
|
|
Jun 8 2012, 14:17
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Jun 9 2012, 06:55
|
Местный
  
Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866

|
Эти прерывания типичны не только для атмелов, мне понравилась объяснение в этом документе от nxp - Handling of spurious interrupts in the LPC2000.
--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
|
|
|
|
|
Jun 10 2012, 13:46
|
Участник

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

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

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

|
А если вот такая ситуация к примеру: 1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки. 3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен. 4. Декрементированый индекс записывается в память. Обработчик прерывания завершается. 5. Фоновый процесс инкрементирует индекс и записывает его в память. Как Вам ситуация?  ИМХО, запрещать прерывание нужно обязательно перед записью в буфер.
--------------------
|
|
|
|
|
Jun 10 2012, 15:53
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(prottoss @ Jun 10 2012, 20:15)  А если вот такая ситуация к примеру: 1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки. 3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен. 4. Декрементированый индекс записывается в память. Обработчик прерывания завершается. 5. Фоновый процесс инкрементирует индекс и записывает его в память. Как Вам ситуация?  Зачем же делать такое кривое FIFO??? Цитата(prottoss @ Jun 10 2012, 20:15)  ИМХО, запрещать прерывание нужно обязательно перед записью в буфер. Если иметь прямые руки и писать FIFO правильно - не нужно!  Обычная реализация FIFO для межпроцессного (и даже - межпроцессорного взаимодействия): Два индекса (у каждого процесса свой). Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать. Один процесс - только пишет в FIFO, другой - только читает. Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO). Минус такой реализации - реальная ёмкость FIFO на 1 элемент меньше выделенного для него буфера. Если элементы - байты - это ерунда.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|