|
Программные прерывания разного приоритета |
|
|
|
Jun 24 2016, 16:02
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Один из таймеров задает базовую частоту, в его обработчике прерывания запускается опрос датчиков и забираются результаты предыдущего опроса. Надо обрабатывать данные одновременно на разных частотах. Для примера конкретные числа, приходит 400 Гц, в первом же обработчике все преобразуется к 100 Гц, далее обработка на 100 Гц. Одновременно с этим 100 Гц преобразуются в 10 Гц и обрабатываются вторым способом, формируются поправки, которые идут на входы первой процедуры обработки.
То есть на временной диаграмме будет долгая работа 10 Гц процедуры, которую несколько раз прерывает 100 Гц процедура, и в 4 раза чаще прерывание для чтения измерений датчиков, которое перебивает всех но занимает мало времени.
Как это сделать на прерываниях? Из первого каждые 4 такта можно запускать второе прерывание с меньшим приоритетом. А из второго каждые 10 тактов третье с еще меньшим приоритетом. Но где взять программные прерывания? Занять неиспользуемые IRQ? Красивее вариантов нет?
Можно было бы обойтись одним прерыванием, если было бы можно разрешить одному IRQ вытеснять самого себя, менять приоритет исполняемого в данный момент прерывания. Но почитав внимательнее про регистр BASEPRI я понял, что так не получится.
МК - stm32f4xx.
Спасибо.
|
|
|
|
|
Jun 27 2016, 07:52
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Идея, в принципе, верная - использовать какие-нибудь "лишние" аппаратные прерывания (благо их в современных камнях с избытком). Даже на ноги ничего выводить не надо (разве что для отладки будет полезно).
Но, по хорошему, требуемый функционал хорошо ложится на RTOS. Я тоже когда-то велосипеды строил - низкоприоритетные прерывания, длинные процедуры которые выполняются за несколько заходов (чтоб в паузах можно было что-то ещё сделать). В очередной раз порекламирую scmRTOS - компактно, наглядно, хорошо документировано. По функционалу до "больших" ОСей бесконечно далеко, но этого никто и не обещал.
PS вроде б можно крутить приоритет текущего прерывания. Надо б внимательно прочитать, в какой момент оно в контроллере прерываний сравнивается. Но зачем подкладывать себе же такие очевидные грабли?!
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Jun 27 2016, 14:37
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(amaora @ Jun 24 2016, 20:02)  Красивее вариантов нет? Это, наверное, самый простой, когда проект без ОС и не хочется самому писать на асме подмену контекстов выходов из IRQ. Но могут попасться недокументированные вектора на месте якобы свободных. Паранойю можно сгладить передачей сигналов подтверждений вызова между своими уровнями. Если при влёте в нижеприоритетное прерывание нет флага от более приоритетного, то сразу выходить из обработчика. Но можно добавить паранойи. Если вдруг разрешить якобы свободный вектор и что-то недокументированное запросит прерывание, то произойдёт зависание в обработчике IRQ. Так что вариант использовать вектор периферии, которая в проекте не используется смотрится тоже неплохо. Обязательно ли нужно запитывать этот блок для корректной работы NVIC должно быть написано в документации. Если не написано, то скорее всего придётся запитывать и внутри обработчика сбрасывать все возможные запросы от этого блока периферии, несмотря на то, что блок не используется. Цитата(esaulenka @ Jun 27 2016, 11:52)  PS вроде б можно крутить приоритет текущего прерывания. Поделитесь информацией, если что-то узнаете. Логика NVIC может быть заточена на отработку инструкции BX со служебными значениями (паттерн 0xffffffxx).
Сообщение отредактировал GetSmart - Jun 27 2016, 21:22
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jun 27 2016, 17:20
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Если переходит на rtos, то я надолго закопаюсь в переписывание всего кода под нее. Наловлю проблем с синхронизацией потоков. Это останавливает. Хотя код во многих прикладных местах может стать более простым, но для этого надо будет отладить сложный низкоуровневый код. Цитата PS вроде б можно крутить приоритет текущего прерывания. Надо б внимательно прочитать, в какой момент оно в контроллере прерываний сравнивается. Но зачем подкладывать себе же такие очевидные грабли?! Да в документах arm об этом, что-то было. Только подразумевается смена приоритета для прерываний которые возникнут после этой смены. А не смена приоритета того, что выполняется в данный момент. На стеке хранится значение регистра PSR в котором номер ISR, по которому похоже определяется приоритет прерывания после, например выхода из вложенного. А приоритеты хранятся в регистрах NVIC, может случится нехорошо если после выхода из вложенного прерывания окажется, что приоритет уже другой.
|
|
|
|
|
Jun 28 2016, 04:09
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(amaora @ Jun 27 2016, 23:20)  Если переходит на rtos, то я надолго закопаюсь в переписывание всего кода под нее. ... Да в документах arm об этом, что-то было. Только подразумевается смена приоритета для прерываний которые возникнут после этой смены. А не смена приоритета того, что выполняется в данный момент. Берёте любой неиспользуемый в программе вектор аппаратного прерывания и используете его (возбуждаете это прерывание программно). Никаких изменений приоритета на ходу делать конечно не надо. Если нужно чтобы управление попало в этот, программно возбуждаемый вектор, после завершения инициировавшего прерывания, то его приоритет делаете ниже чем у инициировавшего прерывания. Лучше даже ниже чем у любого настоящего аппаратного прерывания. Получается что-то типа задачи ОС, получающей управление по событию в инициирующем ISR. Делал так не раз в разных проектах (и в давно работающих) на разных МК, там где и ОС при этом работает - всё прекрасно работает без проблем. Да и почему не должно работать? Цитата(amaora @ Jun 27 2016, 23:20)  На стеке хранится значение регистра PSR в котором номер ISR, по которому похоже определяется приоритет прерывания после, например выхода из вложенного. А приоритеты хранятся в регистрах NVIC, может случится нехорошо если после выхода из вложенного прерывания окажется, что приоритет уже другой. На стеке сохраняется предыдущее значение PSR (и поле IPSR его в том числе) сохранённое при стэкинге. При выходе из прерывания оно будет просто восстановлено в PSR. Текущее содержимое IPSR имхо просто маскирует содержмое регистра запросов NVIC (маскируются все прерывания с приоритетом ниже указанного в IPSR). Цитата(GetSmart @ Jun 28 2016, 03:04)  То есть процессором это значение создаётся, но потом им не читается и ни на что не влияет. Не может быть. Если более приоритетный ISR (номер N) прервал выполнение менее приоритетного (номер K), то после возврата из ISR N, что CPU должен записать в IPSR? Откуда он это определит? Вот как раз со стека он это считывает и заносит в PSR.
|
|
|
|
|
Jun 28 2016, 15:14
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(jcxz @ Jun 28 2016, 08:09)  Не может быть. Если более приоритетный ISR (номер N) прервал выполнение менее приоритетного (номер K), то после возврата из ISR N, что CPU должен записать в IPSR? Откуда он это определит? Вот как раз со стека он это считывает и заносит в PSR. Документальные подтверждения где? На уровне предположений - может. Как говорится мухи отдельно, котлеты отдельно. Номера векторов могут "гулять" по стеку и IPSR. А приоритеты этих активированных векторов могут жить своей (невидимой программисту) жизнью внутри NVIC. При этом можно в стеке эти номера менять (сбивать), оттуда значение грузится в IPSR, а на котлеты (приоритеты принятых прерываний/исключений) это не повлияет. Вопрос стоит в том, насколько подробно ARM этот вопрос задокументировал. Чтобы масоны эту логику в дальнейшем не смогли переиначить.
Сообщение отредактировал GetSmart - Jun 28 2016, 17:06
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jun 29 2016, 03:48
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(GetSmart @ Jun 28 2016, 21:14)  Документальные подтверждения где? Вам письмо за подписью директора ARM нужно? Цитата(GetSmart @ Jun 28 2016, 21:14)  При этом можно в стеке эти номера менять (сбивать), оттуда значение грузится в IPSR, а на котлеты (приоритеты принятых прерываний/исключений) это не повлияет. И где тогда посмотреть текущий уровень приоритета прерывания по Вашему? В каком регистре? Фантазировать можно как угодно, но как правило, разработчики ядер действуют соответствуясь с логикой и здравым смыслом и не городят ненужных сущностей когда без них можно обойтись. Если такие регистры уже есть и они хранят нечто нужное, на кой придумывать некие "невидимые программисту" сущности? О том же говорит и правило Бритвы Оккама. Цитата(GetSmart @ Jun 28 2016, 21:14)  Вопрос стоит в том, насколько подробно ARM этот вопрос задокументировал. Чтобы масоны эту логику в дальнейшем не смогли переиначить. Открываете описание ядра с http://www.arm.com, читаете про регистр IPSR и про регистр Interrupt Control State Register (в числе регистров NVIC), в котором есть поле VECTACTIVE. Пишете простейший код, в котором изнутри одного ISR вызываете другой, более приоритетный. Трассируете: вход в первый ISR - содержимое IPSR и VECTACTIVE - совпадают (например ==0x24); вход во второй ISR (вложенный) - содержимое IPSR и VECTACTIVE - совпадают (например ==0x0B); в стеке содержимое IPSR из первого ISR (0x24), LR=0xFFFFFFF1; меняете на стеке содержимое IPSR на какое-либо другое (например ==0x25); выполняете BX LR и убеждаетесь, что теперь IPSR и VECTACTIVE становятся раными значению, записанному Вами в стек (0x25), а не тому значению, что было в первом ISR (0x24). Обратите внимание - оба регистра IPSR и VECTACTIVE установились в значение, записанное Вами в стек (0x25), а не в значение из первого ISR (0x24), которое могло быть получено из неких "невидимых программисту" субстанций.
|
|
|
|
|
Jun 29 2016, 11:59
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(jcxz @ Jun 29 2016, 07:48)  Обратите внимание - оба регистра IPSR и VECTACTIVE установились в значение, записанное Вами в стек (0x25), а не в значение из первого ISR (0x24), которое могло быть получено из неких "невидимых программисту" субстанций. Вы невнимательны. Описанные мной детали не противоречили этому. <Номера> векторов можно менять на стеке. И оттуда они будут браться при возвратах из обработчиков. Я именно это и имел ввиду. Но номера это не приоритеты. Приоритеты для (как минимум ожидаемых) прерываний задаются программистом в регистрах NVIC.IPR[]. Для исключений есть жёсткие приоритеты, есть тоже настраиваемые. Штука в том, что можно в IPSR загрузить, к примеру для CM0, значение 63 (у него 6-битный IPSR). Но для этого вектора у CM0 нет соответствующего регистра NVIC.IPR[] и вопрос: откуда будет браться приоритет? В то же время, приоритет активированного NVIC-ом вектора всегда существует и такой коллизии там нет. Уточню свои же слова Цитата То есть процессором это значение создаётся, но потом им не читается и ни на что не влияет. = aka "Номер вектора перекладывается с места на место", но приоритетом не управляет. Ещё в описании ARMv6-M (где и описан NVIC) есть такая цитата Цитата If software changes the priority of an exception when it is active or enabled, the effect is UNPREDICTABLE in ARMv6-M. из которой тоже не очень понятно, что за "огород" там организован. --------- Подобными разборками можно напугать начинающих. Хотя простейшую организацию вложенных программных прерываний, как хотел топикстартер, этот спор не касается.
Сообщение отредактировал GetSmart - Jun 30 2016, 01:11
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jun 30 2016, 08:50
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(GetSmart @ Jun 29 2016, 17:59)  Вы невнимательны. Описанные мной детали не противоречили этому. <Номера> векторов можно менять на стеке. И оттуда они будут браться при возвратах из обработчиков. Я именно это и имел ввиду. Это ещё неизвестно кто невнимателен. На мою фразу: Если более приоритетный ISR (номер N) прервал выполнение менее приоритетного (номер K), то после возврата из ISR N, что CPU должен записать в IPSR? Откуда он это определит? Вот как раз со стека он это считывает и заносит в PSR.Вы потребовали документальное подтверждение, а теперь сами пишете что "номера векторов будут браться со стека". И Вы же утверждали, что: Цитата(GetSmart @ Jun 28 2016, 03:04)  То есть процессором это значение создаётся, но потом им не читается и ни на что не влияет. На что я Вам указал что оно влияет - заносится в регистры IPSR и в поле VECTACTIVE регистра "Interrupt Control State Register". А как узнать приоритет текущего прерывания - я не знаю, возможно он программно недоступен и может быть определён только косвенно, считав регистр приоритета для соответствующего номера прерывания. Поэтому и не рекомендуют изменять приоритет для текущего активного или разрешённого прерывания. Возможно в момент регистрации нового запроса прерывания, его приоритет считывается из регистров приоритета и заносится в поле VECTPENDING регистра "Interrupt Control State Register".
|
|
|
|
|
Jun 30 2016, 19:06
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(jcxz @ Jun 30 2016, 12:50)  Это ещё неизвестно кто невнимателен. На мою фразу: Если более приоритетный ISR (номер N) прервал выполнение менее приоритетного (номер K), то после возврата из ISR N, что CPU должен записать в IPSR? Откуда он это определит? Вот как раз со стека он это считывает и заносит в PSR. Вы ерунду написали и даже не поняли этого. По номеру в IPSR и сохранённой копии этого номера в стеке НИКАК не определить кто кого приоритетней. Если в документации чёрным по белому не написано, что <в любой момент времени> или <в моменты переходов между векторами> номер ассоциируется с приоритетом по какой-то таблице. Даже при этой логике про ограниченность таблицы я уже написал. Если же <в момент вызова> ассоциируется, то NVIC вызвать может только допустимый вектор, имеющий (табличный) приоритет. И эта версия уже ближе к тому, что я пытался донести. Цитата(jcxz @ Jun 30 2016, 12:50)  На что я Вам указал что оно влияет - заносится в регистры IPSR и в поле VECTACTIVE регистра "Interrupt Control State Register". Я уже уточнил, что имел ввиду: "Номер вектора перекладывается с места на место", но приоритетом не управляет. Точнее может не управлять. Т.к. ясно это не описано. Вполне рабочее предположение. Можно ещё точнее выразить её: приоритет вектора КЭШИРУЕТСЯ в момент вызова и пока обработчик этого вектора не завершится, то подменами IPSR или регистров NVIC.IPR[] приоритет этого активного вектора не изменить. Для этого кэширования не нужен второй стек. Т.к. все прерывания и исключения испольняются строго с возрастающим приоритетом, то достаточно битовой карты приоритетов, на которой взводятся биты. Это версия. В документации я не вижу противоречий с ней. Но может я что-то ещё не прочитал. Цитата(jcxz @ Jun 30 2016, 12:50)  А как узнать приоритет текущего прерывания - я не знаю ...возможно... Возможно ... Вы так уверенно спорили, что казалось всё знаете. Повторюсь. Предположить можно несколько вариантов. И это будут только предположения. А в норме ясность должна следовать из документации. Можно поковыряться в реальном процессоре. Но нет гарантии, что во всех v6-M это будет одинаково. И в документации неполнота всё-равно будет (если есть).
Сообщение отредактировал GetSmart - Jul 1 2016, 04:14
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|