ESP32 Урок 18. FreeRTOS. Event Groups



На данном занятии мы познакомимся ещё с одним видом межпроцессного взаимодействия и синхронизации потоков — Event Groups (группами событий). Для этого также существуют очереди, семафоры и мьютексы. Но группы событий от них отличаются тем, что во-первых здесь идёт экономия ресурсов, так как за каждое событие отвечает не отдельный объект, а всего лишь один бит, а также существует встроенный механизм отслеживания того момента, когда произойдёт одно из событий либо когда произойдут все события, а это также экономия ресурсов. Немаловажным отличием также является то, что группы событий позволяют отследить наступления событий одновременно в нескольких событий, что мы себе не можем позволить, пользуясь семафорами, очередями и мьютексами. Один семафор нельзя забрать несколько раз и очередь тоже.

Группы событий (Event Groups) оперируют битами (также их называют флагами) событий. Флаг события представляет собой логическое значение (1 или 0), используемое для указания того, произошло ли событие. Это позволяет хранить флаги событий в одном бите, а состояние всех флагов событий в группе событий — в одной переменной, где каждый флаг события EvenBits_t. Если бит в переменной EvenBits_t равен 1, это значит, что произошло событие, представленное битом. Если бит в переменной EvenBits_t равен 0, это значит, что событие, указанное этим битом, не произошло

 

 

Например, на рисунке ниже мы видим, что значение группы событий равно 0x92, то есть биты событий 1, 4 и 7 равны 1, следовательно произошли только события, представленные битами 1, 4 и 7

 

 

Максимальное количество битов, которые могут быть использованы для отслеживания событий в группах, регулируется переменной configUSE_16_BIT_TICKS в файле FreeRTOSConfig.h. Если данная переменная равна единице, то мы можем следить только за восемью событиями, а если равна 0, каждая группа событий может содержать 24 доступных бита события.

Теперь немного об используемых функциях для групп событий.

Создать группу событий мы можем при помощи следующей функции

 

 

Возвращаемое значение:

NULL не удалось создать группу

Not NULL группа событий создана успешно, возвращаемое значение – дескриптор созданной группы событий

Функция установки битов событий

 

 

где:

xEventGroup дескриптор группы событий

uxBitsToSet битовая маска, которая указывает, какие биты в группе событий установлены в 1, а какие в 0

Возвращаемое значение типа EventBits_t возвращаемое значение не обязательно содержит биты, установленные uxBitsToSet, потому что эти биты могут быть очищены другими задачами.

 

Функция проверки битов событий

 

 

где:

xEventGroup дескриптор группы событий.

uxBitsToWaitForбитовая маска, которая определяет бит(ы) события, которые должны быть протестированы в группе событий. Например, если вызывающая задача хочет дождаться установки бита события 0 и(или) бита события 2 в группе событий, устанавливаем для uxBitsToWaitFor значение 0x05.

xClearOnExitесли вызывающая задача удовлетворяет условию разблокирования и xClearOnExit имеет значение pdTRUE, бит события, указанный в uxBitsToWaitFor, очищается перед выходом из данной функции. Если данный параметр равен pdFALSE, данная функция не будет изменять биты событий группы событий.

xWaitForAllBits если pdFALSE, то если установлен любой бит в uxBitsToWaitFor, то функция завершится со сбросом данного бита. Если установим pdTRUE, то если все биты, установленные в uxBitsToWaitFor, устанавливаются, то только тогда мы выйдем из функции и все биты событий, присутствующие в маске, также сбросятся.

xTicksToWaitтайм-аут ожидания. Если вышеуказанные требования не будут выполнены в течение установленного времени, функция будет завершена.

Возвращаемое значение типа EventBits_t если бит события установлен и условие разблокирования вызывающей задачи выполнено, возвращаемое значение является значением группы событий, которая удовлетворяет вызывающей задаче для выхода из состояния блокировки. Если выход вызван тайм-аутом, возвращаемое значение не будет соответствовать значению группы событий, которая вызвала задачу для выхода из заблокированного состояния.

 

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

 

 

Схема со времён предыдущего урока не изменилась

 

 

Проект был сделан из проекта урока 13 по программным таймерам с именем SOFT_TIMER и был назван EVENT_GROUP_LCD.

Откроем проект в Espressif IDE и сразу в файле main.h подключим библиотеку для групп событий

 

 

Перейдём в файл main.c и объявим глобальный указатель для группы событий

 

 

Сразу же объявим макросы для битов событий

 

 

Логика будет простая. Мы создадим три программных таймера. Как только сработает первый таймер — установится бит, второй таймер — другой бит, третий таймер — третий бит.

Функции periodic_timer_callback и oneshot_timer_callback пока удалим вместе с телами, мы потом добавим другие функции обратного вызова.

В функции app_main пока удалим весь код, начиная со строки

LCD_ini();

до бесконечного цикла.

В этой же функции создадим группу событий

 

 

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

 

 

 

Выше функции app_main добавим данные функции, иначе у нас код перестанет собираться

 

 

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

Вернёмся в функцию app_main и создадим, а затем запустим каждый из таймеров с периодом между запусками в 1 секунду

 

 

Выше функции app_main добавим функцию задачи, в которой мы будем следить за нашими событиями

 

 

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

Затем мы проверяем, какое именно у нас событие произошло и отображаем в соответствующей строке дисплея проинкрементированное число.

Также прежде чем у нас код нормально заработал, нам нужно данную задачу создать. Для этого идём в app_main и создаём её

 

 

Соберём код и посмотрим результат на дисплее

 

 

Число число появляется примерно раз в 1 секунду в каждой строке, значит у нас происходит отслеживание каждого события, так как таймеры запущены с разницей во времени в 1 секунду, а период срабатывания у них одинаковый.

Теперь попробуем в функции task1 четвёртый параметр поставить в pdTrue

 

EventBits_t bits = xEventGroupWaitBits(timer_event_group,
  TIMER1_EVT | TIMER2_EVT | TIMER3_EVT,
  pdTRUE,
  pdTRUE,
  portMAX_DELAY);

 

После выход из функции должен будет происходить только при условии, когда все 3 события произойдут.

Проверим это, собрав код и прошив контроллер

 

 

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

Итак, на данном уроке мы познакомились ещё с одной возможностью синхронизации потоков — с использованием групп событий (Event Group). Теперь, я думаю, настало время поработать с беспроводной связью, так как там широко используются разные типы межпроцессного взаимодействия, и, не познакомившись с ними заранее, тяжело будет понять логику работы с WiFi.

Всем спасибо за внимание!

 

Данная статья в Дзен.

 

 

Предыдущий урок Программирование МК ESP32 Следующий урок

 

Исходный код

 

 

Недорогие отладочные платы ESP32 можно купить здесь: Недорогие отладочные платы ESP32

Логический анализатор 16 каналов можно приобрести здесь

Дисплей LCD 20×4 можно приобрести здесь Дисплей LCD 20×4

Дисплей LCD 16×2

Переходник I2C to LCD можно приобрести здесь I2C to LCD1602 2004

 

 

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

ESP32 FreeRTOS. Event Groups

 

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

ESP32 FreeRTOS. Event Groups

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

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

*