Главная » Статьи » Секреты Cortex-M3 – режимы работы ядра

Секреты Cortex-M3 – режимы работы ядра

Стеки MSP и PSP

Регистр R13 является указателем стека — точнее, двух. В зависимости от установки второго бита в специальном регистре управления CONTROL (Рис. 4) он может указывать на системный стек MSP (Main Stack Pointer) или на пользовательский стек PSP (Process Stack Pointer). Поскольку указатель стека объединен в банк, R13 может указывать только один стек за раз (MSP или PSP) — Рис. 6. Кроме того, при обработке прерывания микроконтроллер всегда использует стек MSP.

Рис. 6. В любой момент времени R13 может указывать только один стек (MSP или PSP)

При описании режимов работы микроконтроллеров STM32 было упомянуто, что после запуска система всегда работает в привилегированном режиме. Следствием этого является то, что индикатор стека R13 также указывает системный стек MSP сразу после запуска микроконтроллера.

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

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

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

Рис. 7. Когда используются оба стека, пользовательский стек PSP используется для хранения информации о прерванном процессе, а MSP используется только для обработки прерываний.

Когда микроконтроллер работает в привилегированном режиме, доступ (или запись) к обоим стекам возможен напрямую, используя специальный регистр инструкции чтения (MRS) или записи (MSR). Чтение и запись стека MSP и PSP на ассемблере может выглядеть так:

MRS r0, PSP; Записать PSP в R0
IAS PSP, r0; Записать R0 в PSP
MRS r0, MSP; Чтение MSP в R0
IAS MSP, r0; Записать R0 в MSP

Конечно, приведенные выше инструкции могут быть сохранены с использованием функций, определенных STMicroelectronics, которые были объявлены как макросы ассемблера. В этой ситуации чтение стека пользователя выполняется с использованием кода, показанного в примере 1.

Пример 1. Пример чтения пользовательского стека

Value_PSP = __MRS_PSP ();

Однако процедура записи в стек PSP состоит из вызова соответствующего фрагмента кода ассемблера:

__MSR_PSP ((u32) NEW_VALUE);

Аналогично, запись и чтение стека MSP:

MSP_value = __MRS_MSP ();
__MSR_MSP ((u32) NEW_VALUE);

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

Режим пользователя и PSP

Раздельное использование механизма уровня привилегий и модели с двумя стеками, безусловно, полезно, но значительное увеличение возможностей достигается путем их объединения. В примере 2 показана часть программы, которая отвечает за включение стека пользовательского режима и эксплуатации PSP. Когда эти операции завершены,  вызывается прерывание из системного исключения SVC.

Пример 2. Фрагмент программы, отвечающей за включение режима пользователя и обработку стека PSP

// инициализация PSP
for(Index = 0; Index < 0x200; Index++) 
PSPMem [Index] = 0x00;
__MSR_PSP ((u32) PSPMem + 0x200);
// Выбрать PSP и режим пользователя
__MSR_CONTROL (0x03);
// Генерируем SVC, возвращаемся в привилегированный режим
__SVC ();

Функция обработки прерываний SVC отключает режим пользователя. Вызов прерывания является необходимой процедурой для изменения уровня привилегий. Как уже было написано ранее, его переход из режима пользователя в привилегированный режим возможен только в функции обработки прерываний. Это иллюстрируется примером функции обработки прерываний SVC:

void SVCHandler (void)
{
__MSR_CONTROL (0);
}

Инструкция внутри тела функции предназначена для ввода значения 0 в специальный регистр управления, что соответствует обнулению битов CONTROL [0] и CONTROL [1], которые отвечают за текущий уровень привилегий и используемый стек.

Системные исключения

Контроль задач, выполняемых STM32, значительно облегчается благодаря трем системным исключениям, доступным в архитектуре Cortex. Их конечная задача — работать под управлением операционной системы, хотя в приложениях без ОС их также можно использовать, чтобы обеспечить больший контроль и стабильность работы.

Для переключения контекста циклической задачи был создан 24-битный системный таймер SysTick. Его задача — генерировать прерывания через указанные интервалы, а его функция обработки может быть просто задействована в переключении контекста задачи.

Исключение SVC (система SerVice Call)

В хорошо спроектированной операционной системе работающее в ней приложение не может напрямую ссылаться на аппаратное обеспечение. Ссылаясь на это предложение в конкретном случае, можно сказать, что пользовательское приложение не может работать с портами ввода/вывода, кроме как через операционную систему.

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

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

PendSV исключение

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

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

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

PendSV и SysTick

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

Оставить комментарий

Ваш email нигде не будет показанОбязательные для заполнения поля помечены *

*