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

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

Ядро Cortex-M3 может работать в режиме нормального выполнения программы (режим Thread — TM) или обслуживания прерываний (режим Handler — HM). Это различие имеет решающее значение для приложений написанных на основе операционных систем.

Кроме того, различают два уровня с разными правами доступа к ключевым областям адресного пространства:

  • привилегированный режим (Privileged Level – RU),
  • пользовательский режим (Unpriviledged/User Level – UL).

Рис. 1. Иллюстрация режимов работы ядра Cortex-M3

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

Рис. 2. Микроконтроллер, работающий с прерыванием, всегда работает в привилегированном режиме (PL)

При работе с прерыванием микроконтроллер всегда работает в привилегированном (PL) режиме, даже если пользовательский режим (UL) установлен во время нормального выполнения программы.

Это соотношение показано на рис. 2, а на рис. 3 показана работа микроконтроллера с включенным режимом пользователя. Здесь видно, что ядро ​​Cortex-M3, работающее в режиме UL, при входе в службу прерываний переключается в режим PL, а при завершении службы прерываний возвращается в привилегированный (пользовательский) режим.

Рис. 3. Работа микроконтроллера в активном пользовательском режиме

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

Переход из режима пользователя в привилегированный режим невозможен напрямую. Приложение, работающее в операционной системе, не может отключить пользовательский режим, поскольку оно не имеет доступа к специальному управляющему регистру CONTROL. Запись в него с уровня приложения игнорируется. Изменения могут быть сделаны только во время обслуживания прерывания, которое осуществляется в режиме полной авторизации — PL. Внешний вид всего регистра CONTROL (со значениями по умолчанию показан на рис. 4.

Рис. 4. Строение регистра CONTROL

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

Стек

Стек — это физически область памяти, к которой обращается специальный регистр индикатора. Информация в стеке вводится в режиме LIFO (Last In First Out), это означает, что для чтения скрытых данных сначала необходимо загрузить новые данные из стека (рис. 5).

Рис. 5. Стековая адресация с использованием регистра R13

Доступ к стеку осуществляется с помощью команд удаления (POP) и вставки (PUSH) в стеке. После каждой операции PUSH регистр указателя (в случае ядра Cortex это регистр R13) уменьшается, то есть указывает на младший адрес. Аналогично, операция POP увеличивает регистр указателя стека. Микроконтроллеры STM32 являются 32-битными, поэтому стек увеличивается (или уменьшается) всегда на 4.

Стеки 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 нигде не будет показан. Обязательные для заполнения поля помечены *

*