Бинарные семафоры - системные переменные, способные принимать значения "0" и "1". Это самый простой способ обмена информацией между задачами, а также для синхронизации между ними. Для экономии RAM в OSA все бинарные семафоры являются битовыми полями в переменных, создаваемых самой системой. Программист должен только указать, сколько памяти выделить под бинарные семафоры, задав в файле OSAcfg.h константу OS_BSEMS. Поэтому память под бинарные семафоры резервируется на этапе компиляции и их нельзя создавать или удалять в ходе работы программы.
При обращении к системным сервисам, управляющим бинарными семафорами, нужно указывать номер используемого семафора от 0 до (OS_BSEMS-1), т.е. его идентификатор. Идентефикаторы семафорам удобно присваивать в виде enum, тогда есть гарантия, что они не будут пересекаться:
enum OSA_BINSEMS_ENUM { BS_BUTTON_PRESSED, BS_USART_FREE, BS_WRITE_COMPLETE, . . . };
Такой подход не очень удобен, особенно, если предполагается использование отдельно написанных модулей, но является очень экономным к ресурсам ПИКа (и ROM, и RAM, и скорость): на 8 бинарных семафоров требуется всего один байт ОЗУ. Если же требуются независимые семафоры, то можно использовать счетные семафоры с сервисом установки семафора OS_Csem_Set.
После начальной инициализации сервисом OS_Init все бинарные семафры сброшены. Задача, которая ожидает бинарный семафор, будет поставлена в состояние ожидания до тех пор, пока семафор не будет установлен. Как только он установится, задача переходит в состояние готовности и при получении управления сбрасывает семафор.
Ниже приведен небольшой пример использования бинарного семафора для разделения доступа к общему ресурсу - внешенй EEPROM:
#include <osa.h> enum OSA_BINSEMS_ENUM { BS_EEPROM_FREE }; void Task1 (void) { for (;;) { ... OS_Bsem_Wait(BS_EEPROM_FREE); // Ждем, когда остальные задачи отпустят eeprom // Когда попадаем сюда, eeprom свободен, а семафор сброшен, что не позволит другим // задачам начать работу с eeprom eeprom_read(1); eeprom_read(2); OS_Bsem_Set(BS_EEPROM_FREE); // После выполнения операций с EEPROM освобождаем ресурс ... } } void Task2 (void) { for (;;) { ... OS_Bsem_Wait(BS_EEPROM_FREE); // Ждем, когда остальные задачи отпустят eeprom // Когда попадаем сюда, eeprom свободен, а семафор сброшен, что не позволит другим // задачам начать работу с eeprom eeprom_write(5, 10); OS_Delay(5); // Ждем окончания записи. При ожидании задержки // управление передается планировщику, который может // в свою очередь передать управление задаче Task1. И чтобы // Task1 не полезла в EEPROM, ресурс заблокирован бинарынм // семафором eeprom_write(6, 20); OS_Delay(5); OS_Bsem_Set(BS_EEPROM_FREE); // После выполнения операций с EEPROM освобождаем ресурс ... } }
Для PIC16 программист может выбрать, в каком банке RAM будут храниться бинарные семафоры. Для этого есть константа OS_BANK_BSEMS, которая может принимать значения от 0 до 3. Все бинарные семафоры размещаются в одном банке; нельзя половину опрелелить,например, в bank0, а оставшиеся - в bank2. В памяти бинарные семафоры представлены как массив unsigned char, поэтому эта структура неделима.
Сервис | Аргументы | Описание | Свойства |
---|---|---|---|
Управление | |||
OS_Bsem_Set | (bsem) | Устанавливает семафор | |
OS_Bsem_Reset | (bsem) | Сбрасывает семафор | |
OS_Bsem_Switch | (bsem) | Переключает семафор в противоположное состояние | |
Проверка | |||
OST_WORD OS_Bsem_Check | (bsem) | Смотрим, установлен ли конкретный семафор | |
Ожидание | |||
OS_Bsem_Wait | (bsem) | Ожидаем установку семафора. | |
OS_Bsem_Wait_TO | (bsem, timeout) | Ожидаем установку семафора с таймаутом. |