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

Итак для начала определимся что необходимо иметь:
  • Отладочная плата Stm32VLDiscovery
  • Установленную IDE Keil ARM 5 и выше
  • Желание раразбираться в новом

Если вы уже разрабатывали что-либо для семейства STM32F1x в Keil, то можете пропустить этот абзац. Для начала необходимо установить пакеты для разработки для семейства STM32F1x, это делается следующим образом:
  1. Запускаем Keil.
  2. Нажимаем на кнопку Pack Installer в панели
  3. В открывшемся окне нажимаем кнопку Check For Updates (ждём обновления списка пакетов)
  4. Выбираем в дереве 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)


  1. mentatpsv
    14.12.2016 16:10
    +1

    Можно установить CubeMX и сгенерировать проект за пару кликов, только на HAL.


    1. maxim_rubchenko
      14.12.2016 16:11

      Согласен, только сыровато там ещё всё, хотя конечно чтобы помигать светодами хватит с головой.


      1. persei
        14.12.2016 17:34

        Еще год назад реализовывал на cubemx довольно сложное (правда хоум) решение — не заметил особой сырости, разве что были ошибки в HAL, которые уже исправили


        1. proton17
          14.12.2016 17:41
          +1

          разве что были ошибки в HAL

          Это и называется "сыростью". Еще там местами присутствует много лишнего кода, в 50% он избыточен.


          1. golf2109
            14.12.2016 20:38

            если не трудно, то поподробней о том, что относится к «50% избыточности»


      1. vchs
        14.12.2016 21:10

        На самом деле ничего там не сыровато. Около года десяток устройств STM32F091 трудятся у нас на производстве под управлением HAL драйверов и LL драйверов. Полёт абсолютно нормален. Даже более того. Возьмите любой HAL драйвер и просто пробегитесь по исходникам и найдите хоть одну ошибку. Лёгкий оверхед по ресурсам присутствует. Но какие-то там мифические ошибки и проблемы…. Всегда это удивляет. Вот сидит наш парень и вдруг находит ошибки в коде произведенном серьёзной европейской компанией. И таких вдруг целая страна. А производитель и не знаеи и не подозревает. STMicroelectronics эти драйвера рекомендует использовать официально не только любителям, но и производителям скажем стиральных машин. Так что это всё мифы ещё ни разу! не подкрепленные ни одним фактом.
        Ну а статья хорошая. Тут вопросов нет.


        1. asdfghjk12
          14.12.2016 22:12

          Если у них с программистами всё так прекрасно, то чего они забросили спл и придумали взамен ему хал? Все эти калькуляторы отучают программиста думать. Вместо чтения рефмануала программист ставит галочки и не подозревает о скрытых возможностях периферии. В итоге использует только базовые возможности, под которые в кубике что-то есть…


          1. vchs
            15.12.2016 01:23

            Вы пользуетесь SPL? Я вас обрадую, ещё есть ассемблер. Там ещё круче можно контролировать периферию. Но что то мне подсказывает что уровень абстракции SPL вас полностью устраивает. Ну и уровень абстракции HAL также имеет право на жизнь и кого-то устраивает.
            Ведь пользуясь вашей категоричностью можно найти много «неправильного» в вашем использовании С, благо язык это позволяет, но ведь вас всё с языком устраивает с мотивировкой, «а зачем бежать тут за тактом если всё успевает». Вот и с HAL местами можно не бежать. Скажем UART сам по себе медленнее чем HAL. Да и по большому счёту HAL идёт в комплекте с LL, который и есть замена вашего SPL. А если вдруг почитать документацию по HAL то там даже объясняется философия использования HAL и LL.
            В общем ничего нового под луной… под каждую задачу свой свой инструмент. Медленная периферия или просто инициализация скоростной периферии — HAL, скоростная периферия — или пользуясь даже этим HAL инициализируем этот скоростной конечный автомат, а дальше он живёт своей отдельной жизнью или активно в HAL проекте скоростную часть пишем на LL. Или же всё с нуля пишем на LL. Ну а требование знать периферию никак не соотносится с HAL. Не зная периферии HAL-ом пользоваться также не реально.
            В общем каждый выбирает инструмент по себе, а вот категорично всё остальное отрицать глупо.


          1. golf2109
            15.12.2016 03:49

            Вместо чтения рефмануала программист ставит галочки и не подозревает о скрытых возможностях периферии

            у Вас наверное дооброе начальство, которое будет оплачивать вам пансион для углубленного изучния скрытых возможностей периферии,


        1. Amomum
          15.12.2016 11:49

          Всегда это удивляет. Вот сидит наш парень и вдруг находит ошибки в коде произведенном серьёзной европейской компанией. И таких вдруг целая страна. А производитель и не знаеи и не подозревает.

          Вы удивитесь, но я лично в HALe и в CubeMx находил несколько довольно глупых багов. Разумеется, я хотел их зарепортить… а репортить-то некуда. Багтрекера нет. Ну ладно, пошел на форум, создал несколько тем. В них отписались три с половиной человека, мол, да, действительно.
          Через полгода отписался модератор. Еще через полгода баги поправили.

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

          HAL сам по себе неплох, у него хотя бы есть написанная человеком (а не генерированная) документация.


          1. vchs
            15.12.2016 14:57

            Так продемонстрируйте эти самые найденные баги. Для начала надо бы конечно дать точное определение багу, а то может статься что это и не баг, а неожидаемое для вас поведение кода HAL, обусловленное неверной интерпретацией его концепции и соответственно неверными ожиданиями.
            Я читал интервью разработчиков о том как это всё дело у них тестируется (европейских разработчиков). У них всё покрыто тестами, весь код обязан выполняться на всех задекларированных моделях.
            Всё это конечно не гарантирует 120% надёжности, но уж сильно не стыкуется с утверждением о тотальной сырости продукта.
            В общем ждём демонстрации найденных багов


            1. Amomum
              15.12.2016 16:59

              Вот это 100% баг, признанный и исправленный. Прошу обратить внимание, что пост был в марте 2014 года, а в последнем комменте (в сентябре) упоминается, что баг все еще присутствует.
              https://community.st.com/thread/24409

              Даже не знаю, баги это или нет, но поведение действительно весьма неожиданное. Тут я уже не следил за исправлениями.
              https://community.st.com/thread/8588
              https://community.st.com/thread/8624

              Конечно, все это было довольно давно, вполне возможно, что теперь все хорошо, я уже давненько не проверял, как там у HAL'a и CubeMx дела.


              1. vchs
                15.12.2016 17:19

                Мда, удивлен, но действительно была глупая реализация delay. Так глупо споткнутся об переполнение… Что смешно, так это то что первое на что посмотрел при начале изучения HAL это на реализацию delay. И всё было правильно реализовано. А оказывается когда-то было грустно. Ну что ж, вы первый кто за год указал мне на реальный баг.
                Я когда пользуюсь HAL или LL перед использованием функции лезу и смотрю на реализацию исходников этой функции и на данный момент ещё не сталкивался с реальными ошибками реализации, а посему и сделал вывод о том что не всё так плохо как обычно слышится на форумах.


                1. Amomum
                  15.12.2016 17:24

                  HAL просто все еще слишком свежая, сообщество к ней относится скептически. Когда SPL была свежая, в ней тоже баги попадались, но их со временем исправляли. Скепсис еще пару лет держался. С HAL сейчас такая же история.

                  Многим (мне, кстати, тоже) еще плохо понятно, зачем переходить на HAL, если уже SPL есть и работает. Поэтому HAL юзают в основном «новоприбывшие» на платформу или те, кто переходит на свежие чипы, для которых SPL вообще не было.


    1. roma-cezar
      14.12.2016 21:10

      Так я и не привык к хал.


  1. Zuy
    15.12.2016 08:07

    А для чего вы обоими светодиодами моргаете из одной задачи?
    Логичнее было бы создать отдельную задачу для каждого диода, чтобы продемонстрировать, что нам RTOS даёт.
    Сейчас получается вы RTOS к проекту прицепили, а пример пишете, как будто ее у вас и нет.
    С вашей демкой можно было бы while всунуть в main() и задержку пустым циклом подобрать.


    1. maxim_rubchenko
      15.12.2016 08:30

      Кусок выдрал и какого-то проекта, и просто скопипастил, т.к. целью являлась описание установки FreeRTOS с указанием на «подводные камни». В сети множество примеров и инструкций по работе с самой ОС и использованием её возможностей.


  1. 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


  1. K1801vm2
    15.12.2016 14:04

    у вас написано — Надимаем на кнопку Pack Installer в панели…
    надо бы исправить ошибку


    1. maxim_rubchenko
      16.12.2016 21:36

      Спасибо, исправил.


  1. alk0v
    15.12.2016 15:01

    Товарищи, а у кого есть опыт диагностики и отладки FreeRTOS? В частности интересует потребляемая задачами память, чтобы можно было соптимизировтаь размер стека под каждую задачу.


    1. clawham
      16.12.2016 21:37

      vTaskList(StrBuff);
      vTaskGetRunTimeStats(StrBuf);