Возврат к другой функции из режима обработчика - PullRequest
0 голосов
/ 07 февраля 2020

Когда я нахожусь в режиме обработчика из-за исключения, я оцениваю некоторые условия и решаю, возвращаться ли в режим потока к той же функции или к другой, просто чтобы вернуться к оригиналу после выполнения.

Изначально я хотел сделать то же самое с Cortex R4 и переключиться из режима прерывания в привилегированный режим.

mrs R1,CPSR       ; Save the Interrupt Mode registers
cps #19           ; Switch to privilege mode
 ....             ; do your thing
msr CPSR_CXSF, R1 ; Return to interrupt mode

Но сейчас я использую Cortex M7

Я пытался сделать

  OriginalLR = *(int*)(__get_PSP() + 0x18); 
  ptr_p = (int*)(__get_PSP() + 0x18);
  *ptr_p = MyDummyFunction;  

Затем в MyDummyFunction я набираю sh все регистры, "делаю свое дело" и восстанавливаю все регистры.

 asm(" STMFD R13!,{R0-R12}");
 ... ; doing my thing
 asm(" LDMFD R13!,{R0-R12}");

Но я понятия не имею, как вернуть, Если я выйду или BL, то это POP вещи из стека. Изменение P C кажется опасным.

Есть предложения? Я думаю, я не могу перейти из режима обработчика в режим потока внутри функции, как в Cortex R4?

1 Ответ

0 голосов
/ 11 февраля 2020

В отсутствие какой-либо дополнительной ясности относительно варианта использования этого, я могу дать только несколько возможностей для достижения этой цели.

В семействе Cortex-M обычно есть три основных различия между режимом потока и режимом обработчика (обратите внимание, что существуют различия между членами семейства Cortex-M):

  • Режим обработчика всегда является привилегированным. Режим потока может быть как привилегированным, так и непривилегированным, в зависимости от установки бита nPRIV в регистре CONTROL. nPRIV недоступен на Cortex-M0 и является необязательным на M0 +, но существует на M3, M4 и M4F.
  • Режим обработчика имеет более высокий приоритет, чем режим потока. Или, скорее, обработчики имеют более высокий приоритет, чем код не-обработчика, что равносильно одному и тому же.
  • В режиме обработчика всегда используется указатель основного стека (MSP), отраженный через r13 (SP). Режим потока можно настроить так, чтобы он отражал либо MSP, либо указатель стека процессов (PSP) через SP, используя бит SPSEL в регистре CONTROL. Я почти уверен, что все устройства Cortex-M имеют такое расположение - конечно, устройства Cortex-M0, -M3 и -M4F, с которыми я знаком, занимаются, и я не могу найти никаких ссылок на то, что они являются дополнительными. (Это средство разработано, чтобы помочь с реализацией переключений контекста, что она делает великолепно.)

Не совсем точно, почему вы хотите убедиться, что ваша «введенная» функция работает в режиме потока - будь то Вы можете sh понизить его приоритет, понизить его привилегию или использовать другой указатель стека. Итак, вот несколько вариантов.

Вариант 1: Ничего из вышеперечисленного

Если вам не нужно снижать приоритет введенной функции и вам не нужно менять стеки и вам не нужно запускать внедренную функцию с привилегиями, затем просто вызовите ее, прежде чем вернуться из обработчика. Конечно, он будет работать в режиме обработчика, но кого это волнует?

Вариант 2: речь идет о приоритете

Если вы хотите гарантировать, что ваша введенная функция может быть прервана, например, запросами на прерывание , но вы на самом деле не заботитесь о том, чтобы он запускался в режиме потока, и вы уверены, что обработчик PendSV не используется для других целей (это идеальное место для переключения контекста, так что если вы используете ОС, то, скорее всего, так и есть), тогда вы можете настроить свою функцию для внедрения в качестве обработчика PendSV.

В существующем обработчике установите бит PendSV в ICSR (управление прерываниями) и регистр состояния) в отображенной в памяти SCB (блок управления системой) вызовет запуск обработчика PendSV, и он обычно настроен как обработчик с самым низким приоритетом, поэтому он выполняется после завершения всех других ожидающих обработчиков. Обратите внимание, что бит PendSV сбрасывается автоматически, когда обработчик начинает выполнение.

Вариант 3: вам действительно нужен режим потока

Что ж, это можно сделать, но это сложно. Вот некоторые примеры препятствий, с которыми вы сталкиваетесь:

  • Совершенно возможно сунуть стек, чтобы заставить обработчик вернуться туда, откуда он не пришел. Вот что делает переключение контекста. Однако вам необходимо убедиться, что обработчик исключений никогда не будет вызван из обработчика прерываний, прежде чем пытаться это сделать.
  • В конце введенной функции управление каким-то образом должно быть восстановлено в функции, которая была прервана, вдоль с all его изменчивого контекста, включая флаги состояния и так далее. Предполагая, что вы не можете написать свою внедренную функцию так, чтобы гарантировать сохранение флагов состояния (что означает отсутствие сравнений или тестов!), Тогда в зависимости от конфигурации ваших привилегий это может быть сложно; APSR (часть регистра состояния программы, где хранятся флаги состояния) доступна для записи только из привилегированного кода.

Я бы предложил в качестве отправной точки (и я не проверял это), что если вы можете быть уверены, что ваш обработчик исключений может быть вызван только из потокового режима, вы можете:

  1. Сохраните значение указателя стека в потоковом режиме где-нибудь в безопасности.
  2. Создайте фиктивный фрейм стека и вставьте sh его в стек потокового режима, установив 'stacked' P C для принудительного возврата к вашей введенной функции.
  3. Возврат из обработчика, который приведет к возврату в потоковый режим и вызову введенной функции.
  4. Вместо конца введенной функции для возврата введите команду SV C, чтобы вызвать программный обработчик прерываний. Это можно сделать с C с использованием CMSIS. (Обратите внимание, что если вы не можете контролировать, как пишется внедренная функция, при создании фиктивного стекового фрейма вы можете инициализировать LR, чтобы принудительно перейти к инструкции SV C в конце введенной функции.)
  5. Напишите обработчик SV C, который восстанавливает сохраненный указатель стека в режиме потока. Когда этот обработчик вернется, исходная прерванная функция будет восстановлена.

Если вам нужно поработать с возможностью обработки обработчиками прерываний вашего обработчика исключений, вы можете реализовать вышеописанное в обработчике PendSV. Если это уже не используется ... в этом случае у меня нет идей.

Надеюсь, это даст вам отправную точку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...