Запуск программного события из прерывания (XMEGA, GCC) - PullRequest
0 голосов
/ 10 июня 2018

Я хочу запустить периодическое «служебное» событие, которое регулярно вызывается прерыванием по таймеру.Прерывание срабатывает часто (кГц +), хотя для завершения функции может потребоваться много времени, поэтому я не могу просто выполнить ее в строке.

В прошлом я делал это на ATMEGA,где ISR может просто разрешить другим прерываниям запускать (включая себя снова) с помощью sei ().Оборачивая событие в флаг «все еще выполняется», оно не накапливается в стеке и не вызывает ... вы знаете:

if (!inFunction) { inFunction = true; doFunction(); inFunction = false; }

Я не думаю, что это можно сделать -по крайней мере так же легко - на XMEGA, благодаря контроллеру прерываний PMIC.Похоже, что флаги прерывания могут быть сброшены только путем выполнения RETI.

Итак, я подумал, что было бы удобно, если бы я мог убедить GCC произвести хвостовой вызов из прерывания.Это немедленно выполнило бы событие, одновременно очистив прерывания.

Это было бы достаточно легко сделать в ассемблере, просто нажмите адрес и IRET.(Ну, немного стеков, потому что ISR, но, да.) Но я предполагаю, что это будет хак в GCC, возможно, пользовательская оболочка ASM вокруг «голой» функции?

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

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

Действительно, это проблема XY, и я это знаю.Я думаю, что хочу сделать X, но на самом деле мне нужен метод Y, о котором я просто не знаю.

Один лучший способ - установить флаг, а затем позволить main () с ним справиться, когда он обойдётк этому.К сожалению, у меня есть функции блокировки в main () (обработка пользовательского ввода через последовательный порт), так что это потребует работы и станет беспорядком.полное переключение задач - но, черт возьми, если я собираюсь эффективно внедрить ОСРВ, или вытащить ее, только для этого.Должен быть лучший способ.

Я действительно покрыл все возможности и загнал себя в угол?Должен ли я пойти на компромисс и выбрать один из них?Я что-то пропустил лучше?

1 Ответ

0 голосов
/ 21 сентября 2018

Есть больше возможностей для решения этой проблемы.

1. Включите прерывание по таймеру как с низким приоритетом .Таким образом, прерывания со средним и высоким приоритетом смогут прерывать это прерывание с низким приоритетом и работать без изменений.

Это похоже на использование sei(); в обработчике прерываний в более старых процессорах (без PMIC).

2.a Установить флаг (переменная) в прерывании.Опросить флаг в основном цикле.Если флаг установлен, очистите его и сделайте все возможное.

2.b Установите таймер, но не включайте его прерывание. Опрос флаг прерывания OVF вашего таймера в основном цикле.Если флаг установлен, снимите его и выполняйте свои действия.

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

...