Например TDA7294

Форум РадиоКот :: Просмотр темы - AVR прерывание прерывания
Форум РадиоКот
https://radiokot.ru/forum/

AVR прерывание прерывания
https://radiokot.ru/forum/viewtopic.php?f=20&t=75806
Страница 1 из 3

Автор:  sx386 [ Сб июл 21, 2012 23:29:20 ]
Заголовок сообщения:  AVR прерывание прерывания

Прочитал что прерывания выполняются в очереди приоритета, если срабатывают одновременно

Т.е. при одновременной подаче сигнала на INT0 и INT1 выполниться сначала INT0, а затем INT1

А что будет если подать сигнал на INT0 в то время, когда выполняется код в INT1
Контроллер дождётся выполнения INT1, а затем запустит INT0 или прервёт INT1 и выполнит INT0 ?

Автор:  brutal [ Вс июл 22, 2012 00:04:13 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

входя в обработчик прерывания, avr микроконтроллер сбрасывает флаг разрешения прерывания поэтому INT1 выполнится до конца. Однако при подаче сигнала на INT0 флаг прерывания INTF0 установится, и, по-видимому, при завершении обработки INT1 сработает переход на обработчик INT0.

Поэтому поведение зависит от значения флага I в регистре SREG на момент прихода сигнала INT0.

Автор:  vitalik_1984 [ Вс июл 22, 2012 00:16:52 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

можно насильно включить флаг глобального разрешения прерываний,а нужно ли?Так окажутся все прерывания запутанными и какой нибудь коллапс нагрянет :))

Автор:  coredumped [ Вс июл 22, 2012 06:49:47 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Коллапса не будет, если объем стека позволяет :)

Автор:  ILYAUL [ Вс июл 22, 2012 19:01:46 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

А причём здесь объём стека? Колапс , если не иметь мозгов, наступит при любом объёме

Автор:  BCluster [ Вс июл 22, 2012 19:33:36 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

объем стека как бы при всем)))

Автор:  Goldsmith [ Вс июл 22, 2012 20:10:53 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

sx386 писал(а):
Прочитал что прерывания выполняются в очереди приоритета, если срабатывают одновременно
Совершенно верно. Если установлено одновременно несколько флагов запроса прерывания и установлен флаг Global Interrupt Enable, начнет выполняться разрешенное прерывание с наивысшим приоритетом.

Приоритетность прерывания определяется адресом его вектора: чем меньше адрес, тем выше приоритет.

sx386 писал(а):
Т.е. при одновременной подаче сигнала на INT0 и INT1 выполниться сначала INT0, а затем INT1
Согласно старшинству приоритетов (см. выше): чем меньше адрес вектора, тем выше приоритет. Обычно приоритет INT0 выше, чем у INT1, но моделей AVR много, поэтому за все не могу ручаться.

sx386 писал(а):
А что будет если подать сигнал на INT0 в то время, когда выполняется код в INT1
Контроллер дождётся выполнения INT1, а затем запустит INT0 или прервёт INT1 и выполнит INT0 ?
При входе в прерывание флаг Global Interrupt Enable автоматически сбрасывается, запрещая дальнейшие прерывания. Если он будет явно установлен в программе обработки прерывания, то новый запрос с наивысшим приоритетом прервет текущий обработчик. Приоритет прерывания уже запущенного обработчика при этом не имеет значения: если одновременно выставлены запросы INT0 и INT1 и оба они разрешены, начнет обрабатываться INT0; если далее в обработчике INT0 будет установлен флаг Global Interrupt Enable, то текущий обработчик будет вытеснен обработчиком INT1, а по его завершении будет продолжен (если кто-то еще снова не вытеснит).

Точно так же уже запущенный обработчик INT1 будет прерван более приоритетным INT0 лишь в том случае, если сам установит Global Interrupt Enable. Приоритет важен лишь в момент выбора одного прерывания из нескольких одновременных запросов.

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

Автор:  ILYAUL [ Пн июл 23, 2012 01:06:39 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

BCluster писал(а):
объем стека как бы при всем)))

Ну для С наверное, asm более свободен в этом отношении, там всё решает внимательность.

Автор:  Goldsmith [ Пн июл 23, 2012 10:28:42 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

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

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

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

Автор:  DrHlus [ Пн июл 23, 2012 22:10:37 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Goldsmith писал(а):
Если обработчик прерывания нереентерабелен (что вполне вероятно), то повторное прерывание, возникшее во время обработки предыдущего, приведет к непредсказуемым последствиям.
Можете рассказать об этом подробнее или кинуть ссылочку, где об этом можно почитать?

Автор:  ILYAUL [ Пн июл 23, 2012 23:16:08 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Цитата:
где об этом можно почитать?

+1
Насколько я помню , реентерабельность относится к одному и тому же куску кода , которым одновременно могут воспользоваться несколько пользователей не мешая друг другу , при этом на код накладывается куча условий. И как это понятие применимо к вложенным прерываниям?
Цитата:
Ну а если уж это невыполнимо, то хотя бы сбрасывать флаг разрешения данного прерывания в начале его обработки.
Что обычно делается процессором автоматически при входе в обработчик прерывания , если это прерывание разрешено или всё таки нет?

Автор:  ploop [ Пн июл 23, 2012 23:38:32 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Хотя вложенных прерываний стоит избегать, бывают случаи, когда без них логика становится ещё запутанней, и больше шансов нарваться на грабли. Тут важно понимать одно: в какой момент какое прерывание может наступить. Редко они используются все и сразу.

Например: есть прерывание с относительно длительным обработчиком (и без него никак, либо очень сложно). Есть второе прерывание, которое необходимо обработать моментально, и выполняется оно быстро, при том не модифицирует данные, с которым работает первое. И если больше никаких прерываний не используется, то вполне вариант принудительно разрешить прерывания внутри первого, при этом мы практически ничего не теряем, избавляемся от громоздкости и неповоротливости кода.
Но если есть ещё хоть одно (третье) прерывание, способное повлиять на работу первого, этот вариант отпадает.

Автор:  Goldsmith [ Пн июл 23, 2012 23:43:39 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

DrHlus писал(а):
Goldsmith писал(а):
Можете рассказать об этом подробнее или кинуть ссылочку, где об этом можно почитать?
Если хотите подробно, то можно почитать, например, здесь:

Arnold S. Berger. Embedded Systems Design: An Introduction to Processes, Tools, and Techniques, раздел "Nested Interrupts and Reentrancy".
Bruce Powel Douglass. Real-Time Design Patterns: Robust Scalable Architecture for Real-Time Systems, раздел 7.2 "Critical Section Pattern".
Jean J. Labrosse. Embedded Systems Building Blocks, Second Edition. Complete and Ready-to-Use Modules in C, раздел 2.11 "Reentrancy".

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

Или попробую коротко своими словами. Конечно, пример немного притянут за уши, но в целом ситуацию попробую обрисовать.

Предположим, у нас есть таймер, генерирующий прерывания с частотой килогерц. Каждую тысячную миллисекунду счетчик миллисекунд обнуляется и увеличивается счетчик секунд:

Код:
void обработчик_прерывания_1кГц(void)
{
  счетчик_миллисекунд++;
  if (счетчик_миллисекунд >= 1000)
  { // прошла секунда
    счетчик_миллисекунд = 0;
    счетчик_секунд++;
  }
  // еще какие-то действия
}

Предположим такую последовательность событий:
    счетчик_миллисекунд == 999;

    вошли в обработчик прерывания от таймера;

    инкрементировали счетчик_миллисекунд == 1000;

    условие (счетчик_миллисекунд >= 1000) выполнено, вошли внутрь if (строка, помеченная комментарием // прошла секунда);

    получили какое-то другое прерывание и вошли в его обработчик, обработчик таймера отложен;

    тем временем прошла миллисекунда, повторно вошли в обработчик прерывания от таймера, первый экземпляр обработчика все еще отложен;

    инкрементировали счетчик_миллисекунд == 1001;

    условие (счетчик_миллисекунд >= 1000) выполнено, вошли внутрь if;

    обнулили счетчик_миллисекунд, инкрементировали счетчик_секунд, выполнили остаток кода;

    вышли из вложенного (второго) прерывания от таймера;

    вернулись в отложенный обработчик на помеченную строку (внутрь if);

    снова обнулили счетчик_миллисекунд, инкрементировали счетчик_секунд, выполнили остаток кода;

    вернулись из первого прерывания от таймера.


Итак, имеем все "прелести" вложеннного вызова нереентерабельного обработчика: потеряли миллисекунду (дважды обнулен счетчик), зато получили лишнюю секунду (дважды инкрементировали).

Немного сумбурно и громоздко получилось, но, надеюсь, идея все же понятна.

Автор:  Goldsmith [ Вт июл 24, 2012 00:21:34 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

ILYAUL писал(а):
Насколько я помню , реентерабельность относится к одному и тому же куску кода , которым одновременно могут воспользоваться несколько пользователей не мешая друг другу , при этом на код накладывается куча условий. И как это понятие применимо к вложенным прерываниям?
Наличие нескольких пользователей вовсе не обязательно, иначе получилось бы, что весь код в однопользовательской системе автоматически становится реентерабельным, а это отнюдь не так. Реентерабельный код может выполняться параллельно несколькими потоками в процессе одного пользователя и даже в одном потоке, если это рекурсивный вызов.

Вот вполне корректное определение реентерабельности:
Цитата:
reentrant adj. Said of software that can be executed multiple times simultaneously. A reentrant function can be safely called recursively or from multiple tasks. The key to making code reentrant is to ensure mutual exclusion whenever accessing global variables or shared registers.
Jack Ganssle, Michael Barr. Embedded Systems Dictionary.

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

Цитата:
Что обычно делается процессором автоматически при входе в обработчик прерывания , если это прерывание разрешено или всё таки нет?
Обычно в известных мне архитектурах (хотя, конечно, известны мне далеко не все) при входе в обработчик прерывания автоматически сбрасывается флаг запроса этого прерывания. Бит (он же флаг) разрешения прерывания остается неизменным, его следует устанавливать/сбрасывать явно в коде.

Автор:  Goldsmith [ Вт июл 24, 2012 00:44:16 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

ploop писал(а):
Например: есть прерывание с относительно длительным обработчиком (и без него никак, либо очень сложно).
Довольно часто (из собственной практики я бы даже сказал: "всегда", но жизнь зачастую оказывается разнообразнее наших представлений о ней) удается все же сократить обработчик прерывания до разумно-минимальных размеров, оставив в нем лишь действительно критичные по времени операции (например, забрать из регистров ввода данные, пока они не затерлись следующей порцией). Затем обработчик помещает событие в очередь и завершает работу. Обработкой данных из очереди займется уже другая задача в соответствии с назначенным ей приоритетом, которая никак не мешает прерываниям.

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

Автор:  ploop [ Вт июл 24, 2012 06:32:47 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Да это понятно всё.
Я хотел сказать то, что вы в своём примере очень хорошо подчеркнули фразой "тем временем прошла миллисекунда", то есть второй обработчик может (т.е. такая ситуация в принципе возможна) перекрыть по времени первый.
Тут да, применять не в коем случае нельзя.

Автор:  Goldsmith [ Вт июл 24, 2012 08:12:19 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

ploop писал(а):
Я хотел сказать то, что вы в своём примере очень хорошо подчеркнули фразой "тем временем прошла миллисекунда", то есть второй обработчик может (т.е. такая ситуация в принципе возможна) перекрыть по времени первый.
Тут да, применять не в коем случае нельзя.
Точно. К тому же пример-то специально упрощенный, чтобы читателям проще логику отследить. А если к тому же обработчиков не два, а поболее, да к тому же глобально прерывания постоянно разрешены, и любой обработчик в любой момент перебивается другим экземпляром, в том числе самим собой по вложенной обработке, то получим неиссякающий источник непериодических глюков, причем очень трудно воспроизводимых в системе отладки (а то, что возможно в принципе, все равно рано или поздно произойдет).

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

Автор:  ploop [ Вт июл 24, 2012 08:38:46 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

В последнем проекте была ситуация:
1. Основной цикл. Куча математики, работает очень долго: где-то секунду на одну итерацию. Там же вывод на индикатор, что даёт естественную задержку его обновления около секунды.
2. Таймер, и его прерывание каждые 10мс (100 раз в секунду). Там тоже объёмный код, но работает фиксированное время, около 5-6мс (сам на себя наложиться не может.
3. Внешнее прерывание INTx, внутри которого несколько операций, т.е. считанные микросекунды.

Всего два прерывания. Внутри прерывания таймера разрешил вложенные, и убил двух зайцев: таймер корректно работает, не усложняя основной цикл, и отработка внешнего прерывания происходит всегда вовремя.

Можно было бы пересмотреть логику (изначально так и хотел), но это сильно бы усложнило код, учитывая, что он чисто на ассемблере, в итоге это вылилось бы в увеличение времени на написание и тестирование.

Так что не так страшен чёрт, если подходить с умом.

Автор:  Goldsmith [ Вт июл 24, 2012 09:22:15 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

ploop писал(а):
Так что не так страшен чёрт, если подходить с умом.
Тут ключевой момент:
ploop писал(а):
2. Таймер ... сам на себя наложиться не может.
С таймером проще: вы точно знаете период прерываний, и если так же точно знаете длительность его обработки (в обработчике нет циклов и непредсказуемых условных операторов), то можете дать гарантию, что повторного вхождения в обработчик не будет. Заведомо кратковременный другой обработчик также не создает проблем (если только по INTx гарантированно исключен шквал запросов). В данном частном случае проблема реентерабельности не возникнет, конечно.

Если же событие асинхронное и возникает в непредсказуемые моменты, черт станет гораздо страшнее. Единственный способ не попасть в ловушку - запрещать повторное прерывание от этого же источника при входе в обработчик и разрешать (при необходимости) непосредственно перед выходом. Глобально прерывания запрещать не обязательно. Только в этом случае нереентерабельные обработчики не создадут проблем, о которых DrHlus спрашивал в начале темы.

Автор:  ILYAUL [ Вт июл 24, 2012 11:40:49 ]
Заголовок сообщения:  Re: AVR прерывание прерывания

Цитата:
...Затем обработчик помещает событие в очередь и завершает работу.

Ну вообще-то это стандартный подход к написанию обработчиков прерываний.
Цитата:
...проще будет портировать на другую платформу при необходимости, если, конечно, они не на ассемблере писаны;

Это Вы давненько с asm не работали, портировать его с платформы на платформу не так уж и сложно. Главное правильно сразу написать макросы.

Страница 1 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/