Разбираясь с программированием микроконтроллеров Stm32, решил попробовать установить (операционную систему реального времени) ОСРВ — FreeRTOS и столкнулся с рядом трудностей. В интернете есть множество статей, но внятной инструкции я не нашёл, поэтому всех заинтересовавшихся прошу под кат.
Итак для начала определимся что необходимо иметь:
- Отладочная плата Stm32VLDiscovery
- Установленную IDE Keil ARM 5 и выше
- Желание раразбираться в новом
Если вы уже разрабатывали что-либо для семейства STM32F1x в Keil, то можете пропустить этот абзац. Для начала необходимо установить пакеты для разработки для семейства STM32F1x, это делается следующим образом:
- Запускаем Keil.
- Нажимаем на кнопку Pack Installer в панели
- В открывшемся окне нажимаем кнопку Check For Updates (ждём обновления списка пакетов)
- Выбираем в дереве STMicroelectronics->STM32F1 Series->STM32F100 и устанавливаем все пакеты
На этом подготовка среды разработки закончена.
Переходим непосредственно к созданию проекта с использованием FreeRTOS.
Первое что необходимо сделать это скачать свежий дистрибутив ОСРВ с официального сайта www.freertos.org, на момент написания статьи последней версией была FreeRTOSv9.0.0. Итак мы получили внушительный архив, распаковываем его в любое место (сразу скажу что 99% из него нам не понадобится, так что не пугайтесь рамера получившейся папки у меня более 200 Мб).
Теперь нам необходимо создать новый проект в Keil.
Я назвал его FreeRTOSDemo, вы можете выбрать любое подходящее название, главное чтобы в пути размещения проекта не было пробелов и русских букв.
Теперь нам необходимо выбрать наш чип, я тестировал на отладочной плате STM32VLDiscovery c чипом STM32F100RB соответственно выбирал именно его.
После выбора чипа, необходимо выбрать библиотеки которые мы будем использовать. Нам понадобится библиотека CMSIS и StdPeriph. На рисунках далее показан минимальный выбор компонентов, чтобы проверить работу ОСРВ и помигать диодиками (это касается библиотеки StdPeriph, CMSIS нужна обязательно).
Итак мы создали проект, он выглядит следующим образом:
Далее для удобства в проекте создаем несколько групп, чтобы в последствии не получилась мешанина из файлов.
Всё готово к копированию файлов ОСРВ в проект. Создадим папку FreeRTOS в папке проекта.
Из папки FreeRTOSv9.0.0\FreeRTOS\Source\ копируем все *.с файлы в созданную папку FreeRTOS. Туда же копируем папку include.
Из папки FreeRTOSv9.0.0\FreeRTOS\Source\portable\RVDS\ARM_CM3\ копируем файлы *.с и *.h в соответвующие им места папки FreeRTOS нашего проекта.
Из папки FreeRTOSv9.0.0\FreeRTOS\Source\portable\MemMang\ копируем файл heap_2.c.
Из папки FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil\ копируем файл FreeRTOSConfig.h.
После всех манипуляций должно получится следующее:
Далее нам необходимо добавить файлы в соответствующие группы в проекте, а также создать файл main.c c основным текстом программы.
В итоге должна получится следующая структура проекта.
Для того чтобы проект компилировался в его настройках необходимо указать все пути к *.h файлам, а также прописать дерективу USE_STDPERIPH_DRIVER.
Теперь осталось изменить несколько строк в файле FreeRTOSConfig.h, для корректной работы:
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 ) /*на*/
#define configCPU_CLOCK_HZ ( ( unsigned long ) 24000000 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) /*на*/
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 5 * 1024 ) )
И добавляем следующие строки после #define FREERTOS_CONFIG_H
#define xPortSysTickHandler SysTick_Handler
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
После этого в файле main.c пишем простейшую программу для мигания светодиодами.
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
GPIO_InitTypeDef port;
uint8_t state;
void vFreeRTOSInitAll()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_StructInit(&port);
port.GPIO_Mode = GPIO_Mode_Out_PP;
port.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_8;
port.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &port);
}
void vLedTask (void *pvParameters)
{
while(1)
{
if (state == 0)
{
GPIO_SetBits(GPIOC,GPIO_Pin_9);
GPIO_ResetBits(GPIOC,GPIO_Pin_8);
state = 1;
vTaskDelay(500);
}
else
{
GPIO_ResetBits(GPIOC,GPIO_Pin_9);
GPIO_SetBits(GPIOC,GPIO_Pin_8);
state = 0;
vTaskDelay(500);
}
}
vTaskDelete(NULL);
}
int main(void)
{
vFreeRTOSInitAll();
xTaskCreate(vLedTask,(signed char*)"LedTask", configMINIMAL_STACK_SIZE,
NULL, tskIDLE_PRIORITY + 1, NULL);
vTaskStartScheduler();
}
Теперь можно собрать проект и залить прошивку в микроконтроллер, после перезагрузки наблюдать мигающие светодиоды.
Комментарии (22)
Zuy
15.12.2016 08:07А для чего вы обоими светодиодами моргаете из одной задачи?
Логичнее было бы создать отдельную задачу для каждого диода, чтобы продемонстрировать, что нам RTOS даёт.
Сейчас получается вы RTOS к проекту прицепили, а пример пишете, как будто ее у вас и нет.
С вашей демкой можно было быwhile
всунуть вmain()
и задержку пустым циклом подобрать.maxim_rubchenko
15.12.2016 08:30Кусок выдрал и какого-то проекта, и просто скопипастил, т.к. целью являлась описание установки FreeRTOS с указанием на «подводные камни». В сети множество примеров и инструкций по работе с самой ОС и использованием её возможностей.
Amomum
15.12.2016 11:43Расскажу про пару граблей, на которые мы в свое время очень больно наступили:
— удостоверьтесь, что во freertos_config.h есть непустой #define configASSERT( ( x ) ) (например, что-нибудь вроде if(!x) {__disable_irq(); while(1){;}}
— сделайте вот это до запуска RTOS — NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
— если у вас в прерывании есть системный вызов, то приоритет этого прерывания должен быть ниже, чем у прерываний операционки. Иначе вас ждут феерические рандомные хардфолты.
Источник: http://www.freertos.org/RTOS-Cortex-M3-M4.html
K1801vm2
15.12.2016 14:04у вас написано — Надимаем на кнопку Pack Installer в панели…
надо бы исправить ошибку
mentatpsv
Можно установить CubeMX и сгенерировать проект за пару кликов, только на HAL.
maxim_rubchenko
Согласен, только сыровато там ещё всё, хотя конечно чтобы помигать светодами хватит с головой.
persei
Еще год назад реализовывал на cubemx довольно сложное (правда хоум) решение — не заметил особой сырости, разве что были ошибки в HAL, которые уже исправили
proton17
Это и называется "сыростью". Еще там местами присутствует много лишнего кода, в 50% он избыточен.
golf2109
если не трудно, то поподробней о том, что относится к «50% избыточности»
vchs
На самом деле ничего там не сыровато. Около года десяток устройств STM32F091 трудятся у нас на производстве под управлением HAL драйверов и LL драйверов. Полёт абсолютно нормален. Даже более того. Возьмите любой HAL драйвер и просто пробегитесь по исходникам и найдите хоть одну ошибку. Лёгкий оверхед по ресурсам присутствует. Но какие-то там мифические ошибки и проблемы…. Всегда это удивляет. Вот сидит наш парень и вдруг находит ошибки в коде произведенном серьёзной европейской компанией. И таких вдруг целая страна. А производитель и не знаеи и не подозревает. STMicroelectronics эти драйвера рекомендует использовать официально не только любителям, но и производителям скажем стиральных машин. Так что это всё мифы ещё ни разу! не подкрепленные ни одним фактом.
Ну а статья хорошая. Тут вопросов нет.
asdfghjk12
Если у них с программистами всё так прекрасно, то чего они забросили спл и придумали взамен ему хал? Все эти калькуляторы отучают программиста думать. Вместо чтения рефмануала программист ставит галочки и не подозревает о скрытых возможностях периферии. В итоге использует только базовые возможности, под которые в кубике что-то есть…
vchs
Вы пользуетесь SPL? Я вас обрадую, ещё есть ассемблер. Там ещё круче можно контролировать периферию. Но что то мне подсказывает что уровень абстракции SPL вас полностью устраивает. Ну и уровень абстракции HAL также имеет право на жизнь и кого-то устраивает.
Ведь пользуясь вашей категоричностью можно найти много «неправильного» в вашем использовании С, благо язык это позволяет, но ведь вас всё с языком устраивает с мотивировкой, «а зачем бежать тут за тактом если всё успевает». Вот и с HAL местами можно не бежать. Скажем UART сам по себе медленнее чем HAL. Да и по большому счёту HAL идёт в комплекте с LL, который и есть замена вашего SPL. А если вдруг почитать документацию по HAL то там даже объясняется философия использования HAL и LL.
В общем ничего нового под луной… под каждую задачу свой свой инструмент. Медленная периферия или просто инициализация скоростной периферии — HAL, скоростная периферия — или пользуясь даже этим HAL инициализируем этот скоростной конечный автомат, а дальше он живёт своей отдельной жизнью или активно в HAL проекте скоростную часть пишем на LL. Или же всё с нуля пишем на LL. Ну а требование знать периферию никак не соотносится с HAL. Не зная периферии HAL-ом пользоваться также не реально.
В общем каждый выбирает инструмент по себе, а вот категорично всё остальное отрицать глупо.
golf2109
у Вас наверное дооброе начальство, которое будет оплачивать вам пансион для углубленного изучния скрытых возможностей периферии,
Amomum
Вы удивитесь, но я лично в HALe и в CubeMx находил несколько довольно глупых багов. Разумеется, я хотел их зарепортить… а репортить-то некуда. Багтрекера нет. Ну ладно, пошел на форум, создал несколько тем. В них отписались три с половиной человека, мол, да, действительно.
Через полгода отписался модератор. Еще через полгода баги поправили.
Я не говорю, что с программистами у STM очень плохо, но без багтрекера жить тяжко и реагируют они довольно медленно.
HAL сам по себе неплох, у него хотя бы есть написанная человеком (а не генерированная) документация.
vchs
Так продемонстрируйте эти самые найденные баги. Для начала надо бы конечно дать точное определение багу, а то может статься что это и не баг, а неожидаемое для вас поведение кода HAL, обусловленное неверной интерпретацией его концепции и соответственно неверными ожиданиями.
Я читал интервью разработчиков о том как это всё дело у них тестируется (европейских разработчиков). У них всё покрыто тестами, весь код обязан выполняться на всех задекларированных моделях.
Всё это конечно не гарантирует 120% надёжности, но уж сильно не стыкуется с утверждением о тотальной сырости продукта.
В общем ждём демонстрации найденных багов
Amomum
Вот это 100% баг, признанный и исправленный. Прошу обратить внимание, что пост был в марте 2014 года, а в последнем комменте (в сентябре) упоминается, что баг все еще присутствует.
https://community.st.com/thread/24409
Даже не знаю, баги это или нет, но поведение действительно весьма неожиданное. Тут я уже не следил за исправлениями.
https://community.st.com/thread/8588
https://community.st.com/thread/8624
Конечно, все это было довольно давно, вполне возможно, что теперь все хорошо, я уже давненько не проверял, как там у HAL'a и CubeMx дела.
vchs
Мда, удивлен, но действительно была глупая реализация delay. Так глупо споткнутся об переполнение… Что смешно, так это то что первое на что посмотрел при начале изучения HAL это на реализацию delay. И всё было правильно реализовано. А оказывается когда-то было грустно. Ну что ж, вы первый кто за год указал мне на реальный баг.
Я когда пользуюсь HAL или LL перед использованием функции лезу и смотрю на реализацию исходников этой функции и на данный момент ещё не сталкивался с реальными ошибками реализации, а посему и сделал вывод о том что не всё так плохо как обычно слышится на форумах.
Amomum
HAL просто все еще слишком свежая, сообщество к ней относится скептически. Когда SPL была свежая, в ней тоже баги попадались, но их со временем исправляли. Скепсис еще пару лет держался. С HAL сейчас такая же история.
Многим (мне, кстати, тоже) еще плохо понятно, зачем переходить на HAL, если уже SPL есть и работает. Поэтому HAL юзают в основном «новоприбывшие» на платформу или те, кто переходит на свежие чипы, для которых SPL вообще не было.
roma-cezar
Так я и не привык к хал.