STM Урок 54. System Workbench. FREE RTOS

 

 

 

Урок 54

System Workbench. FREE RTOS

 

 

Сегодня мы продолжим работу с бесплатной средой программирования System Workbench for STM32.

На прошлом занятии мы уже создали собственный проект и попытались помигать светодиодами и нам это удалось.

А теперь мы попытаемся помигать светодиодами уже с использованием ОС.

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

И также, как и для Keil, мы попытаемся не тратить время на создание и настройку нового проекта, а используя предыдущий проект, преобразовать его, но при этом не запортить первый.

Создадим новую папку для проекта с другим именем, например Blink_FREERTOS и скопируем туда из предыдущего проекта только проект Cube MX — Blink.ioc. Переименуем его в Blink_FREERTOS.ioc и подправим внутри, также как мы делали и раньше. Также скопируем в папку папки Inc и Src и файл .mxproject

 

ProjectManager.ProjectFileName=Blink_FREERTOS.ioc

ProjectManager.ProjectName=Blink_FREERTOS

ProjectManager.StackSize=0x4000

ProjectManager.TargetToolchain=SW4STM32

ProjectManager.ToolChainLocation=G\:\\ISH\\ARM\\MYLESSON\\CUBE\\F767\\WB\\Blink_FREERTOS

,,,,,,,,,,

board=Blink_FREERTOS

 

В файле .mxproject также исправим имена

 

HeaderPath=G:/ISH/ARM/MYLESSON/CUBE/F767/WB/Blink_FREERTOS/Inc

HeaderFiles=stm32f7xx_it.h;stm32f7xx_hal_conf.h;main.h;

SourcePath=G:/ISH/ARM/MYLESSON/CUBE/F767/WB/Blink_FREERTOS/Src

        Откроем Blink_FREERTOS.ioc в Cube MX и включим FreeRTOS

image00

 

Зайдём в Configuration, зайдём в свойства FreeRTOS и включим там ещё 4 задачи кроме основной

 

image02

 

Сгенерируем проект и вернёмся в WB. Также его импортируем туда, как и на предыдущем занятии предыдущий проект.

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

Если проект сейчас прошить, то светодиоды мигать не будут, так как мы до бесконечного цикла уже не дойдём. Код надо будет разместить в задачах, а из бесконечного цикла удалить. Мы попробуем помигать пятью парами соседних светодиодов в разных задачах с разной задержкой и увидим независимость друг от друга пяти отдельных процессов. Задержки будут уже выглядеть также по-другому. Разница в задержках в каждом потоке будет всего лишь в одну милисекунду, тем не менее результат будет очевиден

 

void StartDefaultTask(void const * argument)

{

  /* USER CODE BEGIN 5 */

  /* Infinite loop */

  for(;;)

  {

          LED02RESET();

          LED01SET();

          osDelay(100);

          LED01RESET();

          LED02SET();

          osDelay(100);

  }

  /* USER CODE END 5 */ 

}

/* StartTask02 function */

void StartTask02(void const * argument)

{

  /* USER CODE BEGIN StartTask02 */

  /* Infinite loop */

  for(;;)

  {

          LED04RESET();

          LED03SET();

          osDelay(99);

          LED03RESET();

          LED04SET();

          osDelay(99);

  }

  /* USER CODE END StartTask02 */

}

/* StartTask03 function */

void StartTask03(void const * argument)

{

  /* USER CODE BEGIN StartTask03 */

  /* Infinite loop */

  for(;;)

  {

          LED06RESET();

          LED05SET();

          osDelay(98);

          LED05RESET();

          LED06SET();

          osDelay(98);

  }

  /* USER CODE END StartTask03 */

}

/* StartTask04 function */

void StartTask04(void const * argument)

{

  /* USER CODE BEGIN StartTask04 */

  /* Infinite loop */

  for(;;)

  {

          LED08RESET();

          LED07SET();

          osDelay(97);

          LED07RESET();

          LED08SET();

          osDelay(97);

  }

  /* USER CODE END StartTask04 */

}

/* StartTask05 function */

void StartTask05(void const * argument)

{

  /* USER CODE BEGIN StartTask05 */

  /* Infinite loop */

  for(;;)

  {

          LED10RESET();

          LED09SET();

          osDelay(96);

          LED09RESET();

          LED10SET();

          osDelay(96);

  }

  /* USER CODE END StartTask05 */

}

 

Запустим MS Cube, создадим проект, выбрав наш микроконтроллер (нажмите на картинку для увеличения размера)

 

image01_0500

 

В RCC выбираем вот такую опцию

 

image04

 

А в SYS вот такие

 

image03

 

TIM1 выбран ввиду того, что что на Systick будет ругаться генератор кода в случае использования FreeRTOS.

Мигать мы будем сразу десятью светодиодами, как нельзя кстати оказалась под рукой светодиодная матрица. Для удобства подключения мы будем использовать порты в разъёме, расположенные рядом с общим проводом GND. Не забываем ни в коем случае про токоограничивающие резисторы. У меня на 680 ом

 

image06

 

Включим данные ножки на выход

 

image05

 

 

Пока FreeRTOS не задействуем.

Перейдём в Clock Configuration, подключим там резонатор и включим всё на максимум (нажмите на картинку для увеличения размера)

 

image08_0500

 

Зайдём в Project -> Settings и настроим наш будущий генерируемый проект, немного добавив значение стека и кучи

 

image07

 

У вас будет, соответственно, другой путь. Нажмём «ОК».

Сгенерируем проект и закроем диалог, так как вход в проект в случае использования WB (я так буду в дальнейшем для экономии времени и места называть System WorkBench) невозможен

 

image11

 

Запустим System Workbench. Щёлкнем правой кнопкой мыши в левом окне и выберем пункт «Import»

 

image09

 

Выделим «Existing Project into Workspace» и нажмём «Next»

 

image10

 

В «Select root Directory» через обзор выберем папку со вновь созданным проектом. Проект должен будет появиться в списке и пометиться галкой. Жмём «Finish»

 

image12

 

Откроем слева дерево проекта, найдём там файл main.c и поставим туда фокус ввода (кликнем мышкой, чтобы установился курсор). Это помогает компилятору в случае наличия в дереве проектов в дереве проектов простым способом понять, что данный проект для него является текущим и ему работать именно с ним.

Попробуем скомпилировать проект. Для этого выберем в меню Project -> Build Project. Если проект нормально соберётся, то мы увидим внизу вот такую картину

 

image13

 

 Если мы увидим ошибку в виде ругательства на FPU, то у нас скорей всего не обновлён Workbench. В этом случае лучше ничего не править и не выдумывать, а просто его обновить через пункт меню «Help -> Check for Updates».

Теперь попробуем зайти в отладку. Первый раз всё-таки лучше запускать исполнение именно так. Если будут проблемы, то надо удалить в свойствах проекта все конфигурации отладки. Если появится диалог с выбором программатора, то нужно будет его выбрать

 

image14

 

Ну а дальше всё, как на прошлом занятии.

Теперь в main.h для удобства добавим макросы для наших светодиодов. Я вставлю из заранее заготовленного файла macro.txt

 

/* USER CODE BEGIN Includes */

#define LED01 GPIO_PIN_5

#define LED02 GPIO_PIN_6

#define LED03 GPIO_PIN_7

#define LED04 GPIO_PIN_14

#define LED05 GPIO_PIN_15

#define LED06 GPIO_PIN_12

#define LED07 GPIO_PIN_13

#define LED08 GPIO_PIN_9

#define LED09 GPIO_PIN_11

#define LED10 GPIO_PIN_14

#define LED01PORT GPIOA

#define LED02PORT GPIOA

#define LED03PORT GPIOA

#define LED04PORT GPIOD

#define LED05PORT GPIOD

#define LED06PORT GPIOF

#define LED07PORT GPIOF

#define LED08PORT GPIOE

#define LED09PORT GPIOE

#define LED10PORT GPIOF

#define LED01SET() HAL_GPIO_WritePin(LED01PORT, LED01, GPIO_PIN_SET)

#define LED02SET() HAL_GPIO_WritePin(LED02PORT, LED02, GPIO_PIN_SET)

#define LED03SET() HAL_GPIO_WritePin(LED03PORT, LED03, GPIO_PIN_SET)

#define LED04SET() HAL_GPIO_WritePin(LED04PORT, LED04, GPIO_PIN_SET)

#define LED05SET() HAL_GPIO_WritePin(LED05PORT, LED05, GPIO_PIN_SET)

#define LED06SET() HAL_GPIO_WritePin(LED06PORT, LED06, GPIO_PIN_SET)

#define LED07SET() HAL_GPIO_WritePin(LED07PORT, LED07, GPIO_PIN_SET)

#define LED08SET() HAL_GPIO_WritePin(LED08PORT, LED08, GPIO_PIN_SET)

#define LED09SET() HAL_GPIO_WritePin(LED09PORT, LED09, GPIO_PIN_SET)

#define LED10SET() HAL_GPIO_WritePin(LED10PORT, LED10, GPIO_PIN_SET)

#define LED01RESET() HAL_GPIO_WritePin(LED01PORT, LED01, GPIO_PIN_RESET)

#define LED02RESET() HAL_GPIO_WritePin(LED02PORT, LED02, GPIO_PIN_RESET)

#define LED03RESET() HAL_GPIO_WritePin(LED03PORT, LED03, GPIO_PIN_RESET)

#define LED04RESET() HAL_GPIO_WritePin(LED04PORT, LED04, GPIO_PIN_RESET)

#define LED05RESET() HAL_GPIO_WritePin(LED05PORT, LED05, GPIO_PIN_RESET)

#define LED06RESET() HAL_GPIO_WritePin(LED06PORT, LED06, GPIO_PIN_RESET)

#define LED07RESET() HAL_GPIO_WritePin(LED07PORT, LED07, GPIO_PIN_RESET)

#define LED08RESET() HAL_GPIO_WritePin(LED08PORT, LED08, GPIO_PIN_RESET)

#define LED09RESET() HAL_GPIO_WritePin(LED09PORT, LED09, GPIO_PIN_RESET)

#define LED10RESET() HAL_GPIO_WritePin(LED10PORT, LED10, GPIO_PIN_RESET)

/* USER CODE END Includes */

 

Теперь вставим код бегущих огней в бесконечный цикл из того же файла macro.txt

 

  /* USER CODE BEGIN 3 */

          LED10RESET();

          LED01SET();

          HAL_Delay(100);

          LED01RESET();

          LED02SET();

          HAL_Delay(100);

          LED02RESET();

          LED03SET();

          HAL_Delay(100);

          LED03RESET();

          LED04SET();

          HAL_Delay(100);

          LED04RESET();

          LED05SET();

          HAL_Delay(100);

          LED05RESET();

          LED06SET();

          HAL_Delay(100);

          LED06RESET();

          LED07SET();

          HAL_Delay(100);

          LED07RESET();

          LED08SET();

          HAL_Delay(100);

          LED08RESET();

          LED09SET();

          HAL_Delay(100);

          LED09RESET();

          LED10SET();

          HAL_Delay(100);

  }

  /* USER CODE END 3 */

 

Теперь можно прошивать через обычную кнопку «Run»

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

Купить отладочную плату можно здесь STM32F767ZI-Nucleo

Смотреть ВИДЕОУРОК

 

STM32 System Workbench. FREE RTOS

 

2 комментария на “STM Урок 54. System Workbench. FREE RTOS
  1. Yuriy_Y:

    И все же, считаю, что давать ногам метки удобнее в коде. Наглядно видно, какая нога и за что отвечает. Постоянно так делаю и ни разу не пожалел.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*