====== OSA : Бинарные семафоры ======
===== Введение =====
Бинарные семафоры - системные переменные, способные принимать значения "0" и "1". Это самый простой способ обмена информацией между задачами, а также для синхронизации между ними. Для экономии RAM в OSA все бинарные семафоры являются битовыми полями в переменных, создаваемых самой системой. Программист должен только указать, сколько памяти выделить под бинарные семафоры, задав в файле ##[[osa:ref:appendix:configuration|OSAcfg.h]]## константу [[osa:ref:appendix:configuration|OS_BSEMS]]. Поэтому память под бинарные семафоры резервируется на этапе компиляции и их нельзя создавать или удалять в ходе работы программы.
===== Идентификация =====
При обращении к системным сервисам, управляющим бинарными семафорами, нужно указывать номер используемого семафора от 0 до (##[[osa:ref:appendix:configuration|OS_BSEMS]]##-1), т.е. его идентификатор. Идентефикаторы семафорам удобно присваивать в виде enum, тогда есть гарантия, что они не будут пересекаться:
enum OSA_BINSEMS_ENUM
{
BS_BUTTON_PRESSED,
BS_USART_FREE,
BS_WRITE_COMPLETE,
. . .
};
Такой подход не очень удобен, особенно, если предполагается использование отдельно написанных модулей, но является очень экономным к ресурсам ПИКа (и ROM, и RAM, и скорость): на 8 бинарных семафоров требуется всего один байт ОЗУ. Если же требуются независимые семафоры, то можно использовать [[osa:ref:services:counting_semaphores|счетные семафоры]] с сервисом установки семафора ##[[osa:ref:allservices:OS_Csem_Set|OS_Csem_Set]]##.
~~UP~~
===== Работа с бинарными семафорами =====
После начальной инициализации сервисом ##[[osa:ref:allservices:OS_Init|OS_Init]]## все бинарные семафры сброшены. Задача, которая ожидает бинарный семафор, будет поставлена в состояние ожидания до тех пор, пока семафор не будет установлен. Как только он установится, задача переходит в состояние готовности и при получении управления сбрасывает семафор.
Ниже приведен небольшой пример использования бинарного семафора для разделения доступа к общему ресурсу - внешенй EEPROM:
#include
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 освобождаем ресурс
...
}
}
~~UP~~
===== Размещение в памяти =====
Для PIC16 программист может выбрать, в каком банке RAM будут храниться бинарные семафоры. Для этого есть константа [[osa:ref:appendix:configuration|OS_BANK_BSEMS]], которая может принимать значения от 0 до 3. Все бинарные семафоры размещаются в одном банке; нельзя половину опрелелить,например, в bank0, а оставшиеся - в bank2. В памяти бинарные семафоры представлены как массив unsigned char, поэтому эта структура неделима.
~~UP~~
===== Сервисы для работы с двоичными семафорами. =====
^ Сервис ^ Аргументы ^ Описание ^ Свойства ^
| **Управление** ||||
| ##[[osa:ref:allservices:OS_Bsem_Set|OS_Bsem_Set]]## | ''(bsem)'' | Устанавливает семафор | {{osa:ref:attr_call_can_int.png|Есть расширенный сервис с суффиксом _I для работы в прерывании}} |
| ##[[osa:ref:allservices:OS_Bsem_Reset|OS_Bsem_Reset]]## | ''(bsem)'' | Сбрасывает семафор | {{osa:ref:attr_call_can_int.png|Есть расширенный сервис с суффиксом _I для работы в прерывании}} |
| ##[[osa:ref:allservices:OS_Bsem_Switch|OS_Bsem_Switch]]## | ''(bsem)'' | Переключает семафор в противоположное состояние | {{osa:ref:attr_call_can_int.png|Есть расширенный сервис с суффиксом _I для работы в прерывании}} |
| **Проверка** ||||
| [[osa:ref:description:data_types#OST_WORD|OST_WORD]]\\ ##[[osa:ref:allservices:OS_Bsem_Check|OS_Bsem_Check]]## | ''(bsem)'' | Смотрим, установлен ли конкретный семафор | {{osa:ref:attr_call_can_int.png|Есть расширенный сервис с суффиксом _I для работы в прерывании}} |
| **Ожидание** ||||
| ##[[osa:ref:allservices:OS_Bsem_Wait|OS_Bsem_Wait]]## | ''(bsem)'' | Ожидаем установку семафора. | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}} |
| ##[[osa:ref:allservices:OS_Bsem_Wait_TO|OS_Bsem_Wait_TO]]## | ''(bsem, timeout)'' | Ожидаем установку семафора с таймаутом. | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}}{{osa:ref:attr_call_to.png|Использует системный таймер}} |
~~UP~~