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

PendSV

Планировщику RTOS нужно переключить задачу, но делать это посреди обработчика прерывания нельзя: другие прерывания ещё ждут. Cortex-M решает задачу отдельным исключением PendSV — его ставят в очередь, а выполняется оно, когда все более важные обработчики уже закончили.

Обновлено Редакция GAW

PendSV (pendable service call) — системное исключение ядер Cortex-M, которое программа переводит в состояние ожидания, а процессор обслуживает, когда позволяет приоритет. Arm прямо называет его назначение: в среде ОС через PendSV переключают контекст, когда никакое другое исключение не активно (DUI 0553B, разд. 2.3.2). Номер исключения — 14, вектор лежит по смещению 0x38 таблицы векторов, приоритет настраивается.

Как это работает

ПараметрЗначение
Номер исключения14 (в CMSIS — IRQn = −2)
Запросзапись 1 в бит PENDSVSET (28) регистра ICSR, 0xE000ED04
Снятие запросабит PENDSVCLR (27) того же регистра
Приоритетполе PRI_14, биты 23:16 регистра SHPR3, 0xE000ED20
Активацияасинхронная

Источник: DUI 0553B, табл. 2-16, разд. 4.3.3 и 4.3.8.

Типичная схема в RTOS такая. Обработчик SysTick или прерывание от периферии решает, что пора сменить задачу, и выставляет PENDSVSET. Если в этот момент работают другие обработчики, PendSV ждёт. Когда ядро возвращается из последнего из них, оно входит в PendSV — и там, уже без конкуренции с прерываниями, сохраняет контекст текущей задачи и загружает следующую.

Что сохраняет обработчик

При входе в исключение ядро само кладёт в стек восемь слов: R0–R3, R12, LR, PC и xPSR — это кадр стека исключения. Остальные регистры R4–R11 в кадр не входят, поэтому обработчик PendSV сохраняет их программно в стек задачи, меняет указатель PSP и восстанавливает R4–R11 новой задачи. Возврат через EXC_RETURN довершает дело: ядро снимает со стека новой задачи её кадр и продолжает её выполнение.

Приоритет и NVIC

PendSV — системное исключение, поэтому его приоритет задаётся не в регистрах NVIC IPR, а в SHPR3. Если оставить его по умолчанию (0, то есть наивысший настраиваемый), переключение задач начнёт вытеснять обработчики прерываний. Рассчитать, как поля приоритета делятся на группу и подгруппу, помогает калькулятор приоритетов NVIC, а устройство исключений Cortex-M3 разобрано в статье о ядре Cortex-M3.

Частые вопросы

Почему PendSV в RTOS делают самым низким по приоритету?

Чтобы переключение задач не вклинивалось в обработчики прерываний. Исключение с низшим приоритетом выполняется только тогда, когда все остальные уже закончились, — как и советует Arm: использовать PendSV для переключения контекста, когда никакое другое исключение не активно (DUI 0553B, разд. 2.3.2). Приоритет задают полем PRI_14 регистра SHPR3.

Как вызвать PendSV из кода?

Записать 1 в бит 28 PENDSVSET регистра ICSR (адрес 0xE000ED04); в CMSIS это SCB->ICSR = SCB_ICSR_PENDSVSET_Msk. По руководству Arm это единственный способ перевести PendSV в ожидание. Исключение асинхронное: ядро может успеть выполнить ещё несколько команд, прежде чем войдёт в обработчик.

Чем PendSV отличается от SVC?

SVC — синхронное исключение: оно возникает ровно на команде SVC, и обработчик выполняется сразу, если позволяет приоритет. PendSV только ставится в очередь и ждёт, пока освободится процессор. В типичной RTOS через SVC запускают первую задачу и вызывают сервисы ядра, а через PendSV переключают задачи.

Источники

  1. Arm. Cortex-M4 Devices Generic User Guide, ARM DUI 0553B (ID012616) — разд. 2.3.2: PendSV — запрос системного обслуживания по прерыванию; в среде ОС его используют для переключения контекста, когда другие исключения не активны; табл. 2-16: номер исключения 14, приоритет настраиваемый, смещение вектора 0x38, активация асинхронная; разд. 4.3.3: регистр ICSR по адресу 0xE000ED04, бит 28 PENDSVSET — запись 1 переводит PendSV в ожидание, и это единственный способ это сделать, бит 27 PENDSVCLR снимает ожидание; разд. 4.3.8, табл. 4-23: SHPR3 по адресу 0xE000ED20, биты 23:16 PRI_14 — приоритет PendSV
  2. Arm. Armv7-M Architecture Reference Manual, ARM DDI 0403E.e (ID021621) — разд. B1.5: модель исключений Armv7-M — системные исключения с настраиваемым приоритетом, вытеснение, состояние ожидания (pending); асинхронные исключения переводятся в ожидание и обслуживаются по обычным правилам приоритета

Нашли ошибку?