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

Запуск FreeRTOS

646

24 osTimerStart(stim1, 500);

25

26 osKernelStart();

27

28/* Бесконечный цикл */

29while (1);

30}

31

32void blinkFunc(void const *argument) {

33HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);

34}

Код действительно говорит сам за себя. Строки [22:24] определяют новый таймер с именем stim1. Этот таймер сконфигурирован на выполнение процедуры blinkFunc() по истечению его отсчета и запускается с задержкой в 500 мс. Это заставит светодиод LD2 платы Nucleo мигать с частотой 2 Гц.

23.7.1. Как FreeRTOS управляет таймерами

Как вы видели в предыдущем примере, наше приложение не использует потоки. Так кто именно заботится о таймерах? FreeRTOS использует централизованный поток с именем демон ОСРВ, англ. RTOS daemon (или же поток обслуживание таймеров, англ. timer service thread), который автоматически вызывает процедуры обратного вызова по истечении таймера. Этот поток является обычным потоком, приоритет которого определяется макросом configTIMER_TASK_PRIORITY, а его стек имеет размер, определенный макросом configTIMER_TASK_STACK_DEPTH. Кроме того, он имеет внутренний пул объектов таймеров, размер которого определяется макросом configTIMER_QUEUE_LENGTH.

Еще один интересный аспект – как FreeRTOS вычисляет время внутри самой себя. FreeRTOS измеряет время как функцию частоты тиков, которая, в свою очередь, определяется частотой переполнения таймера, выбранного в качестве генератора временного отсчета. Это означает, что если мы используем таймер SysTick, сконфигурированный на переполнение через 1 мс, то внутренние программные таймеры имеют разрешение 1 мс (что соответствует 1 тику). Следовательно, значение millisec, передаваемое процедуре osTimerStart(), преобразуется в тики. Это означает, что в случае Примера 5, если время тика равно 1 мс, то 500 мс будут равны 500 тикам. Если время тика установлено на 500 мкс, задержка в 500 мс преобразуется в 1000 тиков.

23.8.Пример из практики: Управление энергосбережением с ОСРВ

Это довольно сложная тема, требующая знания многих концепций, лежащих в основе ОСРВ. Кроме того, требуется хорошее знание концепций, продемон-

стрированных в Главе 20. Неопытные пользователи могут смело пропустить эту часть.

В Главе 19 мы проанализировали возможности пониженного энергопотребления, предлагаемые микроконтроллерами STM32. Мы видели, что, в особенности для микроконтроллеров, принадлежащих серии STM32L, они предлагают несколько режимов

Запуск FreeRTOS

647

питания, полезных для снижения энергопотребления микроконтроллера, когда не требуется слишком много активной работы. Мы также видели, что микроконтроллер переходит в один из режимов пониженного энергопотребления на добровольной основе, вызывая одну из двух специальных ассемблерных инструкций: WFI или WFE. Если мы знаем, что микропрограмма не делает ничего важного в течение «длительного» периода времени, то можно перейти в режим пониженного энергопотребления, ожидая внешнего прерывания или события.

Когда мы используем ОСРВ, труднее сказать, «когда требуется выполнить не так много работы». До сих пор мы видели, что ОСРВ планирует особый поток, когда все другие потоки находятся в состояниях «заблокирован» или «приостановлен»: холостой поток idle. Это означает, что ОСРВ всегда должна находить способ что-то делать (просто потому, что процессор никогда не останавливается), если только мы не перейдем в режим пониженного энергопотребления, остановив ядро микроконтроллера.

Поэтому ОСРВ является источником «утечек электроэнергии», если мы не найдем решение, которое приостановит ее выполнение. Существуют два способа перевода микроконтроллера в режим пониженного энергопотребления, когда мы используем ОСРВ: один подходит для того, чтобы всего лишь «вздремнуть», другой – для более продолжительных и более глубоких спящих режимов. Давайте проанализируем их.

23.8.1. Перехват холостого потока idle

До сих пор мы видели, что ISR, связанная с таймером, используемым в качестве генератора временного отсчета для ОСРВ (обычно таймер SysTick), управляет действиями ОСРВ. Каждые 1 мс таймер SysTick опустошается, и его ISR передает управление планировщику ОС, который устанавливает следующий поток на выполнение37. Если ни один поток не находится в состоянии «готов к выполнению», то ОС выполняет холостой поток idle, пока другой поток не станет готовым к выполнению. Это означает, что, когда запланирован холостой поток idle, вероятно, самое время перевести микроконтроллер в спящий режим, чтобы уменьшить потребление энергии.

По этой причине FreeRTOS дает пользователю возможность определять перехват потока idle (idle hook), то есть функцию обратного вызова, вызываемую в холостом потоке idle. Чтобы включить перехват, мы должны определить макрос configUSE_IDLE_HOOK в файле FreeRTOSConfig.h и установить его равным 1. Далее мы можем определить функцию vApplicationIdleHook(void) где-нибудь в нашем исходном коде.

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

void vApplicationIdleHook( void ) {

// Предполагается, что __HAL_RCC_PWR_CLK_ENABLE() вызывается в другом месте

HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFE);

}

37 Такое поведение разрешено, когда алгоритмом планирования является приоритетное вытесняющее пла-

нирование с квантованием времени, согласно таблице 2.