Shein 0 8 июня, 2012 Опубликовано 8 июня, 2012 (изменено) · Жалоба Доброго всем времени суток. Столкнулся с таким явлением как вызов обработчика 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. Картина абсолютно идентичная. Изменено 8 июня, 2012 пользователем Shein Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 8 июня, 2012 Опубликовано 8 июня, 2012 · Жалоба Собственно вопрос: это нормальная ситуация? Раньше у меня стояла заглушка (бесконечный цикл) на Spurious Interrupt и на всех неиспользуемых векторах в AIC. Когда на Spurious Interrupt поставил обработчик в котором просто формируется подтверждение (запись в AIC_EOICR) программа, в общем стала нормально работать. Нормальная ситуация. Как раз заглушка с бесконечным циклом на Spurious - это совершенно не нормально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Эти прерывания типичны не только для атмелов, мне понравилась объяснение в этом документе от nxp - Handling of spurious interrupts in the LPC2000. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Вот я и думаю, оставить как есть, еле же есть некий корректный механизм, как запрещать прерывание без возникновения данного эффекта? Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aaron 1 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Если я не ошибаюсь, там же можно два буфера для передачи задавать. Один заполнился - читаем и обрабатываем его спокойно, а второй тем временем заполняется. Зачем запрещать прерывания? Ну и, конечно, из Spurious выходить надо - это по-любому, у меня в одном проекте много блокировок возможно из-за вложенных прерываний, дак там это SPU - обычное явление. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shein 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Народ, спасибо всем большое! :) Вы развеяли мои сомнения. А то ведь я пытался с этим бороться, два дня убил. :smile3046: Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс? По сути, почти так и есть, только для всяких проверок (на наличие принятых данных, заполнение буфера) приходится обращаться к индексам, которые изменяются в ISR. Ну и, можно сказать, перестраховался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба А если вот такая ситуация к примеру: 1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки. 3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен. 4. Декрементированый индекс записывается в память. Обработчик прерывания завершается. 5. Фоновый процесс инкрементирует индекс и записывает его в память. Как Вам ситуация? :) ИМХО, запрещать прерывание нужно обязательно перед записью в буфер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба А если вот такая ситуация к примеру: 1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки. 3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен. 4. Декрементированый индекс записывается в память. Обработчик прерывания завершается. 5. Фоновый процесс инкрементирует индекс и записывает его в память. Как Вам ситуация? :) Зачем же делать такое кривое FIFO??? :crying: ИМХО, запрещать прерывание нужно обязательно перед записью в буфер. Если иметь прямые руки и писать FIFO правильно - не нужно! :) Обычная реализация FIFO для межпроцессного (и даже - межпроцессорного взаимодействия): Два индекса (у каждого процесса свой). Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать. Один процесс - только пишет в FIFO, другой - только читает. Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO). Минус такой реализации - реальная ёмкость FIFO на 1 элемент меньше выделенного для него буфера. Если элементы - байты - это ерунда. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO).Ага, вот тут то и упрется, когда один процесс изменит, другой тож Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Читайте внимательнее: Каждый процесс (или ISR) модифицирует только свой индекс, чужой индекс он может только читать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Читайте внимательнее:Читайте внимательнее. Никто не запрещает одному индексу переехать через другой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Каждый процесс двигает свой индекс записывая или читая в FIFO до тех пор, пока не упрётся в чужой индекс (что является признаком опустошения/заполнения FIFO). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Ваши красные буквы ни как меня не смущают :) Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данных Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MaslovVG 0 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба А если вот такая ситуация к примеру: 1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки. 3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен. 4. Декрементированый индекс записывается в память. Обработчик прерывания завершается. 5. Фоновый процесс инкрементирует индекс и записывает его в память. Здесь вы описываете не FIFO (очередь) а а стек (последний вышол первый вышел). Почитайте Кнут "основные алгоритмы". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данныхЗачем???? И какие данные "общие"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться