====== 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~~