Переключение контекста внутри ISR на Cortex-M
Я пытаюсь написать круговой планировщик barebones для Cortex-M, используя цепочку инструментов CodeSourcery GCC. Мой планировщик использует SysTick для запуска прерывания после истечения временного среза, и переключение контекста происходит внутри ISR. Чтобы все было просто, я использую только основной указатель стека (MSP) для всего.
Я застрял в определении того, как обрабатывать загрузку нового контекста в Cortex-M3. Согласно техническому справочному руководству Cortex-M3 (TRM) процесс помещает регистры PC, LR и status в текущий стек на входе в ISR.
Если я нажму остальные регистры, чтобы сохранить контекст текущей задачи и загрузить новое значение SP из блока управления следующей задачи, как я буду восстанавливать остальную часть его контекста?
согласно тому, что я понимаю, мне нужно вытащить регистры, которые я нажимаю (скажем, {r4-r11}), и процессор вытолкнет остальные (включая обратный адрес новая задача (LR) и регистры состояния) автоматически при возврате ISR. Поэтому я предполагаю, что мне просто нужно выполнить BX
после того, как я закончу переключать задачи?
вот что он говорит на TRM:
исключения возвращаются, когда одна из следующих инструкций загружает значение 0xFFFFFFFX в ПК, когда 1) POP/LDM, который включает загрузку ПК 2) LDR с ПК в качестве назначения 3) BX с любым регистром.
Как я могу идти о загрузке Значение EXC_RETURN? Должен ли я просто нажать его на стек (как это, предположительно, делает здесь)? Если у меня выскочил регистры я толкнул через программное обеспечение, как кора идти о popping регистрирует его спас? В общем, как восстановить контекст задачи?
Я пробовал читать ссылки TRM и других ARM, но они кажутся неясными.
3 ответов
Это действительно довольно сложная. Я пишу книгу об операционной системе FreeRTOS, работающей на ядрах Cortex-M. Я написал об этом главу. Из чтения вашего вопроса я считаю, что эта глава поможет ты:
чтение немного больше и некоторая помощь на IRC-канале #ARM позже я смог понять механизм возврата исключений. Вот что я понимаю.
Как упоминалось в cm3 TRM, ядро выталкивает регистры r0-r3, r12 вместе со статусом, LR и ПК в текущий стек процессов при регистрации исключения. Таким образом, при записи исключения стек содержит 8 слов, которые включают LR, содержащий адрес для возврата. Механизм pop оборудования существенно отменяет то же действие, т. е. он выскакивает последние 8 слов, во время которых он загружает LR в ПК, чтобы вернуться к прерванной функции.
таким образом, контекст может быть переключен просто путем перемещения указателя стека в соответствующее место, так что текущий кадр стека напоминает кадр стека задачи, которая только что была прервана, т. е. содержит точные слова в том же порядке.
при записи исключения и после сохранения регистров в стеке LR загружается со значением EXC_RETURN. Это значение содержит специальные флаги состояния для указания условий возврата. Это также используется для указания конца прерывания. То есть, если ISR должен вернуться к задаче и переключить указатель стека с текущего (MSP) на PSP, он может загрузить LR с соответствующим EXC_VALUE (указанным в TRM) и просто сделать BX LR
для переключения состояний.
вот фрагмент кода, который делает именно то, что вам нужно - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv7-M/ARMv7-M-PendSV_Handler.cpp- он работает, как вы описали:
- запись исключения автоматически складывает некоторые регистры,
- вы вручную складываете оставшиеся регистры,
- вы переключаете SP,
- вы разблокируете" оставшиеся " регистры,
- исключения возврата unstacks остальные реестры.