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