====== OSA : Системные сервисы ====== ===== Общие системные сервисы ===== ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Init|OS_Init]](##////##)## |Инициализация переменных системы. Должна вызываться один раз в начале программы (до основного цикла).| {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | Выполняет начальную инициализация переменных системы OSA. Должна вызываться один раз в начале программы (до основного цикла). Этот сервис обнуляет список задач, сбрасывает все бинарные семафоры, очищает список динамических таймеров. ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Timer|OS_Timer]](##////##)## |Обработка всех таймеров (вставляется в периодическое место в программе, например, в прерывание по таймеру). Эта функция должна использоваться, если в программе есть ##[[osa:ref:allservices:OS_Delay|OS_Delay]]##, работа с ##[[osa:ref:services:timers|пользовательскими таймерами]]## или ожидание событий с таймаутом. | {{osa:ref:attr_call_to.png|Сервис использует таймаут}} |Ожидание Этот сервис должен использоваться, если в программе есть одно из ниже перечисленного: * использование сервиса ##[[osa:ref:allservices:OS_Delay|OS_Delay]]##; * работа со статическими или динамическими таймерами; * ожидание событий с таймаутом. Период вызова сервиса ##[[osa:ref:allservices:OS_Timer|OS_Timer]]## называется __**системным тиком**__ и является внутренней системной единицей времени. Сервис ##[[osa:ref:allservices:OS_Timer|OS_Timer]]## управляет: - Системным таймером, по которому отсчитываются задержки ##[[osa:ref:allservices:OS_Delay|OS_Delay]]## и отслеживаются таймауты для ожидания событий. - Пользовательскими таймерами (динамическими и статическими). При каждом вызове ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##() все активные таймеры увеличиваются на 1 (все неактивные - пропускаются), кроме 24-битных статических таймеров, которые уменьшаются 1 раз в 256 вызовов (см. 2.12.2.1). Пример использования: void interrupt isr() { if (T0IE && T0IF) { TMR0 -= 250; T0IF = 0; OS_Timer(); } } ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Yield|OS_Yield]] (##////##)## |Передача управления планировщику| {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}} | Этот сервис безусловно передает управление операционной системе, давая, таким образом, возможность выполниться другим задачам. ~~UP~~ ===== Сервисы ожидания ===== ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Delay|OS_Delay]] (##//delaytime//##)## |Выдерживаем паузу внутри задачи (в тиках - периодах вызова ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##)| {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}}{{osa:ref:attr_call_to.png|Сервис использует таймаут}} | Переводит задачу в состояние ожидания на время, заданное параметром //delaytime//. Параметр задается в системных тиках - периодах вызова сервиса ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##. Например, если в задаче требуется выводить индикацию температуры раз в секунду, то можно воспользоваться этим сервисом (в этом примере предполагаем, что системный тик, т.е. интервал вызова ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##() равен 10 мс): void Task_Indicate (void) { for (;;) { OS_Delay(100); // Задержка = 100 * 10 мс = 1 сек IndicateTemerature(); // Отображаем температуру } } Используя этот сервис (и вообще, все сервисы ожидания с таймаутами), следует быть внимательным и помнить, что ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##, который отсчитывает системные тики для них, - **дискретный**. Следовательно, точность задания задержки равна одному тику системного таймера. Если системный тик равен 10 мс, то ##[[osa:ref:allservices:OS_Delay|OS_Delay]]##(1) - может прождать 10 мс, а может и ничего не прождать (зависит от того, через какое время произойдет вызов ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##()). Поэтому нужно либо быть уверенным в том, что длительность задержки не существенна для конкретной задачи, либо сократить интервал вызова ##[[osa:ref:allservices:OS_Timer|OS_Timer]]## и увеличить параметр //delaytime// в ##[[osa:ref:allservices:OS_Delay|OS_Delay]]##. Например, участив в 10 раз вызов ##[[osa:ref:allservices:OS_Timer|OS_Timer]]##, т.е. превратив системный тик в 1 мс (вместо 10 мс) мы можем написать: ##[[osa:ref:allservices:OS_Delay|OS_Delay]]##(10) - и быть уверенными, что задержка будет 9-10мс. ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Wait|OS_Wait]] (##//condition//##)## |Ожидаем выполнения условия| {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}} | Переводит задачу в режим ожидания до тех пор, пока не будет выполнено заданное условие. Условием //condition// в данном случае может быть любое выражение перечислимого типа (bool, char, int и т.д.). Как только условие выполняется, задача переходит в состояние готовности и, как только становится самой приоритетной из всех готовых, получает управление. Исключение - [[osa:ref:description:events_and_priority#Состязания приоритетов|состязяние приоритетов]]. ... OS_Wait(m_nInPulseCounter >= 10 || m_bButtonPressed); ... В этом примере //m_nInPulseCounter// и //m_bButtonPressed// - некие внешние глобальные переменные, которые изменяются где угодно в программе (например, в прерывании). Программа будет в режиме ожидания, пока условие не выполнится (в нашем примере, пока не придет больше 10 импульсов, или пока не будет нажата кнопка). \\ ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_Wait_TO|OS_Wait_TO]] (##//condition, timeout//##)## |Ожидаем выполнения условия с таймаутом | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}}{{osa:ref:attr_call_to.png|Сервис использует таймаут}} | То же самое, что и ##[[osa:ref:allservices:OS_Wait|OS_Wait]]##, но с дополнительным условием выхода - таймаутом. Задача переводится в состояние ожидание до тех пор, пока не быдет выполнено условие //condition// или пока не пройдет время //timeout//. Таймаут задается в системных тиках. ... OS_Wait_TO(m_bButtonPressed, 100); if (OS_IsTimeout()) ...; ... В данном примере мы в течение 100 тиков (если 1 тик = 10мс, то в течение секунды) ждем нажатия кнопки. После выхода из ожидания проверяем, по какой причине вышли из ожидания: по выполнению условия или по таймауту. ~~UP~~ ===== Состояние системы ===== Все сервисы проверки состояния системы вызвращают либо 0 либо 1, в зависимости от состояния внутренних системных флагов. ^ Сервис ^ Описание ^ Свойства ^ |##//bool// [[osa:ref:allservices:OS_IsTimeout|OS_IsTimeout]] (##////##)## |Проверка, вышли ли из ожидания по таймауту| {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_to.png|Сервис использует таймаут}} | Этот сервис можно применять только в задачах после любого сервиса ожидания с таймаутом для проверки, по какой причине вышли из ожидания: дождались ли того, что ждали, или по таймауту. Возвращает 1, если вышли из ожидания по таймауту. ^ Сервис ^ Описание ^ Свойства ^ |##//bool// [[osa:ref:allservices:OS_IsError|OS_IsError]] (##////##)## |Проверка, была ли ошибка| | Системными ошибками счиатаюстя: * Ошибка создания задачи (нет свободного дескриптора) ^ Сервис ^ Описание ^ Свойства ^ |##//bool// [[osa:ref:allservices:OS_IsEventError|OS_IsEventError]] (##////##)## |Проверка, была ли ошибка события | | Ошибками события считаются: * Попытка увеличить счетный семафор, если он уже имеет максимальное значение * Выход по таймауту из ожидания события (от ##[[osa:ref:allservices:OS_IsTimeout|OS_IsTimeout]]## отличается тем, что доступен в любом месте программы, а не только внутри задачи) * Посылка сообщения в очередь, когда в ней нет свободного места ^ Сервис ^ Описание ^ Свойства ^ |##//bool// [[osa:ref:allservices:OS_IsInCriticalSection|OS_IsInCriticalSection]] (##////##)## |Возвращает 1, если одна из задач находится в критической секции.| | ~~UP~~ ===== Сервисы управления прерываниями ===== ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_EnterInt|OS_EnterInt]] (##////##)## | **Для PICC и PICC18**: Должна выполняться при входе в прерывание (сохраняет FSR)| {{osa:ref:attr_call_int.png|Разрешен вызов только в прерывании}} | \\ ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_LeaveInt|OS_LeaveInt]] (##////##)## | **Для PICC и PICC18**: Должна выполняться перед выходом из прерывания (восстанавливает FSR)| {{osa:ref:attr_call_int.png|Разрешен вызов только в прерывании}} | ##[[osa:ref:allservices:OS_EnterInt|OS_EnterInt]]## вставляется в самом начале прерывания, сразу после описания переменных функции прерывания, а ##[[osa:ref:allservices:OS_LeaveInt|OS_LeaveInt]]## - в самом конце перед закрывающей скобкой "}". Например: void interrupt int_routine (void) { char var1, var2; int var3; OS_EnterInt(); ... // Здесь делается проверка флагов прерываний ... // и обработка OS_LeaveInt(); } ^ Сервис ^ Описание ^ Свойства ^ |##//char// [[osa:ref:allservices:OS_DI|OS_DI]] (##////##)## |Запретить прерывания. Текущие значения GIEx сохраняются| {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | Этот сервис не просто запрещает прерывания, а еще возвращает состояние битов GIEx. Для PIC18 при IPEN=1 запрещаются (и, соответственно, сохраняются) GIEH и GIEL, а при IPEN=0 - только GIE. \\ ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_EI|OS_EI]] (##////##)## |Разрешить прерывания| {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | Сервис ##[[osa:ref:allservices:OS_EI|OS_EI]]##() разрешает прерывания. Для PIC18 при IPEN=1 разрешаются и GIEH и GIEL, а при IPEN=0 - только GIE. \\ ^ Сервис ^ Описание ^ Свойства ^ |##[[osa:ref:allservices:OS_RI|OS_RI]] (##//char//##)## |Восстановить сохраненные в ##[[osa:ref:allservices:OS_DI|OS_DI]]##() значения GIEx. | {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | Сервис ##[[osa:ref:allservices:OS_RI|OS_RI]]##(char) восстанавливает прерывания из параметра char (полученного сервисом ##[[osa:ref:allservices:OS_DI|OS_DI]]##()). Для PIC18 при IPEN=1 восстанавливаются и GIEH и GIEL, а при IPEN=0 - только GIE. Этот сервис восстанавливает только единичное значение флагов! Т.е. если флаг GIE == 0 был сохранен сервисом ##[[osa:ref:allservices:OS_DI|OS_DI]]##, потом установлен сервисом ##[[osa:ref:allservices:OS_EI|OS_EI]]##, то при выполнении сервиса ##[[osa:ref:allservices:OS_RI|OS_RI]]## он не установится обратно в 0. Ниже приведен пример использования этих сервисов при генерации одиночного импульса длительностью 5 тактов: { char gie_temp; ... gie_temp = OS_DI(); RB0 = 1; NOP(); NOP(); NOP(); NOP(); RB0 = 0; OS_RI(gie_temp); ... } ~~UP~~ ==== Системные сервисы ==== ^ Сервис ^ Аргументы ^ Описание ^ Свойства ^ | **Системные** |||| | ##[[osa:ref:allservices:OS_Sched|OS_Sched]]## | '''' | Основная работа операционки, вызывается в главном цикле функции main() | | | ##[[osa:ref:allservices:OS_Run|OS_Run]]## | '''' | Запускает ядро операционки в работу. | **main()** | | ##[[osa:ref:allservices:OS_Init|OS_Init]]## | '''' | Инициализация переменных системы. | {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | | ##[[osa:ref:allservices:OS_Timer|OS_Timer]]## | '''' | Обработка всех таймеров | {{osa:ref:attr_call_to.png|Использует системный таймер}} | | **Ожидание** |||| | ##[[osa:ref:allservices:OS_Yield|OS_Yield]]## | '''' | Передача управления планировщику | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}} | | ##[[osa:ref:allservices:OS_Delay|OS_Delay]]## | ''(delaytime)'' | Выдерживаем паузу внутри задачи | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}}{{osa:ref:attr_call_to.png|Использует системный таймер}} | | ##[[osa:ref:allservices:OS_Wait|OS_Wait]]## | ''(condition)'' | Ожидаем выполнения условия | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}} | | ##[[osa:ref:allservices:OS_Wait_TO|OS_Wait_TO]]## | ''(condition, timeout)'' | Ожидаем выполнения условия с таймаутом | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}}{{osa:ref:attr_call_ct_sw.png|Переключает контекст}}{{osa:ref:attr_call_to.png|использует системный таймер}} | | **Проверка состояния** |||| | ''bool ''\\ ##[[osa:ref:allservices:OS_IsTimeout|OS_IsTimeout]]## | '''' | Проверка, вышли ли из ожидания по таймауту | {{osa:ref:attr_call_to.png|Использует системный таймер}} | | ''bool ''\\ ##[[osa:ref:allservices:OS_IsError|OS_IsError]]## | '''' | Проверка, была ли ошибка | | | ''bool ''\\ ##[[osa:ref:allservices:OS_IsEventError|OS_IsEventError]]## | '''' | Проверка, была ли ошибка события | | | ''bool ''\\ ##[[osa:ref:allservices:OS_IsInCriticalSection|OS_IsInCriticalSection]]## | '''' | Возвращает 1, если одна из задач находится в критической секции. | | | **Прерывания** |||| | ##[[osa:ref:allservices:OS_EnterInt|OS_EnterInt]]## | '''' | Должна выполняться при входе в прерывание (сохраняет FSR) | {{osa:ref:attr_call_int.png|Разрешен вызов только в прерывании}} | | ##[[osa:ref:allservices:OS_LeaveInt|OS_LeaveInt]]## | '''' | Должна выполняться перед выходом из прерывания (восстанавливает FSR) | {{osa:ref:attr_call_int.png|Разрешен вызов только в прерывании}} | | ''char ''\\ ##[[osa:ref:allservices:OS_DI|OS_DI]]## | '''' | Запретить прерывания. Текущие значения GIEx сохраняются | {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | | ##[[osa:ref:allservices:OS_EI|OS_EI]]## | '''' | Разрешить прерывания | {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | | ##[[osa:ref:allservices:OS_RI|OS_RI]]## | ''(char)'' | Восстановить сохраненные в ##[[osa:ref:allservices:OS_DI|OS_DI]]##() значения GIEx. | {{osa:ref:attr_call_not_int.png|Нельзя вызывать из прерывания}} | | ##[[osa:ref:allservices:OS_EnterCriticalSection|OS_EnterCriticalSection]]## | '''' | Вход в критическую секцию | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}} | | ##[[osa:ref:allservices:OS_LeaveCriticalSection|OS_LeaveCriticalSection]]## | '''' | Выход из критической секции | {{osa:ref:attr_call_task.png|Разрешен вызов только в контексте задачи}} | ~~UP~~