Available Languages?:

OSA : Сообщения

Введение

Сообщения - один из способов обмена информацией между задачами. Телом сообщения может быть все, что угодно: принятые по USART или прочитанные из EEPROM данные, состояния внешних датчиков, информация о нажатых кнопках и пр. В OSA предусмотрены два типа сообщений: указатели на сообщения и короткие однобайтовые сообщения.

Первые - наиболее общие, которые позволяют обмениваться любой информацией, любого размера и содержания. Между задачами идет обмен указателями на тела сообщений. Вторые - однобайтовые сообщения, которые могут принимать значения от 1 до 255 (0 - сообщение отсутствует). Этот тип сообщения реализован в OSA для экономии RAM. В отличие от указателя на сообщение, который занимает в памяти 2 байта (для PIC16) или 3 байта (для остальных пиков), короткое сообщение занимает 1 байт. Ниже будут рассмотрены оба типа сообщений.

Сообщение может находиться в двух состояниях: свободно и занято. Если в данный момент сообщение содержит полезную информацию (т.е. было отправлено какой-то задачей, но еще не обработано задачей, ждущей его), то сообщение считается занятым. Иначе - свободным.

Указатели на сообщения

Тип указателя определен по умолчанию как void*. Но его можно изменить, задав константу OST_MSG в файле OSAcfg.h. Например, его можно задать так:

#define OS_MSG_TYPE    const char *

и передавать в сообщениях текстовые строки.

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

Для отправки сообщения существуют 3 сервиса: OS_Msg_Send, OS_Msg_Send_TO и OS_Msg_Send_Now.

OS_Msg_Send перед отправкой проверяет, свободно ли сообщение. Если нет (задача, которой сообщения отсылаются, по какой-то причине еще не обработала предыдущее), то сервис переводит задачу в состояние ожидания до тех пор, пока сообщение не освободится. Как только сообщение освободится, задача переводится в состояние готовности, и при получении управления она отправит новое сообщение.

OS_Msg_Send_TO - то же, что и OS_Msg_Send, только может выйти по таймауту, если предыдущее сообщение долго не освобождается.

OS_Msg_Send_Now перед отправкой сообщения не обращает внимания на то, занято сообщение или свободно. Предыдущее сообщение, если оно еще не обработано, затирается новым.

Для проверки занятости сообщения есть сервис OS_Msg_Check, который возвращает ноль, если сообщение свободно.

Ниже приведен пример использования указателя на сообщение:

OST_MSG_CB    msg_cb;
 
void Task_USARTReceive (void)
{
    static char BUF[10];        // Буфер для приема данных по UART
    static char Message[10];    // Тело сообщения
 
    OS_Msg_Create(msg_cb);         // Создаем сообщение перед работой с ним
    for (;;){
        ...
        // Получаем данные и пишем их в буфер BUF
        ...
        // Проверяем, обработалось ли предыдущее сообщение
        OS_Cond_Wait(!OS_Msg_Check(msg_cb));
        // Когда попали сюда, му уже уверены, что предыдущее сообщение
        // обработано и Message[] уже не содержит никакой полезной информации
 
        // Теперь копируем данные из буфера в тело сообщения Message[]
        memcpy(Message, BUF, 10);
        // и отправляем сообщение
        OS_Msg_Send(msg_cb, (OST_MSG)Message);
        ...
    }
}
 
. . .
 
void Task_Work (void)
{
    OST_MSG msg;
    for (;;) {
        OS_Msg_Wait(msg_cb, msg);
        // Здесь msg уже является указателем на Message
        // из задачи Task_USARTReceive.
        // После выполнения этого сервиса сообщение освобождается.
        ...
    }
}

Короткие однобайтовые сообщения

Тип короткого сообщения по умолчанию unsigned char, однако, он может быть изменен в файле OSAcfg.h заданием константы OST_SMSG:

#define OS_SMSG_TYPE    unsigned long  // изменение типа SMSG

Если его изменять, то теряется преимущество в использовании RAM. Тем не менее, это иногда может оказаться полезным с точки зрения функционирования программы. Например, при использовании указателя на сообщение, телом которого является unsigned long, мы не можем изменять содержимое тела сообщения, пока сообщение не будет получено и обработано другой задачей (в пердыдущем примере Message[]). В случае с короткими сообщениями это ограничение снимается, т.к. все тело сообщения записывается в переменную сообщения.

Нельзя задавать типом короткого сообщения структуры, массивы и объединения. Короткому однобайтовому сообщени можно давать только числовой тип: char, int long, bit, а также float и double.

Во всем остальном работа с короткими сообщениями повторяет работу с указателями на сообщения.Ниже приведен пример использования короткого сообщения:

OST_SMSG  smsg_Buttons;
. . .
 
void Task_Buttons (void)
{
    OS_Smsg_Create(smsg_Buttons);
    for (;;) {
        . . .
        if (!RB0 || !RB1 || !RB2)
            OS_Smsg_Send(smsg_Buttons, (OST_SMSG)PORTB & 0x07);
        ...
    }
}
 
...
 
void Task_Work (void)
{
    OST_SMSG smsg;
    for (;;) {
        OS_Smsg_Wait(smsg_Buttons, smsg);
        // Обработка нажатой кнопки
        if (smsg & 0x01) ...;
        if (smsg & 0x02) ...;
        if (smsg & 0x04) ...;
        ...
    }
}

Сервисы для работы с сообщниями

Сообщения

Сервис Аргументы Описание Свойства
Создание
OS_Msg_Create (msg_cb) Создает сообщение. Нельзя вызывать из прерывания
Отправка
OS_Msg_Send (msg_cb, message) Отправляем сообщение msg_cb (тип OST_MSG_CB) с ожиданием освобождения Разрешен вызов только в контексте задачиПереключает контекст
OS_Msg_Send_TO (msg_cb, message, timeout) То же, что и OS_Msg_Send с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
OS_Msg_Send_Now (msg_cb, message) Отправляем сообщение msg_cb без ожидания освобождения Есть расширенный сервис с суффиксом _I для работы в прерывании
Проверка
bool
OS_Msg_Check
(msg_cb) Проверить, активно ли сообщение (присутствует ли оно). Есть расширенный сервис с суффиксом _I для работы в прерывании
OS_Msg_Accept (msg_cb, os_msg_type_var) Принять существующее сообщение. Есть расширенный сервис с суффиксом _I для работы в прерывании
Ожидание
OS_Msg_Wait (msg_cb, os_msg_type_var) Ожидаем сообщение msg_cb. Разрешен вызов только в контексте задачиПереключает контекст
OS_Msg_Wait_TO (msg_cb, os_msg_type_var, timeout) То же, что и OS_Msg_Wait, с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер

Короткие сообщения

Сервис Аргументы Описание Свойства
Создание
OS_Smsg_Create (smsg) Создает короткое сообщение (фактически - просто обнуляет его)
Отправка
OS_Smsg_Send (smsg, smessage) Отправляем сообщение smsg с содержимым smessage с ожиданием освобождения Разрешен вызов только в контексте задачиПереключает контекст
OS_Smsg_Send_TO (smsg, smessage, timeout) То же, что и OS_Smsg_Send, но с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
OS_Smsg_Send_Now (smsg, smessage) Отправляем короткое сообщение smsg с содержимым smessage без ожидания освобождения Есть расширенный сервис с суффиксом _I для работы в прерывании
Проверка
bool
OS_Smsg_Check
(smsg) Проверить, активно ли сообщение (присутствует ли оно). Есть расширенный сервис с суффиксом _I для работы в прерывании
OS_Smsg_Accept (smsg, os_smsg_type_var) Принять существующее сообщение Есть расширенный сервис с суффиксом _I для работы в прерывании
Ожидание
OS_Smsg_Wait (smsg, os_smsg_type_var) Ожидаем короткое сообщение smsg. Разрешен вызов только в контексте задачиПереключает контекст
OS_Smsg_Wait_TO (smsg, os_smsg_type_var, timeout) То же, что и OS_Smsg_Wait, с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
 
osa/ref/services/messages.txt · Последние изменения: 07.10.2010 13:54 (внешнее изменение)
 
Creative Commons License Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki