Показаны сообщения с ярлыком FreeRTOS. Показать все сообщения
Показаны сообщения с ярлыком FreeRTOS. Показать все сообщения

воскресенье, 4 октября 2026 г.

STM32 FreeRTOS уведомления задач

 Операционная система FreeRTOS содержит некоторое количество инструментов для коммуникации задачи и обработчиков прерываний между собой. Для этого можно использовать бинарные семафоры и даже, рассмотренные ранее, очереди но если нужно организовать максимально быстрое и не затратное по памяти решение то лучше всего подойдут "уведомления задач" (Task Notifications). Уведомления задач имеются в новых версиях FreeRTOS и могут передавать не только уведомления но и некоторое небольшое количество данных, 32 бита. Уведомления задач на 40% работают быстрее бинарных семафоров и в 90% случаев могут их заменить. Попробуем изучить уведомления задач на простом примере. Допустим у нас есть прерывание по приему на UART1 после получения данных в UART1, в обработчике прерывания, упакуем принятый байт данных и отправим как уведомление в задачу.Задача примет байт и отправит его в UART1. Таким образом мы получим простой эхо режим, работающий через задачу и использующий уведомление задачи. Чтобы использовать уведомление задачи нужно сначала инициализировать её хэндл.

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

Сейчас нас интересуют две функции. Это сама задача и обработчик прерывания по приему UART1.
В обработчике прерывания принимаем байт.
Далее используя специальную функцию для отправки уведомлений задачам из прерывания.
Отправляем уведомление задаче. Важно в прерывании использовать именно такую функцию. Если нужно отправить уведомление от задачи к задаче то есть другая похожая.
В этой функции хэндл задачи указываем первым параметром. Вторым параметром передаем принятый байт, предварительно приведя его к нужному типу.
Третьим параметром передаем константу означающую перезапись значения если задача не успела его вовремя принять и обработать. 
Ну и остальное просто оставим пока как есть. В самой задаче, объявляем переменную в которую будем принимать байт от UART1.
В бесконечном цикле задачи проверяем когда в задачу придет уведомление. Когда оно приходит, извлекаем принятый байт.
После отправляем его обратно в UART1.
Полный код файла main.c проекта, можно скопировать от сюда:

Его можно вставить в свой проект и откомпилировать запустив скрипт. О том как скачать и настроить проект а также откомпилировать см. первый урок по FreeRTOS. Если откомпилировать проект получилось то можно его загрузить в микроконтроллер. Подключить его через usb-uart переходник к компьютеру и в каком либо терминале последовательного порта наблюдать работу.


Адрес биткоин кошелька для поддержки канала - bc1qlhrmmkh77x2lzhqe4lt9qwkglswj64tsqt2l5g

суббота, 1 августа 2026 г.

STM32 FreeRTOS использование очереди

Продолжим изучение операционной системы FreeRTOS. На этот разр рассмотрим две новые темы. Это передача параметра в функцию задачи. Но поскольку это простая тема то рассмотрим ещё одну очень важную. Это использование "очереди" для хранения данных и их передачи между задачами. Очередь это тип хранения данных при котором новые данные добавляются только в конец очереди а старые извлекаются из её начала, как это происходит в реальных очередях. Если заменить людей данными то получиться то что называют очередью в программировании.

Предположим что мы уже умеем запускать сборку проекта, если нет то можно возвратиться к предыдущему 


уроку 


по FreeRTOS и настроить сборку проекта.

Теперь попробуем разобраться с исходным кодом. Открываем main.c. В начале, как обычно, заголовочные файлы библиотек, только на этот раз к ним добавляется заголовочный файл "очереди".

Далее видим что многое осталось таким же как и в предыдущем уроке по FreeRTOS.

Но добавлена строка текста ввиде указателя на тип char который передается четвертым параметром в функцию создания первой задачи.

Таким образом можно передавать какие либо данные в функцию которая выполняет какую либо задачу. Также видим что в коде перед функцией main() добавляется объявление очереди и т.о. выделяется память на её обработчик. В функции main() создается очередь. Функцией создания очереди. Первый параметр, данной функции, это максимальное количество элементов которое может хранить очередь. Второй параметр это размер каждого элемента в очереди в байтах. После попытки создания очереди, присходит проверка. Если очередь создана успешно то создаются задачи и запускается шэдулер. Если нет то выводиться предупреждение об ошибке в последовательный порт. В конце функции main(), как обычно, находиться бесконечный цикл.

Теперь можем переходить к рассмотрению задачи 1.Видим что в задаче 1 мы можем принять тот параметр который передали ранее в функции main(). Далее этот параметр можно привести к нужному типу и использовать. В данном случае мы его приводим к указателю на тип char и используем как строку текста для вывода в последовательный порт.

Также сделаем ещё две строки чтобы передавать их в очередь в данной задаче. Другая задача будет вытаскивать строку из очереди и выводить в порт. Таким образом мы проверим работу учереди на таком простом примере. Чтобы была какая то интерактивность и наглядность сделаем ещё опрос кнопки например на пине 1 порта A и будем записывать в очередь строку соответствующую состоянию пина A1 или соответственно состоянию кнопки. Чтобы отправить строку в очередь. Сначала приводим её к типу беззнаковый 32х битный int и берем адрес который передаем в функцию отправки в очередь вторым параметром. Первым параметром передаем хэндлер очереди а последним ноль. Далее проводим проверку, если отправка не удалась то выводим сообщение об ошибке.

Во второй задаче вынимаем из очереди строку. Функцией приема из очереди. Очередь т.о. опустошается. Если конечно в неё не было передано что то ещё. Но в данном случае такого произойти не должно т.к. обе задачи работают с равными задержками в одну секунду. Также видим что в функции приема есть третий параметр. Первый параметр это хэндлер очереди. В случае удачного приема, принятая строка выводиться в последовательный порт. В случае неудачного примера, в порт выводиться сообщение о том что принять из очереди не получилось. + Также в бесконечном цикле задачи имеется задержка в секунду. 


Также есть в коде функция настройки периферии которая содержит в себе две функции. Одна для настройки uart1 другая для настройки gpio Функцию настройки GPIO мне сгенерировала нейросеть и у неё получилось хотя светодиод на пине 13 не пригодился. Возможно попробуем его задействовать как нибудь в другой раз. Для данного раза достаточно последовательного порта. Проект можно собрать, загрузить в микроконтроллер и посмотреть что он выдает в последовательный порт при нажатой кнопке и при отпущенной. Кнопку следует подключить между пином A1 и GND.


Видим что текст в терминале меняется в зависимости от состояния кнопки, так как и планировалось т.е. очередь работает.
Можно попробовать поменять задержки в задачах и обнаружить либо переполнение очереди либо попытку получить данные из пустой очереди.
Результат зависит от того задержка какой задачи будет больше. Также видим что передача параметра в первую задачу прошла успешно.

Полный код файла main.c


Видео по данной теме с проверкой


Адрес биткоин кошелька для поддержки блога - bc1qlhrmmkh77x2lzhqe4lt9qwkglswj64tsqt2l5g

суббота, 2 мая 2026 г.

STM32 FreeRTOS blue pill

 Изучим бесплатную операционную ситему для встраиваемых систем FreeRTOS. Это не такая операционная система как те что устанавливаются на персональные компьютеры либо одноплатные вроде Raspberry pi. FreeRTOS это многозадачная операционная система реального времени для микроконтроллеров. В ней нет многого того что есть в обычных операционных системах но зато есть многозадачность. Что может быть полезным для случаев при которых микроконтроллер должен выполнять некоторое количество функций. Естественно микроконтроллер не может реально параллельно выполнять много задач одновременно. Если это конечно не такие задачи возможность выполнения которых предусмотрена на аппаратном уровне например DMA. В общем случае, задачи выполняются последовательно и на каждую выделяется определенное время. FreeRTOS является библиотекой которую можно подключить к проекту. Подключив её, можно будет проще реализовывать многозадачность чем при написании кода с нуля самостоятельно. В интернете есть один интересный проект, хорошо подходящий для изучения данной операционной системы на плате blue pill с микроконтроллером stm32f103. Найти его можно по ссылке https://github.com/sbodd/bluepill/tree/master. На странице проекта есть небольшая инструкция по его запуску:

  1. install the toolchain and libarary.
  2. change the TOOLROOT path in Makefile.common
  3. change arm-none-eabi-objcopy path in mkdump.sh
  4. run bash mkdump.sh (it will compile and flash final binary to bluepill, will ask for root password while flashing)
  5. go to app dir and type make clean to remove generated bins and object files

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

sudo git clone https://github.com/sbodd/bluepill.git

Помимо самого проекта, также понадобиться toolchain для микроконтроллеров stm32. Просто так его скачать не получилось (запретили качать из моего региона) поэтому пришлось скачать его сложным способом и добавить, на всякий случай, к себе на яндекс диск.

https://disk.yandex.ru/d/b14nePpO9Jjo5g

После скачивания, можно разархивировать данный тулчейн например утилитой tar.

sudo tar -xf  gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2

Далее понадобиться изменить пару файлов проекта. Это Make файл и скрипт сборки проекта.


В Make файле нужно поменять все пути до тулчейна на корректные

Тоже самое проделать в скрипте сборки проекта + можно убрать загрузку stlink ом если нет stlinkа.
Каждый файл нужно сохранить. В редакторе nano для этого есть комбинация клавиш ctrl+o.
Теперь всё готово для сборки проекта и можно начинать исследовать исходный код.
он содержится по пути корень->Src->FreeRTOS->main.c
В начале, как всегда, подключаются заголовочные файлы библиотек.

Ниже объявляются хэндлеры задач. Задачи у нас будет две, для начала для простоты, поэтому и хандлера всего два.
Ещё ниже объявляются прототипы функций задач.
И ещё есть некоторое колличество прототипов функций инициализации и вспомогательных функций.
В функции main вызывается функция сброса настроек тактирования
и функция обновления тактирования ядра.
Также функция инициализации периферии. В данном случае это инициализация uart1.

В данном проекте микроконтроллер выполняет всего две задачи. Вывод одного текста в uart и вторая задача, вывод другого текста в uart.
Название функции, в которой будет задача, передается первым параметром в функцию xTaskCreate()
Вторым параметром в эту функцию передается просто название задачи кторое нигде больше не используется а служит просто для удобства и понятности.

Далее задается размер стэка задачи. Насколько я понял это то ко
личество оперативной памяти, в словах, которое задача может использовать в стэке.

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

Данный хэндлер впоследствии может быть использован для управления задачей, например для её завершения или приостановки.
Всё тоже самое проделывается теперь для второй задачи.
 После запускается шэдулер который, собственно говоря, и выполняет эти задачи.
В задачах обычно имеются бесконечные циклы и поэтому по идее выполнение программы никогда не должно выходить дальше шедулера но если вдруг это произойдет то дальше есть обычный бесконечный пустой цикл.
Также имеется функция инициализации периферии и пара вспомогательных функций для отправки сообщений в uart.
Теперь можно рассмотреть сами задачи. Функции ывполняюшие задачи должны принимать один указатель на тип void и ничего не возвращать т.е. возвращать void
В этих функциях д.б. бесконечные циклы. В данном случае одна из задач посылает один текст в uart с одной задержкой.
Вторая задача посылает в uart другой текст с другой задержкой между отправками.
Чтобы запустить сборку проекта, нужно зайти в папку со скриптом запуска проекта и запустить его специальной командой.
После, если сборка прошла успешно, можно найти прошивку в формате .bin там же где находиться исходный код. И загрузить её в микроконтроллер например через FlashLoaderDemonstrator или stlink. 


Также есть видеогайд коорый можно посмотреть



Адрес биткоин кошелька для поддержки - bc1qlhrmmkh77x2lzhqe4lt9qwkglswj64tsqt2l5g