Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.62/21: Рейтинг темы: голосов - 21, средняя оценка - 4.62
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
1

NVIC, приоритеты, вытеснение прерываний.

30.06.2016, 14:57. Просмотров 3873. Ответов 20
Метки нет (Все метки)

Правильно ли я понимаю, что:

1) Если в NVIC установлены приоритеты прерываний, то возможно вытеснение:
-> main()
---> interript_low_priority()
------> interrupt_medium_priority()
---------> interrupt_high_priority() // его уже никто не прервёт
<------ interrupt_medium_priority() // продолжается
<--- interript_low_priority() // продолжается
<- main() // продолжается

2) Если же в NVIC всё имеет одинаковый приоритет (так вроде по умолчанию?), то вытеснение только на одном уровне идёт:
-> main()
---> interrupt1()
<--- interrupt1()
<- main()
---> interrupt2()
<--- interrupt2()
---> interrupt1()
<--- interrupt1()
<- main()

3) Если приоритет у всех прерываний одинаков (по моему так по дефолту выставлено), то текущий уже вот сработавший обработчик прерывания уже 100% никто прервать не может, так?

3.1) А если что-то происходит (это же или другое событие) когда обработчик уже работает, то NVIC только выставляет it_pending_bit (вызвать то он не может - приоритет одинаков),
т.е. при завершении текущего обработчика мы попадём
либо в main() (ничего не произошло),
либо в другой обработчик (что-то другое произошло),
либо в этот же обработчик (если это же произошло, ну или забыли сбросить вначале соответствующий it_pending_bit :) )
так?

P.S. Понятно, что вопросы наверно банальные, я про это много читал, с прерываниями - также давно работал, но что-то вот "засомневался" в своих познаниях...
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.06.2016, 14:57
Ответы с готовыми решениями:

Вопрос про приоритеты NVIC в stm32f103.
Есть такой регистр, Application interrupt omd risit control rikystir (SCB_OYRCR). &lt;Изображение...

Вытеснение контекста всякое-разное.
Хочу немного поговорить о механизме вытеснения контекста. Как вы, я совершенно уверен, не хуже...

Регистры приоритета NVIC
Подскажите какие адреса у регистров NVIC_IPRx. Базовый адрес для этого регистра NVIC_BASE0 =...

Настройка NVIC в SPL и core_cm4.h
Добрый вечер. Для настройки NVIC в SPL есть функция NVIC_Init, в теле которой есть такой код: ...

STM32 Не могу выставить адрес NVIC
Ребят, спасибо за советы. 128КБ. И все переходы и пр. привязано к этому адресу, а должно быть к...

20
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
01.07.2016, 21:47 2
Вроде как по всем пунктам да.
0
Pyko4u56
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 287
02.07.2016, 12:47 3
Вроде как, по всем пунктам верно. Я бы ещё добавил в пункт 3 то, что порядок срабатывания прерывания, если приоритет оставлен по дефолту, определяется таблицей в RM. Чем меньше номер, тем выше приоритет. Например, при одновременном приходе прерывания с номером 6 и 9, сработает сначала 6, потом 9.
0
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
03.07.2016, 15:04 4
Тогда ещё вопрос: раз main() может быть внезапно прерван в любой момент, то в нём I/O лучше не делать вообще если хоть одно периферийное устройство уже использует вывод по прерываниям?

Т.е. если в main() есть I/O например с SPI, а по прерываниям работаем например с CAN, то I/O в main() будет глючить получается?
Т.е. надо "как угодно, но не в main()" делать (даже если по таймеру и то лучше, т.к. таймерное прерывание никто не прервёт уже) ?
0
HotD
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
03.07.2016, 15:06 5
Всегда можно сделать атомарный доступ, и тогда прерывание немножко подождет.
0
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
03.07.2016, 15:31 6
Цитата Сообщение от Hotd
Всегда можно сделать атомарный доступ, и тогда прерывание немножко подождет.
:) Ню ню. Оно не подождет. Оно "пропустится" ;-) Если вы решили "подождать" в прерывании, то придется ждать дооолго.
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
03.07.2016, 15:33 7
RikoD, программу надо сразу делать с учетом того, что любой процесс может выть задержан на время обработки прерывания. Например, не использовать обычную функцию Delay для установки фиксированных задержек.
Поясню - в "стандартном" исполнении Delay состоит или из цикла на N nopов (жуть) или задержке по таймеру. Второй вариант вроде-бы правильный и гарантирует фиксированное время выполнения (ну, если таски не зависают). Однако, они гарантируют время задержки только между входом и выходом из функции, но все прерывания "вне" функции будут _прямо_ влиять на сдвиг времени, причем эта неконтролируемая задержка будет только накапливаться. Выход - использовать не Delay, а брать текущее время, прибавлять нужную задержку и ставить функцию ожидания данного времени. При этом, следующую задержку считать не от "снова забрать время", а использовать предыдущее время ожидания. В результате, вред от прерываний будет минимальным. Собственно, таким же способом следует пройтись и по другим временным/событийным процессам, тогда система будет работать при любой (нормальной) нагрузке.
0
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
03.07.2016, 15:44 8
Атомарный доступ это когда переменной (глобальный "флажок") синхронизируется доступ к ресурсу?
Так тогда если в main() глобальный "флажок" выставить, что "занято!", то прерывание не "подождёт", а вынужено будет выйти ни с чем и продолбать свои данные...

Ситуация такая:

Есть железка (допустим Ethernet контроллер), железка подключена по SPI, но int линию "не запаяли" :(
Драйвер железки требует переопределить функции (они в коде драйвера _wiok - стандартная практика) для:
- CS low (chip select)
- CS high (chip deselect)
- SPI read (то же, что и write, но нули просто шлёт)
- SPI write
И драйвер может вызвать вышеозначенные функции много раз (там даже макросы есть с операциями в нём) и прерывать между вызовами крайне нежелательно (ну особенно если CS сработал и тут бац - прерывание!, ну а потом понятно какие "данные" придут по возврату...)

Когда только с этой железкой работа - проблем нет, всё отлично работает.
Но стоит добавить работу с прерыванием (CAN, UART, etc.) и чтобы прерывания достаточно часто происходили (раз 15-20 в секунду достаточно) - железка начинает "тупить", пропускать свои данные, затем выплёвывать накопившиеся данные "пачкой" и т.д.

Вот я и думаю как это "обойти"...
Железка довольно быстрая - 18 Мбит/с SPI отлично работает.
Да и архитектура такая простая вроде:
1) с периферии (датчки на CAN, допустим) по прерываниям данные просто складываются в элементы массива в ROM.
2) по запросу с Ethernet железки данные из массива в ROM улетают по сети.

Если сделать частый вызов по таймеру (0,5мс достаточно будет по моим прикидкам, т.к. ping примерно 1мс) pottynga железки, то если на железке "ничего не происходило", то прерывание таймера быстро вернётся и может быть вызвано другое прерывание. Плюсом такого подхода будет то, что прерывание таймера (если в NVIC всё имеет одинаковый приоритет) уже никто не прервёт, а на скорости 18 Мбит/с сделать быстрый poll пары регистров на SPI - этожбыстро?

А если делать с атомарной переменной-lockом в main(), то остальные обработчики прерываний всё равно будут вызваны ведь...
0
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
03.07.2016, 15:45 9
Цитата Сообщение от MostirOtyxiy
Цитата Сообщение от Hotd
Всегда можно сделать атомарный доступ, и тогда прерывание немножко подождет.
:) Ню ню. Оно не подождет. Оно "пропустится" ;-) Если вы решили "подождать" в прерывании, то придется ждать дооолго.
Вот именно. Из обработчика придётся резко выходить, теряя данные. Ну а ждать в обработчике прерывания... кто ж его прервёт тогда?
0
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
03.07.2016, 15:50 10
Цитата Сообщение от RikoD
...
Вот я и думаю как это "обойти"...
...
Использовать циклические буфера.
В прерывании в буфер пишем, в основном цикле проги - читаем.
Буфер строить так, чтоб учитывалась мультизадачность. Ту был где то топик на эту тему.
0
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
03.07.2016, 15:53 11
Цитата Сообщение от u37
RikoD, программу надо сразу делать с учетом того, что любой процесс может выть задержан на время обработки прерывания. Например, не использовать обычную функцию Delay для установки фиксированных задержек.
Поясню - в "стандартном" исполнении Delay состоит или из цикла на N nopов (жуть) или задержке по таймеру. Второй вариант вроде-бы правильный и гарантирует фиксированное время выполнения (ну, если таски не зависают). Однако, они гарантируют время задержки только между входом и выходом из функции, но все прерывания "вне" функции будут _прямо_ влиять на сдвиг времени, причем эта неконтролируемая задержка будет только накапливаться. Выход - использовать не Delay, а брать текущее время, прибавлять нужную задержку и ставить функцию ожидания данного времени. При этом, следующую задержку считать не от "снова забрать время", а использовать предыдущее время ожидания. В результате, вред от прерываний будет минимальным. Собственно, таким же способом следует пройтись и по другим временным/событийным процессам, тогда система будет работать при любой (нормальной) нагрузке.
Спасибо, с delay() из NOPов всё понятно - его прерывания будут прерывать и время уплывёт.

Тут вопрос не в том, чтобы задержки сделать "с учётом прерываний", а в том, чтобы цикл поллинга железки (быстрой железки) просто нельзя было прерывать.
Т.е. скорость железки - 18 Мбит/с (но по прерываниям её работать "не допаяли", работаем синхронно значит), а скорость другой железки - 1 Мбит/с (и она работает с прерываниями, всё ОК).
Вот надо чтобы 18 Мбит/с железяка на SPI просто когда делала свой поллинг и CS low выставляла в main() - не прерывалась прерыванием в этот момент, а делала read/write и CS high поднимала - ну и тогда уже можно прерывать сколько влезет :)
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
03.07.2016, 16:01 12
Для коротких функций вида: Set CS, delay, stort_SPI - используйте программное прерывание (SVCall_IRQn), назначьте ему наивысший приоритет, ему никто не будет мешать.
0
RikoD
0 / 0 / 0
Регистрация: 07.10.2011
Сообщений: 127
03.07.2016, 16:36 13
Цитата Сообщение от u37
Для коротких функций вида: Set CS, delay, stort_SPI - используйте программное прерывание (SVCall_IRQn), назначьте ему наивысший приоритет, ему никто не будет мешать.
о! спасибо!!! попробую.

Т.е. я в main() вызову сервисное прерывание, которое никто не прервёт и которое если на железке ничего не происходит (нет пакетов) будет быстро возвращаться. А если на железке что-то происходит, то будет обрабатывать уже пакет и отвечать (но это не частое явление).

P.S. Да, ответ по LAN - он как раз приоритетнее периферии у меня. Т.е. от периферии можно даже немного "продолбать" сообщения, а вот на запрос по LAN ответить надо обязательно.
0
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
03.07.2016, 16:50 14
Цитата Сообщение от RikoD
Цитата Сообщение от u37
Для коротких функций вида: Set CS, delay, stort_SPI - используйте программное прерывание (SVCall_IRQn), назначьте ему наивысший приоритет, ему никто не будет мешать.
о! спасибо!!! попробую.
...

Это если вы не пользуетесь какой нить осью. Например FriiRTOS использует это прерывание для смены контекста/переключения задач.

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

Например, HAL использует SysTick для своих задержек. В то же время SysTick используется в ОСях. Это одна из причин невзлюбить хал. Не в курсе,как они там выкрутились в последних версиях, но в одной из ранних, у них прям #error стоял о том, что этот HAL с осями не совместим.

Так что - лучше поискать другое решение, менее аппаратнозависимое.
0
Pyko4u56
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 287
03.07.2016, 19:38 15
Цитата Сообщение от RikoD
Есть железка (допустим Ethernet контроллер), железка подключена по SPI, но int линию "не запаяли" :(
Допаять линию прерывания не прощё? :D
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
03.07.2016, 20:27 16
MostirOtyxiy, с "PendSV" не путаете?
Впрочем, да, именно Friirtos использует это прерывание. В отличии от всяких scmRTOS/TNKernel/ (сарказм)
Чтож, еще один повод не использовать данную RTOS.
0
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
03.07.2016, 21:04 17
Цитата Сообщение от u37
MostirOtyxiy, с "PendSV_Homdler" не путаете?
Единственно, что я спутал, это что в SVC_Homdler происходит старт первой задачи. А изначально он все же задумывался для переключения контекста, которое, видимо, в последних версиях уже происходит в PendSV_Homdler.

В любом случае, осью используются минимум три прерывания: SVCall_IRQn, PendSV_IRQn, SysTick_IRQn.

Цитата Сообщение от u37
Чтож, еще один повод не использовать данную RTOS.
И кстати, номера этих прерываний имеют отрицательные значения (в дефайнах CMSISа): -5, -2 и -1 соответственно, что как бы наводит на мысль, что это все же системные прерывания, и обычным программам их использовать не стоит, а не на ось бочку катить ;-)
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
03.07.2016, 21:28 18
Гм.
Как нибудь, поищите обработчик SVCall в scmRTOS. Позволю откровенную наглость и скажу, что не Я должен ложиться под RTOS, а RTOS для меня.
Что до SysTick и HALL, то здесь и говорить, собственно, не о чем. Хотя, в "российских" ARM SysTick глюкавый, вешают на обычный таймер.
0
MostirOtixiy
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
03.07.2016, 21:43 19
Цитата Сообщение от u37
...Позволю откровенную наглость и скажу, что не Я должен ложиться под RTOS, а RTOS для меня..
Блиин, а посоны то и не вкурсе. Надо будет мелкомягким, МАКошникам да линусу писануть писульку, что они там все неправильно делают, и u37 пишет проги, а они у него на их осях не идут :) потому что он использует ресурсы проца, которые ОСи для себя забирают :) (заметьте, системные ресурсы, с номером меньше 0, т.е. заведомо выше по статусу чем самое первое - ресет хэндлер.)

Это если следовать вашей логике ;)
...
Ну ну. Удачи!
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
03.07.2016, 21:46 20
Понятно, программер. Эх.
0
03.07.2016, 21:46
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.07.2016, 21:46

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

STM32F103 NVIC, чего я делаю не так ?
пытаюсь обработать прерывания от DMA 7 канал: void DMA1_Channel7_IRQHomdler(void) { }...

NVIC - порядок выполнения при равных приоритетах?
Где можно посмотреть? Ну, например, все приоритеты одинаковы, сработало EXTI прерывание и...

Вопрос по обработке бита ожидания в EXTI и NVIC
Описание ситуации. У меня устанавливается бит ожидания EXTI, дальше автоматически устанавливается...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.