STM32CubeMx. Быстрый старт с FreeRTOS для STM32.

Давно не было статей с использованием FreeRTOS на нашем сайте. Что еще более удивительно, если учесть, что в повседневной жизни эта ОС используется регулярно. Так что сегодня без лишних слов и предисловий создадим базовый пример с поддержкой FreeRTOS для STM32. Прошли те времена, когда для включения ОС в свой проект приходилось перетаскивать кучу файлов, некоторые из которых оказывались несовместимы, некоторых просто не хватало… В STM32CubeMx все намного менее интересно и делается в пару кликов. В общем, приступаем!

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

  • 1 мс
  • 10 мс
  • 50 мс
  • 100 мс

Конкретные значения могут зависеть уже от конкретных целей конкретного проекта. И далее вся работа распределяется по этим task’ам. Соответственно, те действия, которые необходимо выполнять максимально часто вызываются из задачи, период вызова которой равен 1 мс. Например, сохранение значений АЦП для последующей обработки. Другие же действия напротив нужно выполнять намного реже, к примеру, обновлять информацию на дисплее. И в итоге вся программа распределяется по этим временным уровням.

Вот сегодня и реализуем базовый проект для STM32 с поддержкой FreeRTOS и нескольких задач. Пусть task’и будут вызываться каждые 1 мс, 10 мс и 50 мс. По аналогии можно будет легко и быстро добавить и другие.

Запускаем STM32CubeMx. Сразу уточню – не будем подробно погружаться во все нюансы настройки FreeRTOS и рассматривать каждую конкретную опцию, иначе получится не статья, а книга 🙂 Максимально быстрый старт! Если возникнут какие-либо вопросы, смело задавайте их в комментариях или на форуме, я буду рад помочь!

Итак, первым делом активируем FreeRTOS:

Использование FreeRTOS в STM32CubeMx.

Но тут сразу же есть важный нюанс. При использовании FreeRTOS, в качестве базового таймера для HAL рекомендуется выбрать не SysTick (стоит по умолчанию), а другой. Для этого переходим в категорию SYS и меняем SysTick на один из свободных таймеров:

Time base source for HAL.

Поскольку мы уже условились делать базовый проект, то оставляем на этом этапе все настройки FreeRTOS без изменений:

Настройки FreeRTOS для STM32.

Но добавляем наши задачи в разделе Tasks and Queues и задаем их приоритет – Normal:

Создание задачи в STM32CubeMx.

Полностью аналогичным образом добавляем остальные задачи:

Задачи FreeRTOS для микроконтроллера STM32.

Все готово, генерируем, открываем и собираем проект! Видим, что Cube создал наши task’и:

/* creation of Task1ms */
Task1msHandle = osThreadNew(Task1msHandler, NULL, &Task1ms_attributes);

/* creation of Task10ms */
Task10msHandle = osThreadNew(Task10msHandler, NULL, &Task10ms_attributes);

/* creation of Task50ms */
Task50msHandle = osThreadNew(Task50msHandler, NULL, &Task50ms_attributes);

Но сейчас единственное, что связывает эти функции с нашим планом вызывать их через равные промежутки времени – это их название. Так что необходимо доработать непосредственно код функций. И для того, чтобы обеспечить периодичность выполнения task’ов мы будем использовать функцию:

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement)
  • Первый аргумент хранит значение времени, соответствующее моменту, когда задача была разблокирована в предыдущий раз. При первом вызове функции vTaskDelayUntil() необходимо инициализировать эту переменную текущим значением времени, а в дальнейшем функция сама будет обновлять это значение.
  • Второй аргумент – в нем мы уже задаем нужный нам период. В итоге функция vTaskDelayUntil() заблокирует нашу задачу до момента времени, равного (pxPreviousWakeTime + xTimeIncrement).

Теперь реализуем все на практике. Подключаем:

#include "task.h"

Для task’а, который работает с периодом 10 мс получаем следующее:

void Task10msHandler(void *argument)
{
	/* USER CODE BEGIN Task10msHandler */
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;

	xLastWakeTime = xTaskGetTickCount();
	/* Infinite loop */
	for(;;)
	{
		// Add code here
    
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
	}
	/* USER CODE END Task10msHandler */
}

А непосредственно свой код мы добавляем перед вызовом vTaskDelayUntil(), внутри цикла for(;;). Здесь значение 10 мс задается в строке:

const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;

Абсолютно аналогично делаем и для других наших задач, меняя только значение периода. Кроме того, давайте добавим счетчики, которые будут инкрементироваться при вызове каждого из task’ов:

/* USER CODE BEGIN PV */
uint32_t task1msCnt = 0;
uint32_t task10msCnt = 0;
uint32_t task50msCnt = 0;

/* USER CODE END PV */

И итоговый код, например, для task’а 50 мс:

void Task50msHandler(void *argument)
{
	/* USER CODE BEGIN Task50msHandler */
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 50 / portTICK_PERIOD_MS;

	xLastWakeTime = xTaskGetTickCount();
	/* Infinite loop */
	for(;;)
	{
		// Add code here
		task50msCnt++; 
    
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
	}
	/* USER CODE END Task50msHandler */
}

Вот такой механизм для организации периодических задач в FreeRTOS на контроллере STM32. Давайте соберем проект и проверим, как все это работает. Индикацией для нас будут служить счетчики вызовов task’ов:

Пример использования FreeRTOS для STM32.

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

Ссылка на полный проект – MT_FreeRTOS_Base.

Поделиться!

Подписаться
Уведомление о
guest
2 комментариев
старее
новее большинство голосов
Inline Feedbacks
View all comments
Srl
Srl
9 дней назад

Хорошая статья. Спасибо. Ждем новых статей по этой теме..

Присоединяйтесь!

Profile Profile Profile Profile Profile
Vkontakte
Twitter

Язык сайта

Ноябрь 2020
Пн Вт Ср Чт Пт Сб Вс
 1
2345678
9101112131415
16171819202122
23242526272829
30  

© 2013-2020 MicroTechnics.ru