Кажется, вы неправильно понимаете, как ввод и возврат исключений работает в Cortex-M. Когда вы запускаете инструкцию SVC
из потокового режима, процессор переходит в режим обработчика, как и для любого другого исключения.
Режим обработчика всегда привилегирован и всегда использует основной стек (MSP). Режим потока может быть либо привилегированным, либо непривилегированным в зависимости от бита nPRIV
(бит 0) в регистре CONTROL
, и может быть настроен на использование стека процессов (PSP), установив бит SPSEL
(бит 1) в регистр CONTROL
из потокового режима.
При входе в режим обработчика r0-r3
, r12
, lr
, pc
и xPSR
помещаются в активный стек (PSP или MSP (в зависимости от того, что используется) и возвращаемое значение исключения загружается в lr
. Стек переключен на MSP. В конце обработчика инструкция BX lr
(или эквивалентная) заставляет это значение использоваться в качестве цели ветвления, что автоматически вызывает восстановление предыдущего режима и стека, и выдает r0-r3
, r12
, lr
, pc
и xPSR
. Всплывающее окно pc
восстанавливает выполнение с того места, где произошло прерывание.
Важной особенностью этого механизма является то, что он на 100% совместим с ARM ABI. Другими словами, можно написать обычную функцию и использовать ее в качестве обработчика исключений, просто поместив адрес функции в соответствующее место в таблице векторов прерываний. Это потому, что возвращение в конце функции выполняется с помощью BX lr
или его эквивалента, который является точно такой же инструкцией, которая запускает возврат из режима обработчика.
Итак, чтобы написать обработчик SV C, который делает При использовании обратных вызовов необходимо:
- Определить, какой стек использовался, когда была выдана инструкция SV C
- Выкопать сложенную
pc
, чтобы найти адрес самой инструкции SV C и извлечение 8-битной константы из инструкции SV C - Используйте константу, чтобы определить, какой обратный вызов вызывать
- Ветвь к ( не вызов) соответствующий обратный вызов
обратный вызов может быть совершенно обычной функцией. Когда он возвращается, он запускает возврат из режима обработчика, потому что соответствующий код возврата исключения все еще будет в lr
.
Обработчик, который делает все это, представлен в Руководстве M3, глава 10.
Если требуется, чтобы обратный вызов получал аргументы, это немного сложнее, но я могу расширить свой ответ, если хотите. Обычно обратные вызовы обработчика выполняются в режиме обработчика (в этом и заключается смысл SV C). Если по какой-то причине вам требуется, чтобы обратный вызов выполнялся без привилегий, это еще более сложно; хотя есть пример в главе 23 руководства M3. В комментариях вы говорите, что не хотите «управлять вложенными прерываниями», но действительно вложенные прерывания просто управляют собой.