STM32 и FreeRTOS. 4. Шаг в сторону HAL

  • Tutorial
HAL 9000: I'm completely operational, and all my circuits are functioning perfectly.
или это должно быть первой статьей, но я почему-то всегда пишу подобное ближе к концу

Раньше было про потоки, про семафоры и очереди

Одним из основных препятствий для перехода на STM32 является обилие текстов, инструкций и мануалов, описывающих работу с контроллером. Виновником этого обилия стала сама STMicroelectronics, которая поначалу планомерно запутывала своих пользователей, а затем предлагала неверные варианты выхода.

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

Но не так давно ST поняла, в какую яму она угодила и начала усиленно из нее выбираться, привлекая новые силы. И именно благодаря этому сейчас время старта сократилось до несуразно маленьких величин. Как это выглядит на практике? Добро пожаловать под кат.

Для начала дам совет, как быстро определить то, что не стоит читать про STM32.

Во-первых, год публикации раньше 2011-2012. Просто поверьте, что «то, что тогда» и «то, что сейчас» — две большие разницы. SPL и HAL в мире STM не просто очередные аббревиатуры.

Во-вторых, если встретится подобный код (это всего лишь кусочек инициализации ADC, если это кому-либо интересно).

RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; 

ADC1->SMPR2 |= ADC_SMPR2_SMP0 | ADC_SMPR2_SMP1 
        | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP3 | ADC_SMPR2_SMP4 
        | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP6 | ADC_SMPR2_SMP7;     

ADC1->SQR1 |= ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0;
        
ADC1->SQR2 |= ADC_SQR2_SQ8_2 | ADC_SQR2_SQ8_1 | ADC_SQR2_SQ8_0 
        | ADC_SQR2_SQ7_2 | ADC_SQR2_SQ7_1;           

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

Итак, в чем проблема? Главная и единственная проблема — это инициализация периферии. Вон те шаманские пляски с битами возникли не на пустом месте. И 99% проблем «у меня не работает» заключаются именно в неправильной инициализации. Не те частоты, попытка использовать выделенное под другое ресурсы и так далее и тому подобное. Что особо обостряет проблему, так это то, что никаких кодов ошибок или там эксепшенов нет. Все как у сапера: что-то сделал не так — все мертвое.

Вам кажется, что это сказки? Вот вам рисуночек схемы тактирования STMF3


Подсчетом мест, где можно ошибиться, предлагаю заняться самостоятельно


В итоге ST выкатила сначала SPL (Standard Peripheral Library), которая хоть улучшила ситуацию, но не сильно. А затем появилась следующая версия, которую обозвали HAL. А что бы еще больше облегчить разработчикам жизнь, была обновлена утилита STM32CubeMX, которая позволила буквально парой кликов мышки сгенерировать код инициализации для всего многообразия плат, процессоров и периферии. А рядышком положила так называемые firmware, в которые запихнула кучу примеров работы именно для данного процессора.

И то, что нажатием двух кнопок можно получить 100% (я ни разу пока не встретился с обратным) рабочий код абсолютно давит мысли «там оптимизировать и оптимизировать»…

Сама программа построена по привычному всем принципу «выбери мышкой что надо и нажми кнопку». Выбрал одну схему тактирования — программа сразу показала частоты и выделила красным те места, которые с такими частотами работать не могут. Попробовали использовать тот функционал, который в данных условиях невозможен (например, ножка уже занята чем-то другим) — опять подсветит ошибку.

Вот на рисунке слева я показал список функций, которые можно повесить на одну-единственную ножку. После подсчета обычно AVRщики (где 4 функции на ножку — максимум) долго хмыкают и что-то подсчитывают в уме. А когда я им говорю, что таких ножек может быть больше 160 штук, то вообще выпадают в осадок.

Но больше всего меня радует тот факт, что теперь благодаря HAL не надо переписывать код работы с периферией. Если где-то написано

НAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET); 

То я знаю, что на всех доступных на данный момент мне процессорах этот код переведет ножку PA2 в «ноль». И даже написанная функция взятия среднего значения нужного канала АЦП тоже не будет сопротивляться при переходе с L1 на F4

int GetADCValue(uint32_t Channel,uint32_t Count)
{
	int val = 0;
	ADC_ChannelConfTypeDef   sConfig;
	sConfig.Channel=Channel;
	sConfig.Rank=1;
	sConfig.SamplingTime=10;
	HAL_ADC_ConfigChannel(&hadc,&sConfig);
	
	for(int i = 0; i < Count; i++)
	{
		HAL_ADC_Start(&hadc);
		HAL_ADC_PollForConversion(&hadc,1);
		val += HAL_ADC_GetValue(&hadc);
	}
return val / Count;
}

А теперь немного положенной по канонам магии STM32

Как вы думаете, сколько мне придется приложить усилий, что бы получить из STM32F3 ком-порт в usb, который просто будет возвращать то, что в него послали? Я тут подсчитал — 12 нажатий мышкой (включить USB, выбрать CDC, сгенерировать) и 6 строчек кода в функции CDC_Receive_FS (файл usbd_cdc_if.с)

for (int i = 0; i < *Len; i++)
        UserTxBufferFS[i] = UserRxBufferFS[i];

USBD_CDC_SetTxBuffer(&hUsbDeviceFS, &UserTxBufferFS[0], *Len);
USBD_CDC_TransmitPacket(&hUsbDeviceFS);
    
 USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &UserRxBufferFS[0]);
 USBD_CDC_ReceivePacket(&hUsbDeviceFS); 

И примерно так же и с той же сложностью реализуется «звуковая карта», «флешка» или HID. Да, дадут только код инициализации, логику самому писать надо будет, но и это — офигенное подспорье.

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



На вопрос «где бы примерчик взять?» ответ простой — в скачиваемой при генерации «фирмвари» лежит куча примеров. И рекомендую накачать (в менюшке найдете) «фирмварь» для других моделей процессоров — очень часто примеры не пересекаются и тот же «АЦП через DMA» есть только в одном месте, хотя прекрасно работает и там и там.

Отдельным абзацем замечу, что STM32Cube хоть и помогает программисту в быстром старте, она по прежнему требует понимания, что же настраивается и почему именно так настраивается. К примеру, по умолчанию прерывания и DMA для USART выключены, поэтому некоторые функции просто не будут работать. В общем, тщательно смотрите за вкладочками, благо программа позволяет перегенерировать проект, сохранив уже написанное.

Где-то здесь программисты обычно уже уходят «поуши» в генерацию «чего-то этакого», смену дескрипторов, размеров буферов и смены отображаемого названия в диспетчере задач на «Super Cool Device». Ну и я оставлю Вас с этим

Завершаем и приносим пользу
Поделиться публикацией

Похожие публикации

Комментарии 18
    0
    Спасибо за статью!
    Как дела у CubeMX обстоят с совместимостью с семейством STM32F103?
    Пробовал какое-то время сгенерировать им код для F103. То ли одного инсталятора CubeMX недостаточно для работоспособности, то ли он пока не совместим с F103. Сгенерированный код содержал одни пустышки с закомментированными плейсхолдерами в коде.
      +1
      Судя по картинке отсюда, то пока никак.

      Но вообще-то он и для других генерирует код с пустышками внутри. Непустышки у него только в области инициализации. Или я про другое?
        0
        Ну у меня были пустышки в коде инициализации. Назначал некоторые пины на AF, а в сгенерированном коде получал либо ничего (пустые области, обрамленные комментариями-заголовками), либо закомментированные строки с конфигурацией пинов в GPIO.
        Кажется даже пытался сгенерировать код FreeRTOS, и ничего не вышло.

        Поскорее бы допилили.
          0
          Ну судя по скорости поддержки L1/L0 (в мае прошлого года точно не было), то скоро будет. Но сильно не радуйтесь, даже для «обкатанного» F4 есть ошибки в ихних «фирмварях». Причем ошибки классическо-индусного типа «не посмотрели, забыли и забили» :)
            0
            Хммм… Только что на удачу закачал с той страницы инсталлятор, установил и зачал новый проект. Все настроил как хотелось, нажал «Сгенерировать код». Он запросил восстановить коннекцию с STM для скачки фирмварей и вот уже качает.

            Быть может хоть что-то нагенерирует. Позже отпишусь.

            PS: с ошибками разберемся как-нибудь.
              0
              УРА!
              Сгенерировался код. На текущей машине не был установлен ARMGCC тулчейн и Eclipse, потому сгенерировались дополнительно проектные файлы только для EWARM, Keil и еще какой-то IDE. Не могу проверить генерацию под GCC пока. Однако код библиотек получается общий и можно будет просто сымпортировать в Eclipse.
              Работоспособность кода также пока не проверял.
                0
                Ну это же хорошо :) Скорее всего, это появилось в недавнем обновлении, а на сайте не исправили :)
                  0
                  Либо в первую свою попытку я прошляпил коннекцию к серверу STMicro.
                  Если все будет работать как надо, то уже CooCox не будет так сильно нужен. Есдинственная его киллер-фича будет только автозаливка бинарника в МК (а может и тут я просто пока не научился это делать в ванильной Eclipse).
                    0
                    Я как-то мучался-мучался и привык к Keil :) Причем иногда матерюсь, вспоминая добрым словом кококс, но потом матерки утихают, когда я вспоминаю 2.х версии кокоса и keil уже кажется милым и прекрасным средством разработки :)
        0
        del
          0
          Имеется — еще 16 декабря была. Просто эту новость все узнали только потыкав в апдейтер куба…
          Проверьте версию — должна быть 4.6.0.
            0
            Вот только сегодня и попробовал (комментарии выше). Код был сгенерирован успешно. Не успел еще попробовать запустить.
          0
          Я к HAL и STMCube присматривался примерно полгода назад. Я не смог понять, как теперь пользоваться UART'ом и не нашел никакой документации или примеров. Теперь с этим получше?

          Ах да, еще я обнаружил достаточно тривиальный баг в одной из HAL'овских функций, но сообщать о нем пришлось на форум; никакой формы для баг-репорта я тоже не нашел. И не знаю, исправили этот баг уже или нет, надо будет проверить.
            0
            Хм, не скажу насчет «отлично», но примеры есть. Конечно, тяжело без описаний, почему это сделано так, а не этак, но исходники выручают :)
            0
            Верной дорогой идут с этим STM32CubeMX: бардака меньше, а удобства больше. Главное чтобы не бросили и через год-два опять не решили всё переделать.

            Кстати по поводу RTOS и HAL. В упомянутой вами в первой части ChibiOS, HAL для STM32 свой, встроенный. Не возьмусь судить насколько он качественный, но то, что он разрабатывался под конкретную ОС и доступен из коробки, уже неплохо.
              0
              Я пробовал HAL от ChibiOS. Вполне себе. В смысле свои задачи выполняет и даже в отличии от STMовского, кроссплатформенный (вот тут сильно не тестировал, но один и тот же код мигал и на STM32 и на MSP430)
              0
              Интересно, а есть где-то толковый гайдлайн или описание структуры HAL для применения в своих проектах и для перехода с SPL?
              А то документ у них с описанием есть, но в типичном бюрократическом стиле — сплошные ссылки по документу, куча ненужной инфы, а нужная изложена так, что лучше б ее не было.
                0
                Вот взял кубик, сгенерировал проект с USB CDC
                с включённым FreeRTOS устройство вообще не определяется
                если выключить FreeRTOS определяется с ошибкой Code 10/Код 10

                ЧЯДНТ и как его заставить хотя бы определяться во FreeRTOS?

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

                Самое читаемое