Перейти к содержанию
    

ARM7 от Atmel. Запрет прерываний.

Доброго всем времени суток.

Столкнулся с таким явлением как вызов обработчика 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Нормальная ситуация. Как раз заглушка с бесконечным циклом на Spurious - это совершенно не нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот я и думаю, оставить как есть, еле же есть некий корректный механизм, как запрещать прерывание без возникновения данного эффекта?

Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я не ошибаюсь, там же можно два буфера для передачи задавать. Один заполнился - читаем и обрабатываем его спокойно, а второй тем временем заполняется. Зачем запрещать прерывания? Ну и, конечно, из Spurious выходить надо - это по-любому, у меня в одном проекте много блокировок возможно из-за вложенных прерываний, дак там это SPU - обычное явление.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Народ, спасибо всем большое! :) Вы развеяли мои сомнения. А то ведь я пытался с этим бороться, два дня убил. :smile3046:

Корректный механизм в случае работы с UART через кольцевые буфера - вообще не запрещать прерывания. Зачем их запрещать если в кольцевой RX-буфер только один писатель - ISR, а в кольцевой TX-буфер - пишет только фоновый процесс?

По сути, почти так и есть, только для всяких проверок (на наличие принятых данных, заполнение буфера) приходится обращаться к индексам, которые изменяются в ISR. Ну и, можно сказать, перестраховался.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если вот такая ситуация к примеру:

1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.

3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.

4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.

5. Фоновый процесс инкрементирует индекс и записывает его в память.

 

Как Вам ситуация? :)

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если вот такая ситуация к примеру:

1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.

3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.

4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.

5. Фоновый процесс инкрементирует индекс и записывает его в память.

 

Как Вам ситуация? :)

Зачем же делать такое кривое FIFO??? :crying:

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

Если иметь прямые руки и писать FIFO правильно - не нужно! :)

Обычная реализация FIFO для межпроцессного (и даже - межпроцессорного взаимодействия):

Два индекса (у каждого процесса свой).

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

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

Минус такой реализации - реальная ёмкость FIFO на 1 элемент меньше выделенного для него буфера. Если элементы - байты - это ерунда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читайте внимательнее:

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читайте внимательнее:
Читайте внимательнее. Никто не запрещает одному индексу переехать через другой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ваши красные буквы ни как меня не смущают :) Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данных

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если вот такая ситуация к примеру:

1. Фоновый процесс считывает в регистр индекс, дабы увеличить его на 1 с целью записать в FIFO новый байт для отправки.

3. Возникает прерывание по отправке данных. Считывается, опять же индекс из памяти дабы уменьшить индекс FIFO, так как очередной байт отправлен.

4. Декрементированый индекс записывается в память. Обработчик прерывания завершается.

5. Фоновый процесс инкрементирует индекс и записывает его в память.

Здесь вы описываете не FIFO (очередь) а а стек (последний вышол первый вышел). Почитайте Кнут "основные алгоритмы".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще раз вам повторяю, что один процесс должен приостановить второй, прежде чем он что то изменит в общих данных
Зачем???? И какие данные "общие"?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...