Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2740
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать
configMAX_SYSCALL_INTERRUPT_PRIORITY
config-

Запуск FreeRTOS

644

Несмотря на то что уровень CMSIS-RTOS предназначен для абстрагирования этой двойной системы API-интерфейсов, мы должны уделять особое внимание вызову API-функций FreeRTOS из процедур ISR в микроконтроллерах на базе Cortex-M3/4/7. Дело в том, что данные ядра позволяют выборочно маскировать прерывания на уровне приоритета. В Главе 7 мы видели, что регистр BASEPRI позволяет выборочно запрещать выполнение ISR, маскируя все IRQ, имеющие приоритет ниже заданного значения. FreeRTOS использует этот механизм, чтобы разрешить выполнение прерываний с более высоким приоритетом, которые, как предполагается, являются непрерываемыми, приостанавливая при этом прерывания с более низким приоритетом. Это означает, что небезопасно вызывать API-функции FreeRTOS из всех ISR, но безопасно вызывать функции FreeRTOS только из тех ISR, которые имеют заданный (или более низкий) уровень приоритета.

Мы можем установить этот максимальный уровень приоритета, определив макрос

configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY36 в файле FreeRTOSConfig.h. CubeMX авто-

матически выполняет эту операцию за нас, и обычно максимальный уровень приоритета устанавливается равным 5. При разрешении IRQ с использованием CubeMX следует соблюдать особую осторожность: даже если свежие выпуски CubeMX, как кажется, правильно обрабатывают этот аспект, всегда следите за тем, чтобы ISR, которая вызывает функции FreeRTOS, была сконфигурирована с приоритетом, равным

LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY или ниже.

Несмотря на то, что этот макрос определяется также и в проектах, сгенерированных CubeMX для микроконтроллеров STM32F0/L0, он не имеет практического значения, поскольку платформозависимый код FreeRTOS для этих семейств использует регистр PRIMASK для маскирования всех прерываний (ядра Cortex-M0/0+ не предлагают способа выборочного запрета IRQ). Поэтому этот макрос просто игнорируется.

Наконец, важно помнить, что FreeRTOS спроектирована так, что прерывание от тика (то есть IRQ, связанный с таймером, который действует как генератор временного отсчета для ядра) должно быть установлено на самый низкий возможный приоритет, который равен 7 в семействах STM32F0/L0 и 15 для всех остальных микроконтроллеров. Макрос

configLIBRARY_LOWEST_INTERRUPT_PRIORITY в файле FreeRTOSConfig.h устанавливает его, и

настоятельно рекомендуется оставить его как есть.

23.7. Программные таймеры

Программные таймеры – это предоставляемый ОСРВ способ планирования выполнения процедур на временной основе. Программные таймеры реализуются и управляются ядром FreeRTOS. Они не требуют специальной аппаратной поддержки (за исключением таймера, используемого в качестве генератора тиков для ОС) и не имеют ничего общего с аппаратными таймерами. Более того, они не способны обеспечить такую же точность,

36 Если вы прочитаете официальную документацию FreeRTOS, то увидите, что макрос, используемый для установки максимального уровня приоритета прерывания, – configMAX_SYSCALL_INTERRUPT_PRIORITY. Однако, поскольку FreeRTOS является переносимой среди нескольких производителей интегральных схем, уровень приоритета, заданный в этом макросе, является точным значением регистра IPR, который принимает только старшие 4 бита в микроконтроллере STM32 (например, приоритет, равный 0x2, должен быть задан как 0x20). Инженеры ST определили макрос configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, чтобы мы могли задать уровень приоритета в соответствии с соглашением HAL (в форме LSB), в то время как

определен следующим образом:

#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - \ configPRIO_BITS) )

Запуск FreeRTOS

645

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

Программные таймеры являются необязательной функцией во FreeRTOS, и их необходимо включить, установив макросу config_USE_TIMERS значение 1 в файле FreeRTOSConfig.h. Когда мы включаем таймеры, FreeRTOS также требует, чтобы мы определили

макросы configTIMER_TASK_PRIORITY, configTIMER_QUEUE_LENGTH и config-

TIMER_TASK_STACK_DEPTH. Мы рассмотрим роль этих макросов в ближайшее время.

На уровне CMSIS-RTOS программный таймер определяется с помощью макроса osTimerDef(), который принимает имя таймера и указатель на функцию обратного вызова. Программный таймер эффективно создается функцией

osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument);

которая позволяет указать тип таймера и необязательный аргумент для передачи в процедуру обратного вызова. API-интерфейс CMSIS-RTOS предоставляет два вида программных таймеров: интервальные таймеры (one-shot timers), то есть таймеры, выполняющие обратный вызов только один раз, и периодические таймеры (periodic timers), которые действуют как аппаратные таймеры STM32, которые перезапускают отсчет после их переполнения.

Чтобы запустить таймер, мы используем функцию

osStatus osTimerStart(osTimerId timer_id, uint32_t millisec);

где параметр millisec представляет собой период таймера. Чтобы остановить его, мы используем функцию

osStatus osTimerStop(osTimerId timer_id);

Наконец, таймер динамически выделяется ОС и должен быть уничтожен, когда он больше не нужен с помощью функции

osStatus osTimerDelete(osTimerId timer_id);

В следующем примере показано наше вездесущее мигающее приложение, созданное с использованием программного таймера.

Имя файла: src/main-ex5.c

13int main(void) {

14osTimerId stim1;

16 HAL_Init();

17

18 Nucleo_BSP_Init();

19

20 RetargetInit(&huart2);

21

22osTimerDef(stim1, blinkFunc);

23stim1 = osTimerCreate(osTimer(stim1), osTimerPeriodic, NULL);