SVC и SVCall
Задача в RTOS работает с ограниченными правами, а ядру ОС нужны привилегированные. Мост между ними — команда SVC: она синхронно вызывает исключение SVCall, и обработчик получает управление в привилегированном режиме. Номер нужного сервиса передаётся прямо в коде команды.
Обновлено Редакция GAW
SVC (supervisor call) — команда ядер Cortex-M, которая вызывает исключение SVCall. Её назначение Arm описывает так: в среде ОС приложения используют SVC, чтобы обратиться к функциям ядра и драйверам (DUI 0553B, разд. 2.3.2). В отличие от PendSV, исключение синхронное: оно возникает ровно на этой команде.
Параметры
| Параметр | Значение |
|---|---|
| Номер исключения | 11 (в CMSIS — IRQn = −5) |
| Вектор | смещение 0x2C в таблице векторов |
| Приоритет | поле PRI_11, биты 31:24 регистра SHPR2, 0xE000ED1C |
| Аргумент | 8 бит, 0–255, в коде команды |
| Кодировка | 16 бит: 0xDF и imm8 в младшем байте |
Источники: DUI 0553B, табл. 2-16 и 4-22, разд. 3.12.10; DDI 0403E, разд. A7.7.178.
Как передать номер сервиса
Процессор аргумент #imm не использует — его разбирает обработчик. При входе в исключение ядро кладёт в стек кадр исключения, и в нём есть адрес возврата: адрес команды, следующей за SVC. Команда занимает два байта, а номер — её младший байт, поэтому обработчик читает байт по адресу «сохранённый PC − 2». Аргументы для сервиса передают в R0–R3: они тоже лежат в кадре, и обработчик может вернуть результат, записав его в сохранённый R0.
Когда SVC превращается в HardFault
SVCall должно быть обслужено немедленно. Если его приоритет не выше текущего уровня выполнения — например, SVC вызвана из обработчика прерывания с более высоким приоритетом или при PRIMASK = 1, — ядро эскалирует исключение в HardFault (DDI 0403E, разд. B1.5). Это частая ошибка при переносе кода: функцию RTOS, построенную на SVC, вызывают из критической секции с запрещёнными прерываниями.
Где применяют
- Запуск планировщика. В обработчике SVC удобно переключить стек на PSP и перейти в режим потока — так можно стартовать первую задачу.
- Вызов привилегированных функций. Регистры разрешения и ожидания прерываний NVIC доступны только привилегированному коду (DUI 0553B, табл. 4-2), а обработчик SVCall выполняется с привилегиями.
- Защищённые сервисы. Номер в команде работает как номер системного вызова: одна точка входа, таблица функций внутри.
Устройство режимов и стеков Cortex-M разобрано в статье о ядре Cortex-M3, а настройка приоритетов исключений STM32 — в статье о прерываниях STM32.
Частые вопросы
Как обработчику узнать номер, указанный в SVC #n?
Процессор номер игнорирует, его достают программно. В стековом кадре лежит адрес возврата — адрес команды после SVC. Сама SVC 16-битная, номер — её младший байт (кодировка 0xDF imm8, DDI 0403E, разд. A7.7.178), поэтому номер читают как байт по адресу «сохранённый PC − 2». Какой стек смотреть, MSP или PSP, подсказывает бит 2 значения EXC_RETURN в LR.
Почему SVC внутри прерывания или при запрещённых прерываниях даёт HardFault?
SVCall — синхронное исключение: оно должно быть обслужено сразу. Если его приоритет не выше текущего уровня выполнения, обычное вытеснение невозможно, и ядро эскалирует его в HardFault. Arm приводит прямой пример: команда SVC при PRIMASK = 1 (DDI 0403E, разд. B1.5). Поэтому SVC вызывают из кода задач, а не из обработчиков с высоким приоритетом.
SVC и SWI — одно и то же?
Да. В старых версиях архитектуры Arm эта команда называлась SWI (software interrupt), ассемблер Armv7-M принимает старое написание как синоним (DDI 0403E, разд. A7.7.178).
Источники
- Arm. Cortex-M4 Devices Generic User Guide, ARM DUI 0553B (ID012616) — разд. 2.3.2: SVCall — исключение, которое вызывает команда SVC; в среде ОС приложения обращаются через SVC к функциям ядра и драйверам; табл. 2-16: номер 11, приоритет настраиваемый, смещение вектора 0x2C, активация синхронная; разд. 3.12.10: синтаксис SVC{cond} #imm, imm — 8-битное значение 0–255, процессор его игнорирует, обработчик может получить его через сохранённый в стеке PC; разд. 4.3.8, табл. 4-22: SHPR2 по адресу 0xE000ED1C, биты 31:24 PRI_11 — приоритет SVCall
- Arm. Armv7-M Architecture Reference Manual, ARM DDI 0403E.e (ID021621) — разд. A7.7.178: SVC — вызов системного супервизора, прежнее имя SWI; кодировка T1 — 16 бит 1101 1111 imm8, imm8 в младшем байте; разд. B1.5: SVCall всегда разрешено, приоритет настраиваемый; разд. B1.5, «Priority escalation»: если групповой приоритет ожидающего синхронного исключения, в том числе SVCall, не выше текущего, оно эскалируется в HardFault; пример — команда SVC при PRIMASK = 1
Нашли ошибку?
Смотрите также
- PendSVИсключение Cortex-M, которое программа ставит в ожидание; в RTOS в нём переключают задачи
- Кадр стека исключенияВосемь регистров, которые Cortex-M сам сохраняет в стек при входе в исключение
- HardFaultИсключение Cortex-M при необработанной ошибке
- Критическая секцияУчасток кода под запретом прерываний
- Cortex-M3Регистры, карта памяти, bit-banding, NVIC, SysTick, MPU, старт, пример
- Прерывания STM32Векторы и IRQn, приоритеты и HAL, EXTI и общие векторы, флаги, события, примеры