Содержание

OSA : Флаги

Введение

Флаги, по сути, очень похожи на бинарные семафоры. Есть две принципиальные разницы:

  1. одним сервисом можно обработать несколько флагов сразу (например, можно ждать установки хотя бы одного из нескольких флагов или установки сразу нескольких);
  2. после завершения ожидания флаги, в отличие от бинарных семафоров, не сбрасываются.

Применение флагов может быть полезным, когда какой-то задаче для продолжения работы необходимы результаты работы сразу нескольких задач. Например, задаче для вычисления каких-то физических параметров необходимы сведения о температуре, давлении и влажности. Каждая из этих физических величил измеряется в отдельной задаче, которая по завершении измерения устанавливает соответствующий флаг.

#include <osa.h>
 
OST_FLAG8   F_Sensors;
 
#define  TEMPERATURE_MEASURED   0x01
#define  PRESSURE_MEASURED      0x02
#define  HUMIDITY_MEASURED      0x04
 
void Task_Calc (void)
{
    for (;;) {
        // Ждем завершения измерений
        OS_Flag_Wait_AllOn(F_Sensors, TEMPERATURE_MEASURED | PRESSURE_MEASURED | HUMIDITY_MEASURED);
        OS_Flag_Clear(F_Sensors, TEMPERATURE_MEASURED | PRESSURE_MEASURED | HUMIDITY_MEASURED);
 
        // Теперь можно начинать расчеты
        ...
    }
}

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

#include <osa.h>
 
OST_FLAG8    F_Doors;      // Флаги, отражающие состояние каждой двери: 1 - открыта, 0 - закрыта
                           // Устанавливаются и сбрасываются в задаче обработки датчиков
 
#define DOORS_MASK   0x0F  // Маска битов, отражающих состояние дверей
#define TRUNK_MASK   0x30  // Маска битов, отражающих состояние капота и багажника
 
void Task_Guard (void)
{
    for (;;) {
        OS_Bsem_Wait(BS_CMD_GUARD);    // Получили команду с брелока "Постановка на охрану"
 
        // Ждем, когда будут закрыты все двери, капот и багажник
        OS_Flag_Wait_AllOff(F_Doors, DOORS_MASK | TRUNK_MASK);
 
        // Начиная отсюда, переходим в режим охраны:
        // подаем звуковые и световые сигналы, берем под охрану все датчики и пр.
        ...
    }
}

Объявление флагов

Флаги могут быть 8-, 16- и 32-разрядные. В программе объявляются так:

OST_FLAG      MyFlag1;	//  8-разрядные флаги
OST_FLAG16    MyFlag2;	// 16-разрядные флаги
OST_FLAG32    MyFlag3;	// 32-разрядные флаги

Флаги можно определять в любом банке памяти, например:

bank2    OST_FLAG16   MyFlag;

В программе могут одновременно использоваться флаги разных разрядностей.

Для работы с флагами их нужно создать сервисом OS_Flag_Create. Этого можно и не делать, но тогда их начальное значение будет не определено. Ниже приведены все системные сервисы для работы с флагами.

Сервисы для работы с флагами.

Сервис Аргументы Описание Свойства
Создание
OS_Flag_Create (flags) Создает флаги (фактически просто сбрасывает все флаги)
Управление
OS_Flag_Init (flags, value) Устанавливает все флаги в заданное значение Есть расширенный сервис с суффиксом _I для работы в прерывании
OS_Flag_Set (flags, mask) Установка флагов по маске Есть расширенный сервис с суффиксом _I для работы в прерывании
OS_Flag_Clear (flags, mask) Сброс флагов по маске Есть расширенный сервис с суффиксом _I для работы в прерывании
Проверка
bool
OS_Flag_Check_AllOn
(flags, mask) Проверить, все ли флаги по маске установлены Есть расширенный сервис с суффиксом _I для работы в прерывании
bool
OS_Flag_Check_On
(flags, mask) Проверить, есть ли хотя бы один установленный флаг по маске Есть расширенный сервис с суффиксом _I для работы в прерывании
bool
OS_Flag_Check_AllOff
(flags, mask) Проверить, все ли флаги по маске сброшены Есть расширенный сервис с суффиксом _I для работы в прерывании
bool
OS_Flag_Check_Off
(flags, mask) Проверить, есть ли хотя бы один сброшенный флаг по маске Есть расширенный сервис с суффиксом _I для работы в прерывании
Ожидание
OS_Flag_Wait_AllOn (flags, mask) Ожидаем установки всех флагов по маске Разрешен вызов только в контексте задачиПереключает контекст
OS_Flag_Wait_On (flags, mask) Ожидаем установки хотя бы одного флага из маски Разрешен вызов только в контексте задачиПереключает контекст
OS_Flag_Wait_AllOff (flags, mask) Ожидаем сброса всех флагов по маске Разрешен вызов только в контексте задачиПереключает контекст
OS_Flag_Wait_Off (flags, mask) Ожидаем сброса хотя бы одного флага из маски Разрешен вызов только в контексте задачиПереключает контекст
OS_Flag_Wait_AllOn_TO (flags, mask, timeout) Ожидаем установки всех флагов по маске с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
OS_Flag_Wait_On_TO (flags, mask, timeout) Ожидаем установки хотя бы одного флага из маски с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
OS_Flag_Wait_AllOff_TO (flags, mask, timeout) Ожидаем сброса всех флагов по маске с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер
OS_Flag_Wait_Off_TO (flags, mask, timeout) Ожидаем сброса хотя бы одного флага из маски с выходом по таймауту Разрешен вызов только в контексте задачиПереключает контекстИспользует системный таймер