STM Урок 104. FreeRTOS. Бинарные (двоичные) семафоры. Часть 1



Продолжим забытую нами тему использования операционной системы реального времени — FreeRTOS.

Операционная система реального времени позволяет нам добиться организации процессов, также многозадачности, причём часть работы по данной организации система берёт на себя, но некоторая часть данной организации вопросов также ложится и на разработчика приложения.

Например может случиться следующая ситуация. Есть какой-нибудь ответственный процесс, который в данный момент времени должен вызываться только из одной задачи, то есть не должно быть одновременного выполнения данного процесса несколькими задачами. Обычно в блогах любят это сравнивать с туалетом, в который существует очередь и одновременно двое не должны присутствовать в помещении туалета. Там присутствует один человек, а остальные его терпеливо дожидаются. И как выразился один из блогеров, почему-то никто не ассоциирует эту ситуацию с флагом передовика. Ну, скорей всего потому, что флаг передовика получит кто-то один, а остальным его ожидающим его уже не дадут, так как он только один. Вот такая, вообщем, ситуация. Ну а касабельно микроконтроллера может быть вывод в какой-то порт информации процессом, если данная задача в это же время будет вызвана процессом другим, то скорей всего данные в лучшем случае перемешаются, а в худшем половина их растеряется вообще, хотя этот случай больше касается очередей. Так вот помещение туалета принято называть критической секцией. То есть действие «присутствие в помещении» могут одновременно осуществлять только ограниченное количество людей, в нашем случае людей, а в программирование — процессов. Так вот если у нас семафор не бинарный, а счётный и счётчик, например, будет установлен в 5, то тогда одновременно присутствовать или выполнять код данной критической секции сможет 5 процессов. Можно меньше, но никак не больше.

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

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

Вообще бинарый семафор всё-таки лучше рассматривать как обычный счётный, но только со значением счёта 1.

Не хотел я рисовать картинки, так как этого я не люблю, но видимо придется на это потратить немного времени, так как это будет понятнее, чем объяснять на пальцах.

Предположим, что у нас есть какие-нибудь 3 процесса, которые хотят выполнить код, находящийся в критической секции (нажмите на картинку для увеличения изображения)

 

 

Каждый процесс хочет выполнить код критической секции. На участок критической секции мы установили бинарный семафор. Как это делается, мы узнаем, когда будем писать код нашего проекта. Сначала все процессы протекают в обычном режиме и не собираются выполнять код критической секции (стадия 1). Вдруг процессу 1 захотелось выполнить код критической секции. Мы помним, что семафор у нас бинарный, следовательно значение его счётчика 1. В момент попытки выполнить код критической секции процессом 1 семафор срабатывает и пропускает процесс 1 к выполнению кода критической секции. Счётчик семафора становится равным 0, а процесс 1 начинает выполнять код критической секции (стадия 2). Если значение счётчика семафора меньше или равно нулю, то семафор блокирует вход других процессов в критическую секцию. Предположим, что процесс 1 ещё код, находящийся в критической секции, не выполнил, а процесс 2 также захотел перейти в критическую секцию и выполнить её код. Но значение счётчика семафора в данный момент у нас 0 и, следовательно он туда не пустит процесс 2 и поставит его в очередь и счётчик семафора ещё убавится на 1 и станет равным -1 (стадия 3). А процесс 1 всё ещё продолжает выполнять код критической секции. Вдруг ещё в какой-то момент процесс 3 также захочет выполнить код, находящийся в критической секции. А значение счётчика семафора у нас в данный момент -1 и он само собой туда процесс 3 не пустит и также поставит его в очередь, в которой уже находится процесс 2. Процесс 3 встанет в очереди за процессом 2 и счётчик семафора установится равным -2 (стадия 4). В какой-то момент процесс 1 выполнит код критической секции и выйдет из неё. Семафор теперь разрешит выполнять код критической секции процессу 2, так как тот находится первым в очереди (опять мне приходит на ум туалет, никуда не денешься). Значение счётчика семафора тогда увеличится на 1 и станет равным -1, а в очереди останется только процесс 3 (стадия 5). То есть при увеличении счётчика семафора на 1, если есть какой-то процесс в очереди, то он будет допущен к выполнению кода критической секции. Но если придёт ещё какой-то процесс и захочет выполнить код критической секции, то он будет поставлен в очередь, так как значение семафора меньше или равно 0. Но у нас таких процессов нет, поэтому процесс 3 остаётся в очереди один и он стоит в ней первым. Затем процесс 2 также выполнит код критической секции и выйдет из неё. Семафор сработает и счётчик его опять увеличится на 1 и станет равным 0, а также он теперь пустит в код критической секции процесс 3, который дожидался своей очереди. Очередь освободится (стадия 6). Затем процесс 3 также выполнит код критической секции и выйдет из неё. Семафор опять сработает и его счётчик снова увеличится на 1 и станет равным 1. Теперь у нас критическая секция свободна, очередь свободна и любой процесс, желающий выполнить код критической секции, будет в неё допущен (стадия 7).

Вот примерно так. Слов получилось много, но диаграмма на рисунке, надеюсь, поможет вам понять происходящее.

Теперь, думаю, с теорией мы немного познакомились, пора бы перейти к сочинению проекта. Но прежде чем в него перейти, надо выбрать контроллер, для которого мы будем данный проект писать. Я решил использовать достаточно мощный контроллер — STM32F746NGH6, находящийся на плате STM32F746G-DISCO (32F746GDISCOVERY). Вы можете использовать любой контроллер, в котором хватит памяти для работы операционной системы FreeRTOS. А я всё-таки остановлюсь на данной плате, так как она удобна ещё потому, что на ней установлен отличный дисплей, который мы знаем не понаслышке и с которым мы прекрасно умеем работать, а также на этой плате установлена микросхема LAN8742A, которая нам позволит продолжить работать с локальной сетью, не подключая никаких дополнительных устройств и плат расширения.

Создадим новый проект в Cube MX и выберем контроллер

 

 

Включим RCC

 

 

Выберем отладчик, а в качестве базового таймера выберем таймер 1. Так любит RreeRTOS, видимо ему системный таймер ещё зачем-то требуется

 

 

Так как мы собираемся использовать дисплей, то включим LTDC

 

 

Переопределим на нём ножки так же, как мы это делали в уроке 64.

Также не забываем включить на выход 2 служебные ножки для LTDC

D8    PK3     LCD_BL_CTRL

E3    PI12     LCD_DISP

Настроим FMC, также как и в уроке 62

 

 

 

Для FMC переопределяем только одну ножку — PH2 (K4) на PC3 (L4)

 

 

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

 

 

Также включим DMA2D

 

 

Включим FreeRTOS

 

 

Настроим частоты в Clock Configuration (нажмите на картинку для увеличения изображения)

 

 

Перейдём в Configuration и настроим сначала регионы в Cortex M7 (нажмите на картинку для увеличения изображения)

 

 

Настроим FMC

 

 

 

Настроим LTDC — сначала General Settings

 

 

Затем Layer Settings

 

 

Настроим DMA2D

 

 

В DMA2D включим прерывания

 

 

Настроим FreeRTOS.

Сначала Config parameters, увеличим там размер кучи

 

 

Затем идём в Tasks and Queues, добавим там ещё одну задачу, а у той, которая по умолчанию, увеличим размер стека

 

 

 

Ну и самое главное, добавим один бинарный семафор во вкладке Timers and Semaphores

 

 

Перейдём в GPIO и немного поработаем с ножками портов.

На PI12 и PK3 установим скорость в High, а также уровень при включении также в High

 

 

Перейдём на вкладку LTDC и всем ножкам установим скорость в High

 

 

Зайдём в настройки проекта, дадим ему имя, выберем в качестве среды разработки System Workbenh, а также увеличим значения стека и кучи

 

 

Сохраним настройки, сгенерируем проект, откроем его в System Workbench, установим уровень оптимизации в 1, удалим, если есть, конфигурацию отладки и попробуем собрать.

Скорей всего, проект не соберётся из-за некоторых настроек DMA, так как их почему-то не знает System Workbench. Закомментируем строки с ошибками

 

//hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;

//hdma2d.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR;

hdma2d.LayerCfg[0].InputOffset = 0;

hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;

hdma2d.LayerCfg[0].AlphaMode = DMA2D_REPLACE_ALPHA;

hdma2d.LayerCfg[0].InputAlpha = 0;

//hdma2d.LayerCfg[0].AlphaInverted = DMA2D_REGULAR_ALPHA;

//hdma2d.LayerCfg[0].RedBlueSwap = DMA2D_RB_REGULAR;

 

Теперь проект скорей всего нормально соберётся.

Возможно, эта ситуация со временем исправится.

Из проекта урока 70 по выводу текста на дисплей с именем LTDC_TEXT скопируем в соответствующие папки нашего нового проекта файлы ltdc.c, MT48LC4M32B2.c, font8.c, font12.c, font16.c, font20.c, font24.c, ltdc.h, MT48LC4M32B2.h и fonts.h.

Освежим проект в дереве проектов (Refresh) и ещё раз попробуем собрать.

 

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

 

 

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

 

 

Отладочную плату можно приобрести здесь 32F746G-DISCOVERY

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM FreeRTOS. Бинарные семафоры

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

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

*