Режимы Thread и Handler
Ядро Cortex-M всегда находится в одном из двух режимов: выполняет основную программу или обрабатывает исключение. С режимом связаны и права кода, и выбор стека, а переключает их регистр CONTROL и механизм исключений.
Обновлено Редакция GAW
Thread и Handler — два режима ядер Cortex-M. В режиме Thread выполняется основная программа, и в него ядро выходит из сброса. В режим Handler ядро переходит при входе в обработчик любого исключения и возвращается в Thread, когда все исключения обслужены (DUI 0552A, разд. 2.1.1). Переход делает аппаратура: программа не переключает режим сама, а только вызывает исключение и возвращается из него.
Режим, привилегии и стек
| Режим | Что выполняется | Привилегии | Стек |
|---|---|---|---|
| Thread | программа | привилегированный или нет — бит nPRIV регистра CONTROL | MSP или PSP — бит SPSEL |
| Handler | обработчики исключений | всегда привилегированный | всегда MSP |
По табл. 2-1 и 2-10 DUI 0552A. Непривилегированный код ограниченно пользуется командами MRS и MSR, не может выполнять CPS, не имеет доступа к SysTick, NVIC и блоку управления системой, а блок защиты памяти может закрыть ему и области памяти. Записи в регистры масок из непривилегированного кода игнорируются (ARMv7-M ARM, B1.4.3).
Менять регистр CONTROL может только привилегированный код. Поэтому вернуть себе права непривилегированный код может лишь через исключение — обычно вызов SVC, обработчик которого работает в режиме Handler.
Два стека
В режиме Handler всегда используется основной стек MSP. В режиме Thread бит SPSEL выбирает MSP или стек процесса PSP (подробнее — в статье «Стек»). Arm рекомендует, чтобы потоки ОС работали на PSP, а ядро ОС и обработчики — на MSP. После смены стека командой MSR сразу ставят ISB, чтобы следующие команды уже работали с новым указателем (разд. 2.1.3):
__set_PSP((uint32_t)&task_stack[STACK_WORDS]);
__set_CONTROL(__get_CONTROL() | CONTROL_SPSEL_Msk); /* Thread mode uses PSP */
Функция CMSIS __set_CONTROL() сама ставит ISB после записи.
Переключать стек в середине функции на C опасно: её локальные переменные остались в старом стеке. ОС делают это при запуске первой задачи, а переключают задачи в обработчике PendSV.
У Cortex-M0 режимы те же, но регистр CONTROL выбирает только стек — уровней привилегий в описании этого ядра нет (DUI 0497A, разд. 2.1). Как режимы связаны с картой памяти и исключениями — в статье «Cortex-M3».
Частые вопросы
В каком режиме работает обычная программа на STM32?
В режиме Thread, привилегированно и со стеком MSP — так ядро выходит из сброса, и программа без ОС обычно так и остаётся. В режим Handler ядро переходит само на время обработчика любого исключения и возвращается в Thread, когда обработчиков больше нет.
Как непривилегированный код получает доступ к периферии ядра?
Только через исключение. Непривилегированный код не может менять регистр CONTROL и выполнять CPS, поэтому вызывает SVC. Обработчик SVCall работает в режиме Handler, всегда привилегированно, выполняет запрос или меняет бит nPRIV и возвращает управление.
Зачем нужен стек PSP?
Чтобы отделить стеки задач от стека ядра ОС и прерываний. Arm рекомендует такую схему: задачи в режиме Thread работают на PSP, у каждой свой стек, а обработчики всегда используют MSP. Переполнение стека задачи тогда не портит стек прерываний, а переключение задач сводится к смене PSP.
Источники
- Arm. Cortex-M3 Devices Generic User Guide, DUI 0552A, 2010 — разд. 2.1.1: режим Thread — выполнение приложения, в него ядро выходит из сброса; режим Handler — обработка исключений, по окончании всех исключений ядро возвращается в Thread; непривилегированный код ограниченно использует MRS и MSR, не может выполнять CPS, не имеет доступа к SysTick, NVIC и SCB, может иметь ограниченный доступ к памяти и периферии; в Thread уровень задаёт регистр CONTROL, в Handler выполнение всегда привилегированное; менять CONTROL может только привилегированный код, непривилегированный передаёт управление через SVC; разд. 2.1.2, табл. 2-1: в Handler всегда основной стек, в Thread — основной или стек процесса; табл. 2-10: CONTROL — бит 1 SPSEL (0 — MSP, 1 — PSP), бит 0 nPRIV (0 — привилегированный, 1 — непривилегированный); после смены стека через MSR нужна команда ISB; Arm рекомендует потокам ОС стек процесса, ядру ОС и обработчикам — основной стек; разд. 2.3.2: после сброса выполнение привилегированное, в режиме Thread
- Arm. ARMv7-M Architecture Reference Manual, ARM DDI 0403C_errata_v3, 2010 — B1.4.3: непривилегированные записи в регистры масок игнорируются
- Arm. CMSIS 6, CMSIS-Core cmsis_gcc_m.h, core_cm3.h (v6.4.0) — __set_CONTROL() выполняет MSR control и затем __ISB(); __set_PSP(); маски CONTROL_SPSEL_Msk и CONTROL_nPRIV_Msk
- Arm. Cortex-M0 Devices Generic User Guide, DUI 0497A, 2009 — разд. 2.1.1–2.1.3: у Cortex-M0 те же режимы Thread и Handler, регистр CONTROL выбирает только стек; уровней привилегий в описании ядра нет
Нашли ошибку?
Смотрите также
- СтекОбласть ОЗУ для адресов возврата и локальных переменных
- SVCallИсключение Cortex-M, которое вызывает команда SVC; через него программа обращается к ядру ОС
- Блок защиты памяти (MPU)Права доступа к областям памяти в Cortex-M
- PendSVИсключение Cortex-M, которое программа ставит в ожидание; в RTOS в нём переключают задачи
- Cortex-M3Регистры, карта памяти, bit-banding, NVIC, SysTick, MPU, старт, пример
- Регистры ядра Cortex-MR0–R12, SP, LR, PC, xPSR и специальные регистры: что в каждом