banner
CoAP Protocol and Message Queues in Zephyr RTOS.

В этой статье речь пойдет об очередях сообщений (Message Queues) и обработчиках прерываний в Zephyr RTOS в контексте расширения, описанного в предыдущей статье. Коротко напомню содержание предыдущей статьи.
Программа Object Detector распознает объекты, передает их имена посредством протокола CoAP (через сервер CoAP) в Zephyr RTOS. Клиент CoAP в Zephyr RTOS принимает имена объектов, а расширение CoAP управляет рабочими потоками в соответстветствии с именами принятых объектов.
Описанное в предыдущей статье расширение протокола CoAP не передает в потоки никаких данных (команд), а от оборудования не поступает сигналов обратной связи, например, в виде прерываний. Решим эти две задачи.
Добавим в код нашего расширения CoAP две очереди сообщений (Message Queues) и два обработчика прерываний (ISR). Каждый поток будет отправлять изменяющие данные в свою очердь сообщений, а каждый обработчик прерываний будет извлекать данные из очереди сообщений. Отправляемые в очередь и извлекаемые из очереди данные будут выводиться в монитор для контроля работы приложения.
На рисунке 1 показан исходной код расширения. На рисунке 2 показан результат работы программы CoAP с расширением запущенной на плате nRF7002 DK. На рисунке 3 показана программа CoAP с расширением в режиме nRF Debug.
Отмечу, что реализация протокола CoAP принадлежит вот этому автору. Опубликованный им исходный код не изменен. Для запуска расширения к основному тексту добавлен вызов функции static void decoding_object (const uint8_t *payload). Место вызова функции показано на рисунке 4 в строке 273.
Это тридцать третья статья из цикла "Real-Time Object Recognition". Первые тридцать две опубликованы здесь: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 и 32

1. Исходный код и результат работы программы.

Рисунок 1.


Результат работы программы.

Рисунок 2.


Программа CoAP в режиме отладки.

Рисунок 3.


Место вызова функции static void decoding_object (const uint8_t *payload)

Рисунок 4.

2. Описание расширения для протокола CoAP.
Код расширения предствавлен на рис. 1.
  • В строке 33 подключается заголовочный файл для работы с портами ввода-вывода (GPIO);
  • В стрках 36-37 определяются макросы препроцессора для создания идентификаторов узлов для светодиодов led0 и led1;
  • В строке 40 определяется размер стека для потоков person и tvmonitor;
  • В строках 42-43 определяются приоритеты для потоков person и tvmonitor;
  • В строках 45-46 определяются статические константные структуруы, содержащие всю необходимую информацию для работы с GPIO-портами (led0 и led1);
  • В строках 49-53 определяется структура SensorReading, содержащая данные для передачи в потоки;
  • В строках 56-57 определяются очереди сообщений;
  • В строках 59-60 определяются семафоры для регулирования работы потоков;
  • В строке 63 определяется указатель на массив list_comparison_objects[], содержащий поисковые образы;
  • В строке 65 определяется указатель char *result на найденную строку;
  • В строке 67 определяется переменная int position, содержащая позицию в массиве поисковых образов;
  • В строках 70 - 90 находится обработчик прерываний static void tvmonitor_handler() для таймерв tvmonitor_timer;
  • В строках 92 - 103 находится обработчик прерываний static void person_handler() для таймера person_timer;
  • В строках 106 - 107 определяются таймеры tvmonitor_timer и person_timer;
  • В строках 109 - 135 находится функция static void tvmonitor_func() потока tvmonitor_thread;
  • В строках 137 - 163 находится функция static void person_func() потока person_thread;
  • В строках 165 - 166 определются потоки tvmonitor_thread и person_thread;
  • В строках 169 - 194 находится функция static void decoding_object (const uint8_t *payload) входа в расширение протокола CoAP.
Рассмотрим алгоритм работы расширения. Первой вызывается функция decoding_object (payload), смотрите строку 273 на рис. 4. В этой функции выполняется декодирование данных, получаемых от программы Object Detector, смотрите строки 169 - 194 на рис. 1. При обнаружении строк tvmonitor или person будет открыт соответствующий светофор k_sem_give(&instance_monitor_sem) или k_sem_give(&instance_person_sem), смотрите строки 188 или 185. Далее в функциях static void tvmonitor_func() или static void person_func() в очередь сообщений device_message_queue или person_message_queue будут отправлены данные, смотрите строки 121 и 149. После отправки данных вызваются функции k_timer_start(&tvmonitor_timer, K_MSEC(100), K_NO_WAIT) или k_timer_start(&person_timer, K_MSEC(100), K_NO_WAIT) для инициирования одноразового страбатывания таймеров, смотрите строки 133 и 161. Обработчики прерываний static void tvmonitor_handler() или static void person_handler() получают данные из свих очередей и выводят их в терминал, смотрите строки 79 и 101.
Обратите внимание, в данной реализации расширения запуск таймеров k_timer_start() выполняется внутри потоков. Это упрощает наблюдение за отправляемыми в очередь и получаемыми из очереди данными. В реальных устройствах прерывания формируются, как првило, в произвольное время. Для приближения расширения к работе с реальными устройствами код можно изменить, достаточно функции k_timer_start() вынести за пределы функций потоков и определить периоды срабатывания таймеров.

Расширение можно загрузить.
Консультации через e-mail: veresov@jdesign.ru или телефон: +7 921-215-45-70.
Евгений Вересов.
11.07.2026 года.