Продолжаем рассматривать службы ОСРВ, предоставляющие дополнительную информацию о задачах и операциях с ними.

К дополнительным вызовам API, связанным с задачами, относятся вызовы получения ID задачи, проверки объема стека, сброса задачи, получения информации о задаче и определение количества задач в системе. Nucleus RTOS и Nucleus SE обеспечивают 4 основных вызова API для этих операций, о которых я расскажу в этой статье.

Получение ID текущей задачи


Этот служебный вызов возвращает ID вызываемой задачи. Для Nucleus RTOS это указатель на блок управления текущей задачи. Для Nucleus SE – индекс (0-15) текущей задачи.

Вызов текущей задачи в Nucleus RTOS
Прототип служебного вызова:
NU_TASK *NU_Current_Task_Pointer(VOID);

Параметры:
Отсутствуют.

Возвращаемое значение:
Указатель на блок управления текущей задачи;
NU_NULL – нет выполняемой задачи.

Вызов текущей задачи в Nucleus SE
Этот API-вызов поддерживает основной функционал API Nucleus RTOS.

Прототип служебного вызова:
NUSE_TASK NUSE_Task_Current(void);

Параметры:
Отсутствуют.

Возвращаемое значение:
Индекс текущей (вызываемой) задачи.

Выполнение текущей задачи в Nucleus SE
Реализация вызова API в данном случае довольно проста: возвращается значение глобальной переменной NUSE_Task_Active.

Проверка доступного объёма стека


Этот служебный вызов возвращает доступный объём стека (в байтах) для текущей задачи. Это целесообразно только для планировщиков, где каждая задача имеет свой собственный стек; т.е. не подойдет для планировщика Run To Completion (RTC) в Nucleus SE.

Вызов информации об объеме стека в Nucleus RTOS
Прототип служебного вызова:
UNSIGNED NU_Task_Check_Stack(VOID);

Параметры:
Отсутствуют.

Возвращаемое значение:
Размер доступного объема стека для текущей задачи в байтах.

Вызов информации о размере стека в Nucleus SE
Этот вызов API поддерживает основной функционал API Nucleus RTOS. Однако в Nucleus SE требуется формальный (dummy) параметр, чтобы упростить получение значения указателя на используемый стек.

Прототип служебного вызова:
U16 NUSE_Task_Check_Stack(U8 dummy);

Параметры:
dummy – любое значение, поскольку фактически оно не используется.

Возвращаемое значение:
Размер доступного объёма стека для текущей задачи в байтах.

Реализация
Для такого вызова код должен быть переносимым:



Если используется планировщик RTC, возвращаемое значение 0, поскольку невозможно (при использовании переносимого кода) определить доступное для задачи пространство стека.

В других случаях значение указателя стека определяется нахождением адреса параметра dummy, который будет находиться почти в начале стека. Строго говоря, такой метод зависит от средств разработки/компилятора, но всегда будет рабочим. Возвращаемое значение – это разница между этим значением и первоначальным значением пространства стека, переведенная в байты.

Сброс задачи


Вызов API, в данном случае, возвращает задачу в ее первоначальное неиспользуемое состояние. Такая функция API отличается от обычных функций сброса API для других объектов ядра, хотя бы потому что это именно сброс, а не простое установление задачи в ее начальное состояние (для Nucleus SE это либо NUSE_READY, либо запись NUSE_Task_Initial_State[] (см. Структуры данных в следующей статье)); задача переводится в состояние приостановки (NUSE_PURE_SUSPEND) и должна быть возобновлена, для того чтобы снова быть поставленной на планирование. Такая логика похожа на функционал соответствующего вызова API в Nucleus RTOS.

Вызов сброса задачи в Nucleus RTOS
Прототип служебного вызова:
STATUS NU_Reset_Task(NU_TASK *task, UNSIGNED argc, VOID *argv);

Параметры:
task – указатель на блок управления задачей;
argc – элемент данных, который может использоваться для передачи информации в задачу;
argv – указатель, который может использоваться для передачи информации в задачу.

Возвращаемое значение:
NU_SUCCESS – вызов успешно выполнен;
NU_INVALID_TASK – некорректный указатель на задачу;
NU_NOT_TERMINATED – описываемая задача не находится в состоянии полной приостановки (terminated) или завершения (finished); только задачи в состоянии приостановки или завершения могут быть сброшены.

Вызов сброса задачи в Nucleus SE
Этот API-вызов поддерживает основной функционал API Nucleus RTOS.

Прототип служебного вызова:
STATUS NUSE_Task_Reset(NUSE_TASK task);

Параметры:
task – индекс (ID) задачи, которую необходимо сбросить.

Возвращаемое значение:
NUSE_SUCCESS – вызов успешно выполнен;
NUSE_INVALID_TASK – некорректный индекс задачи.

Реализация сброса задачи в Nucleus SE
Основное назначение API функции NUSE_Task_Reset() после проверки параметра – повторная инициализация всех структур данных задачи:



Если задача заблокирована при вызове API для ожидания доступа к объекту ядра, первое, что необходимо сделать, настроить счетчик заблокированных задач, соответствующих объекту. Это осуществляется оператором switch.

Затем структуры данных задачи инициализируются (в основном, нулями, кроме ее контекстного блока) с помощью вызова функции инициализации NUSE_Init_Task(). Её выполнение более детально будет рассмотрено в следующей статье с описанием инициализации системы. Наконец, статус задачи устанавливается в NUSE_PURE_SUSPEND.

Получение информации о задаче


Этот служебный вызов позволяет получить частичную информацию о задаче. Реализация Nucleus SE отличается от Nucleus PLUS, в которой возвращается меньше информации, поскольку присваивание объектам имен, вытеснение менее приоритетной задачи и квант времени не поддерживаются, а приоритет не возвращается, будучи избыточной информацией.

Вызов получения информации о задаче в Nucleus RTOS
Прототип служебного вызова:
STATUS NU_Task_Information(NU_TASK *task, CHAR *name, DATA_ELEMENT *task_status, UNSIGNED *scheduled_count, OPTION *priority, OPTION *preempt, UNSIGNED *time_slice, VOID **stack_base, UNSIGNED *stack_size, UNSIGNED *minimum_stack;

Параметры:
task – указатель на задачу, информация о которой запрашивается;
name – указатель на 8-символьную строку для имени задачи; включает область для нулевых символов;
task_status – указатель на переменную, которая получает текущее значение статуса задачи;
scheduled_count – указатель на переменную, которая получает значение счетчика, сколько раз задача была добавлена в планировщик;
priority – указатель на переменную для получения приоритета задачи;
preempt – указатель на переменную для опций вытеснения менее приоритетной задачи; NU_PREEMPT показывает, что задача может быть вытеснена, и NU_NO_PREEMPT показывает, что задача не может быть вытеснена;
time_slice – указатель на переменную для получения значения кванта времени задачи; значение 0 показывает, что квантование времени для данной задачи невозможно;
stack_base – указатель на переменную для получения адреса стека задачи;
stack_size – указатель на переменную для получения размера стека задачи;
minimum_stack – указатель на переменную для получения минимального количества байт, остававшихся в стеке.

Возвращаемое значение:
NU_SUCCESS – вызов успешно выполнен;
NU_INVALID_TASK – некорректный указатель на задачу.

Вызов получения информации о задаче в Nucleus SE
Этот вызов поддерживает основной функционал API Nucleus PLUS.

Прототип служебного вызова:
STATUS NUSE_Task_Information(NUSE_TASK task, U8 *task_status, U16 *scheduled_count, ADDR *stack_base, U16 *stack_size);

Параметры:
task – индекс задачи, о которой запрашивается информация;
task_status – указатель на переменную U8, которая получает текущее значение статуса задачи (если состояние ожидания задачи недоступно, ничего не возвращается);
scheduled_count – указатель на переменную U16, которая получает значение счетчика количества задач, добавляемых в планировщик (если счетчик планируемых задач отключен, то ничего не возвращается);
stack_base – указатель на переменную ADDR, которая получает адрес стека задачи (если используется планировщик RTC, ничего не возвращается);
stack_size – указатель на переменную U16, которая получает размер стека задачи (если используется планировщик RTC, ничего не возвращается).

Возвращаемое значение:
NUSE_SUCCESS – вызов успешно выполнен;
NUSE_INVALID_TASK – некорректный индекс задачи;
NUSE_INVALID_POINTER – параметры указателей (один или более) некорректны.

Реализация получения информации о задаче в Nucleus SE
Реализация этого API-вызова довольно проста:



Функция возвращает статус задачи, учитывая различные возможности конфигураций.

Получение количества задач


Этот служебный вызов возвращает информацию о количестве задач, сконфигурированных в приложении. В то время как в Nucleus RTOS это количество может меняться, и возвращаемое значение будет представлять текущее количество задач на данный момент, в Nucleus SE возвращаемое значение устанавливается при сборке и не больше не меняется.

Вызов получения количества задач в Nucleus RTOS
Прототип служебного вызова:
UNSIGNED NU_Established_Tasks(VOID);

Параметры:
Отсутствуют

Возвращаемое значение:
Число установленных (созданных и не удаленных) задач в приложении.

Вызов получения количества задач в Nucleus SE
Этот вызов API поддерживает основной функционал API Nucleus PLUS.

Прототип служебного вызова:
U8 NUSE_Task_Count(void);

Параметры:
Отсутствуют

Возвращаемое значение:
Количество сконфигурированных задач в приложении.

Реализация
Реализация этого вызова API довольно проста: возвращается значение директивы #define NUSE_TASK_NUMBER.

В следующей статье будут рассмотрены структуры данных в Nucleus SE, связанные с задачами и некоторыми стандартными вызовами API, не поддерживаемыми Nucleus SE.

Об авторе: Колин Уоллс уже более тридцати лет работает в сфере электронной промышленности, значительную часть времени уделяя встроенному ПО. Сейчас он — инженер в области встроенного ПО в Mentor Embedded (подразделение Mentor Graphics). Колин Уоллс часто выступает на конференциях и семинарах, автор многочисленных технических статей и двух книг по встроенному ПО. Живет в Великобритании. Профессиональный блог Колина, e-mail: colin_walls@mentor.com.

О переводе: этот цикл статей показался интересным тем, что, несмотря на местами устаревшие описываемые подходы, автор очень понятным языком знакомит малоподготовленного читателя с особенностями ОС реального времени. Я сам принадлежу к коллективу создателей российской ОСРВ, которую мы предполагаем сделать бесплатной, и надеюсь, что цикл будет полезен начинающим разработчикам.

Комментарии (0)