Переключение контекста внутри 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. Я написал об этом главу. Из чтения вашего вопроса я считаю, что эта глава поможет ты:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here


чтение немного больше и некоторая помощь на 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 остальные реестры.