Mailboxes в Nucleus SE: Практическое руководство по конфигурации и использованию
View the RTOS Revealed series
Mailboxes были введены в предыдущей статье как один из самых простых механизмов межзадачного взаимодействия в Nucleus SE — сразу после сигналов. Они предлагают низкозатратный, высокогибкий способ передачи простых данных между задачами.
Использование Mailboxes
В Nucleus SE mailboxes определяются на этапе сборки. Максимум 16 mailboxes может быть сконфигурировано на приложение. Если вы конфигурируете ноль mailboxes, компилятор опускает все связанные структуры данных и API код, держа бинарник lean.
Mailbox по сути — слот хранения, способный удерживать одну переменную типа ADDR. Только одна задача может писать в mailbox за раз. Как только он полон, последующие попытки записи будут проваливаться до тех пор, пока mailbox не будет прочитан или сброшен. В зависимости от опций API, попытка записи в полный mailbox может вернуть ошибку или приостановить задачу до появления места.
Mailboxes против Queues
Некоторые операционные системы заменяют mailboxes на single-entry queue. Хотя queue может имитировать поведение mailbox, он несет дополнительные накладные расходы — head и tail указатели, более крупные структуры данных и больше путей кода — ведущие к более высокому использованию памяти и времени выполнения.
В Nucleus SE вы можете выбрать либо mailboxes, либо queues. Если ваш дизайн использует много queues но только несколько mailboxes, замена mailbox на queue слегка увеличит размер данных, но устранит mailbox-специфичный API код, упрощая обслуживание. Легко протестировать обе конфигурации для сравнения memory footprint и производительности.
Queues будут рассмотрены в будущей статье.
Конфигурация Mailboxes
Количество Mailboxes
Ключевой макрос в nuse_config.h — NUSE_MAILBOX_NUMBER. Значение по умолчанию 0, означающее, что mailboxes не включены. Вы можете установить его в любое целое от 1 до 16. Compile-time проверка в nuse_config_check.h вызовет ошибку, если значение вне диапазона.
Установка ненулевого значения активирует mailbox подсистему: структуры данных размерятся, и символы включения API обрабатываются.
API Enables
У каждого mailbox API вызова есть соответствующий #define в nuse_config.h:
NUSE_MAILBOX_SENDNUSE_MAILBOX_RECEIVENUSE_MAILBOX_RESETNUSE_MAILBOX_INFORMATIONNUSE_MAILBOX_COUNT
По умолчанию все установлены в FALSE, отключая вызов и его реализацию. Для использования API включите соответствующий макрос, установив его в TRUE. Включение API без сконфигурированных mailboxes вызовет compile-time ошибку (кроме NUSE_Mailbox_Count(), который всегда доступен). Использование отключенного API произведет link-time ошибку.
/* Number of mailboxes in the system – 0-16 */ #define NUSE_MAILBOX_NUMBER 0 /* Service call enablers: */ #define NUSE_MAILBOX_SEND FALSE #define NUSE_MAILBOX_RECEIVE FALSE #define NUSE_MAILBOX_RESET FALSE #define NUSE_MAILBOX_INFORMATION FALSE #define NUSE_MAILBOX_COUNT FALSE
Mailbox Service Calls
Nucleus SE предлагает девять mailbox-связанных service calls. Реализованные в SE:
- NUSE_Mailbox_Send() — запись сообщения в mailbox.
- NUSE_Mailbox_Receive() — чтение сообщения из mailbox.
- NUSE_Mailbox_Reset() — очистка mailbox без приостановки задач.
- NUSE_Mailbox_Information() — запрос статуса mailbox.
- NUSE_Mailbox_Count() — возврат числа сконфигурированных mailboxes.
Другие функции такие как создание, удаление, bulk retrieval и broadcast не реализованы в SE.
Операции записи и чтения
Mailboxes поддерживают две основные операции: отправку (запись) и получение (чтение). Оба API доступны в Nucleus RTOS и Nucleus SE, с некоторыми различиями в гибкости и обработке ошибок.
Отправка в Mailbox
В Nucleus RTOS вызов NU_Send_To_Mailbox поддерживает неопределенное или таймаут-приостановку, если mailbox полон. Nucleus SE предлагает упрощенную версию: приостановка опциональна, таймауты не поддерживаются.
Пример прототипа для Nucleus SE:
STATUS NUSE_Mailbox_Send(NUSE_MAILBOX mailbox, ADDR *message, U8 suspend);
Параметры:
mailbox— индекс mailbox.message— указатель наADDRпеременную.suspend—NUSE_NO_SUSPENDилиNUSE_SUSPEND.
Возвращаемые значения включают NUSE_SUCCESS, NUSE_INVALID_MAILBOX, NUSE_MAILBOX_FULL и NUSE_MAILBOX_WAS_RESET.
Обзор реализации
Когда блокировка отключена, рутина проверяет флаг статуса mailbox. Если mailbox пуст, она записывает данные и помечает mailbox как полный; иначе возвращает NUSE_MAILBOX_FULL.
С включенной блокировкой код циклится до успешной отправки сообщения или пробуждения задачи операцией receive. Если задача приостановлена на mailbox, она немедленно возобновляется после успешной отправки.
Следующий фрагмент демонстрирует основную логику когда блокировка включена (упрощено для читаемости):
do { if (!NUSE_Mailbox_Status[mailbox]) { // Mailbox пуст — сохраняем данные и будим ожидающую задачу если есть. } else if (suspend == NUSE_NO_SUSPEND) { return NUSE_MAILBOX_FULL; } else { // Приостанавливаем задачу до освобождения mailbox. } } while (suspend == NUSE_SUSPEND);
В итоге, mailbox API балансирует простоту и гибкость, позволяя разработчикам выбирать между немедленным провалом или приостановкой задачи в зависимости от тайминговых требований их приложения.
Встроенный
- Камерные замки (Cam Locks): как они скрыто запирают шкафы
- Что такое кольцевые винты (Eye Screws)? Профессиональное руководство по дизайну и применению
- Громметы: виды, применение и защита вашего оборудования
- Нержавеющая сталь: состав, производство и глобальное влияние
- COVID-19 и облако: как крупные провайдеры усилили бизнес во время пандемии
- Основы ввода-вывода в C#: Console.WriteLine, ReadLine и форматирование
- Семафоры в Nucleus RTOS: Утилитарные сервисы и структуры данных
- Семафоры в Nucleus SE: Обзор, конфигурация и основы API
- Мастерство Event Flag Groups: Утилитарные сервисы и структуры данных в Nucleus RTOS/SE
- Event Flag Groups в Nucleus SE: Вводное руководство по конфигурации и использованию API