Программирование ARM ESP-IDF FreeRTOS Task API Fri, April 19 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

ESP-IDF FreeRTOS Task API Печать
Добавил(а) microsin   

В этой статье содержится документация по типам, функциям и макросам задач FreeRTOS. Они автоматически генерируются из заголовочных файлов FreeRTOS. Здесь приведен перевод источника [1], где к сожалению есть досадные опечатки (которые переводчик постарался исправить). Более правильную документацию по функциям советую смотреть в исходном коде порта ESP-IDF FreeRTOS.

Примечание: ESP-IDF FreeRTOS основывается на Vanilla FreeRTOS v10.4.3. Для дополнительной информации поддержки симметричной много процессорной обработки см. [2]. По дополнительным функциям, добавленных в ESP-IDF FreeRTOS, см. [3]. Расшифровку незнакомых терминов см. в разделе Словарик, в конце статьи. Также см. цикл статей, посвященных FreeRTOS [12].

[Конфигурация]

Традиционно ядро Vanilla FreeRTOS конфигурируются для портов и приложений путем различных макросов #define config... в заголовочном файле FreeRTOSConfig.h. С помощью этих макросов конфигурируется поведение планировщика ядра и различные функции ядра, которые можно разрешить или запретить. Однако в среде ESP-IDF файл FreeRTOSConfig.h считается приватным, и он не рассчитан на прямую модификацию пользователем. Любая конфигурация FreeRTOS предоставлена пользователю через интерфейс menuconfig.

ESP-IDF FreeRTOS можно конфигурировать в путем запуска команды меню конфигурации проекта (idf.py menuconfig), после чего надо зайти в раздел настроек Component Config / FreeRTOS (см. скриншот на рис. 1). Далее будет показано назначение некоторых опций конфигурации ESP-IDF FreeRTOS, полный список опций см. в [5].

ESP IDF run idf.py menuconfig FreeRTOS fig01

Рис. 1. Экран системы конфигурирования проекта на основе запуска команды idf.py menuconfig.

Удобная фича menuconfig: существует поиск нужных опций с помощью функции [/] Jump to symbol. Нажмите клавишу /, и станет доступен быстрый поиск по опциям.

В процессе установки ESP-IDF [4] будут также установлены ярлыки, которые запустят рабочую среду для выполнения скриптов Python. На этих скриптах основан инструментарий компиляции и автоматической генерации (конфигурирования) дополнительных файлов для проектов ESP32. Эти ярлыки настраивают переменные окружения, необходимые для компиляции.

ESP IDF setup fig09

Один ярлык запускает командную строку cmd.exe, другой ярлык запускает командную строку PowerShell. Каким из них пользоваться - не имеет значения, все зависит от Ваших предпочтений. Все основные действия среда ESP-IDF производит путем запуска скрипта idf.py вместе с необходимой командой, например menuconfig или build. Этим собственно и объясняется невыносимая тормознутость выполнения основных операций в среде ESP-IDF.

Кроме того, эти команды можно запускать автономно, без запуска среды разработки ESP-IDF. Вот так, например, можно запустить меню конфигурирования проекта с помощью idf.py:

1. Запустите командную строку с помощью ярлычка (например, ярлычка ESP-IDF 4.4 CMD).

2. С помощью команды cd выполните навигацию в корневой каталог проекта (каталог, где находятся файлы .project и Makefile).

3. Выполните следующую команду:

python.exe c:\Espressif\frameworks\esp-idf-v4.4\tools\idf.py menuconfig

Здесь необходимо указать полный путь места нахождения на диске файла скрипта idf.py. Он находится в каталоге установки среды ESP-IDF, папка tools.

CONFIG_FREERTOS_UNICORE запустит ESP-IDF FreeRTOS только на ядре CPU0. Обратите внимание, что это не эквивалентно запуску Vanilla FreeRTOS. Кроме того, эта опция может повлиять на поведение компонентов, которые не относятся к FreeRTOS. Для дополнительной информации по эффектам запуска ESP-IDF FreeRTOS на одном ядре см. раздел "ESP-IDF FreeRTOS Single Core" в статье [6]. Альтернативно пользователи также могут поискать другие места появления опции CONFIG_FREERTOS_UNICORE в компонентах ESP-IDF.

CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION приведет к остановке (halt) в функциях ESP-IDF FreeRTOS, которые не были полностью протестированы в контексте SMP.

CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER применит для всех task-функций специальную обертку (wrapper). В случае неожиданного возврата из task-функции (например, не по причине вызова vTaskDelete()) управление будет возвращено в функцию обертки. Тогда функция обертки выведет в лог ошибку и произведет полное прекращение работы приложения (abort). Пример вывода в лог для такой ситуации:

E (25) FreeRTOS: FreeRTOS task should not return. Aborting now!
abort() was called at PC 0x40085c53 on core 0

[Приложения ESP-IDF FreeRTOS]

В отличие от Unlike Vanilla FreeRTOS, пользователю не нужно вызывать запуск планировщика через vTaskStartScheduler(). Вместо этого ESP-IDF FreeRTOS запускает планировщик автоматически. Точка входа в приложении для пользователя определена в виде готовой функции void app_main(void), где может находиться традиционный бесконечный цикл.

● Обычно подразумевается, что пользователи должны запускать свои задачи приложения из тела функции app_main.
● Функции app_main разрешено выполнить возврат в любом месте (например до завершения приложения).
● Функция app_main вызывается из задачи main.

Задача main это одна из нескольких задач, которые автоматически запускает ESP-IDF в процессе старта (startup). Эти задачи перечислены в таблице 1.

Таблица 1. Список задач, создаваемых во время startup.

Имя задачи Привязка Приоритет Описание
Main Task (main) CPU0 1 Задача, которая просто вызывает функцию app_main. Эта задача удалит саму себя, если произойдет выход из app_main.
Idle Task (IDLEx) CPU0 и CPU1 0 Задачи ожидания, создаваемые и привязываемые к каждому CPUx.
IPC Task (ipcx) 24 Задачи IPC создаются и привязываются к каждому CPUx. Они используются для реализации функции IPC [13].

[Task API]

Заголовочный файл:

components/freertos/FreeRTOS-Kernel/include/freertos/task.h

BaseType_t xTaskCreatePinnedToCore (TaskFunction_t pvTaskCode,
                                    const char *constpcName,
                                    const uint32_t usStackDepth,
                                    void *constpvParameters,
                                    UBaseType_t uxPriority,
                                    TaskHandle_t *constpvCreatedTask,
                                    const BaseType_t xCoreID);

Создает новую задачу task с указанной привязкой к определенному ядру (affinity). Действие этой функции подобно xTaskCreate, однако здесь можно заказать привязку к нужному ядру (task affinity) в многоядерной системе (SMP system).

Возвращаемое значение pdPASS, если задача была успешно создана и добавлена в список готовности (ready list), иначе будет возвращен код ошибки, определенный в файле projdefs.h

Параметры

pvTaskCode: указатель на функцию точки входа (task entry). Задачи должны быть реализованы таким образом, чтобы никогда не делать возврат из своей функции (т. е. работать в бесконечном цикле), либо они должны завершаться с помощью функции vTaskDelete.

pcName: описательное имя для задачи. Параметр в основном предназначен для упрощения отладки, и функционально больше ни для чего не нужен. Максимальная длина строки для имени определена опцией configMAX_TASK_NAME_LEN, по умолчанию 16.

usStackDepth: размер стека задачи, указанный в байтах. Обратите внимание, что это отличается от vanilla FreeRTOS.

pvParameters: указатель, который будет использоваться как параметр для созданной задачи.

uxPriority: приоритет, с которым задача должна работать. Системы, в которых имеется поддержка MPU, могут опционально создавать задачи в привилигированном режиме (system mode) путем установки бита portPRIVILEGE_BIT в параметре приоритета. Например, чтобы создать привилегированную задачу с приоритетом 2 , параметр uxPriority должен быть установлен в значение (2 | portPRIVILEGE_BIT).

pvCreatedTask: используется для передачи обратно дескриптора (handle), по которому можно будет впоследствии ссылаться на эту задачу.

xCoreID: если значение этого параметра tskNO_AFFINITY, то созданная задача не привязывается ни к какому CPU, и планировщик может запустить её на любом доступном ядре. Значения 0 или 1 показывают номер индекса CPU, к которому задача должна быть пристыкована. Если указать значение, превышающее (portNUM_PROCESSORS-1), то это приведет к ошибке вызова функции xTaskCreatePinnedToCore.

static BaseType_t xTaskCreate (TaskFunction_t pvTaskCode,
                               const char *constpcName,
                               const uint32_t usStackDepth,
                               void *constpvParameters,
                               UBaseType_t uxPriority,
                               TaskHandle_t *constpxCreatedTask);

Создает новую задачу, и добавляет её в список задач, готовых к работе.

Внутри реализации FreeRTOS задачи используют 2 блока памяти. Первый блок используется для хранения структур данных задачи (TCB). Второй блок используется задачей для своего стека. Если задача создана с использованием xTaskCreate(), то оба этих блока памяти автоматически выделяются динамическим способом (из кучи) в теле функции xTaskCreate() (см. [14]). Если задача создается с использованием xTaskCreateStatic(), то разработчик приложения должен сам предоставить необходимую память. Таким образом, xTaskCreateStatic() позволяет создать задачу без использования динамического выделения памяти.

xTaskCreate() может быть использована только для создания задачи, которая получает неограниченный доступ ко всей карте памяти MCU. Системы, которые снабжены поддержкой MPU, могут альтернативно создавать задачу, на которую наложены ограничения доступа со стороны MPU, для чего используется xTaskCreateRestricted().

Возвращаемое значение pdPASS, если задача была успешно создана и добавлена в список ready, иначе код ошибки, определенный в projdefs.h.

Примечание: если программа использует локальные переменные потока (такие, которые определены с ключевым словом __thread), то хранилище для них выделяется из стека задачи.

Параметры

pvTaskCode: указатель на функцию точки входа (task entry). Задачи должны быть реализованы таким образом, чтобы никогда не делать возврат из своей функции (т. е. работать в бесконечном цикле), либо они должны завершаться с помощью функции vTaskDelete.

pcName: описательное имя для задачи. Параметр в основном предназначен для упрощения отладки, и функционально больше ни для чего не нужен. Максимальная длина строки для имени определена опцией configMAX_TASK_NAME_LEN, по умолчанию 16.

usStackDepth: размер стека задачи, указанный в байтах. Обратите внимание, что это отличается от vanilla FreeRTOS.

pvParameters: указатель, который будет использоваться как параметр для созданной задачи.

uxPriority: приоритет, с которым задача должна работать. Системы, в которых имеется поддержка MPU, могут опционально создавать задачи в привилигированном режиме (system mode) путем установки бита portPRIVILEGE_BIT в параметре приоритета. Например, чтобы создать привилегированную задачу с приоритетом 2 , параметр uxPriority должен быть установлен в значение (2 | portPRIVILEGE_BIT).

pvCreatedTask: используется для передачи обратно дескриптора (handle), по которому можно будет впоследствии ссылаться на эту задачу.

Пример использования:

// Создаваемая задача.
void vTaskCode (void * pvParameters)
{
   for( ;; )
   {
      // Здесь вставляется код задачи.
   }
}
 
// Функция, которая создает задачу.
void vOtherFunction (void)
{
   static uint8_t ucParameterToPass;
   TaskHandle_t xHandle = NULL;
 
   // Создается задача и сохраняется её дескриптор. Обратите внимание,
   // что параметр ucParameterToPass должен существовать в течение
   // всего времени жизни задачи, так что в этом случае он декларирован
   // как static. Если это была только лишь автоматическая переменная
   // из стека, то она возможно не будет дальше существовать, или
   // как минимум может быть повреждена в тот момент, когда задача
   // попытается обратиться к ней.
   xTaskCreate(vTaskCode,
               "NAME",
               STACK_SIZE,
               &ucParameterToPass,
               tskIDLE_PRIORITY,
               &xHandle);
   configASSERT(xHandle);
 
   // Дескриптор используется для удаления задачи.
   if(xHandle != NULL)
   {
      vTaskDelete( xHandle );
   }
}

TaskHandle_t xTaskCreateStaticPinnedToCore (TaskFunction_t pvTaskCode,
                                            const char *constpcName,
                                            const uint32_t ulStackDepth,
                                            void *const pvParameters,
                                            UBaseType_t uxPriority,
                                            StackType_t *const pxStackBuffer,
                                            StaticTask_t *const pxTaskBuffer,
                                            const BaseType_t xCoreID);

Создает новую задачу task с указанной привязкой к определенному ядру (affinity). Действие этой функции подобно xTaskCreateStatic, однако здесь можно заказать привязку к нужному ядру (task affinity) в многоядерной системе (SMP system).

Будет возвращен дескриптор задачи, на который можно будет впоследствии ссылаться, если не было передано NULL ни для pxStackBuffer, ни для pxTaskBuffer. Это означает, что задача была успешно создана и добавлена в список готовности (ready list). Если же в в любом из параметров pxStackBuffer или pxTaskBuffer был передан NULL, то задача не будет создана, и будет возвращен код ошибки errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY.

Параметры

pvTaskCode: указатель на функцию точки входа (task entry). Задачи должны быть реализованы таким образом, чтобы никогда не делать возврат из своей функции (т. е. работать в бесконечном цикле), либо они должны завершаться с помощью функции vTaskDelete.

pcName: описательное имя для задачи. Параметр в основном предназначен для упрощения отладки, и функционально больше ни для чего не нужен. Максимальная длина строки для имени определена опцией configMAX_TASK_NAME_LEN в файле FreeRTOSConfig.h (по умолчанию 16).

usStackDepth: размер стека задачи, указанный в байтах. Обратите внимание, что это отличается от vanilla FreeRTOS.

pvParameters: указатель, который будет использоваться как параметр для созданной задачи.

uxPriority: приоритет, с которым задача должна работать.

pxStackBuffer: должен быть массив типа StackType_t размером как минимум в ulStackDepth индексов. Этот массив будет использован для стека задачи, память для стека не будет выделяться динамически.

pxTaskBuffer: указатель на переменную типа StaticTask_t, которая будет использоваться для хранения структур данных задачи, память для этой структуры не будет выделяться динамически.

xCoreID: если значение этого параметра tskNO_AFFINITY, то созданная задача не привязывается ни к какому CPU, и планировщик может запустить её на любом доступном ядре. Значения 0 или 1 показывают номер индекса CPU, к которому задача должна быть пристыкована. Если указать значение, превышающее (portNUM_PROCESSORS-1), то это приведет к ошибке вызова функции xTaskCreatePinnedToCore.

Пример использования:

// Размер буфера, который задача использует в качестве своего стека.
// Замечание: количество указывается в байтах, а не в количестве слов,
// как это можно найти в vanilla FreeRTOS.
#define STACK_SIZE 200
 
// Структура, которая хранит TCB создаваемой задачи.
StaticTask_t xTaskBuffer;
 
// Буфер, который создаваемая задача будет использовать для своего стека.
// Обратите внимание, что массив состоит из переменных типа StackType_t.
// Размер StackType_t зависит от порта FreeRTOS.
StackType_t xStack[ STACK_SIZE ];
 
// Функция, которая реализует создаваемую задачу.
void vTaskCode (void *pvParameters)
{
   // Ожидается передаваемое значение параметра, равное 1, поскольку
   // значение 1 было передано в параметре pvParameters при вызове
   // функции xTaskCreateStatic().
   configASSERT( ( uint32_t ) pvParameters == 1UL );
 
   for( ;; )
   {
      // Здесь находится код алгоритма задачи.
   }
}
 
// Функция, которая создает задачу.
void vOtherFunction (void)
{
   TaskHandle_t xHandle = NULL;
 
   // Создание задачи без динамического выделения памяти.
   xHandle = xTaskCreateStaticPinnedToCore(
                 vTaskCode,       // Функция, где реализована задача.
                 "NAME",          // Описательное имя задачи.
                 STACK_SIZE,      // Резмер стека задачи в байтах, не в словах.
                 (void*)1,        // Параметр, переданный в задачу.
                 tskIDLE_PRIORITY,// Приоритет создаваемой задачи.
                 xStack,          // Массив, используемый в качестве стека задачи.
                 &xTaskBuffer,    // Переменная, где будет храниться TCB задачи.
                 1);              // Используемое ядро для задачи.
 
   // pxStackBuffer и pxTaskBuffer не NULL, так что задача будет создана,
   // и в переменную xHandle будет сохранен дескриптор задачи. Этот дескриптор
   // используется для приостановки задачи.
   vTaskSuspend( xHandle );
}

static TaskHandle_t xTaskCreateStatic (TaskFunction_t pvTaskCode,
                                       const char *constpcName,
                                       const uint32_t ulStackDepth,
                                       void *constpvParameters,
                                       UBaseType_t uxPriority,
                                       StackType_t *constpuxStackBuffer,
                                       StaticTask_t *constpxTaskBuffer);

Создает новую задачу, и добавляет её в список задач, готовых к работе.

Внутри реализации FreeRTOS задачи используют 2 блока памяти. Первый блок используется для хранения структур данных задачи (TCB). Второй блок используется задачей для своего стека. Если задача создана с использованием xTaskCreate(), то оба этих блока памяти автоматически выделяются динамическим способом (из кучи) в теле функции xTaskCreate() (см. [14]). Если задача создается с использованием xTaskCreateStatic(), то разработчик приложения должен сам предоставить необходимую память. Таким образом, xTaskCreateStatic() позволяет создать задачу без использования динамического выделения памяти.

Будет возвращен дескриптор задачи, на который можно будет впоследствии ссылаться, если не было передано NULL ни для pxStackBuffer, ни для pxTaskBuffer. Это означает, что задача была успешно создана и добавлена в список готовности (ready list). Если же в в любом из параметров pxStackBuffer или pxTaskBuffer был передан NULL, то задача не будет создана, и будет возвращен код ошибки errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY.

Параметры

pvTaskCode: указатель на функцию точки входа (task entry). Задачи должны быть реализованы таким образом, чтобы никогда не делать возврат из своей функции (т. е. работать в бесконечном цикле), либо они должны завершаться с помощью функции vTaskDelete.

pcName: описательное имя для задачи. Параметр в основном предназначен для упрощения отладки, и функционально больше ни для чего не нужен. Максимальная длина строки для имени определена опцией configMAX_TASK_NAME_LEN в файле FreeRTOSConfig.h (по умолчанию 16).

usStackDepth: размер стека задачи, указанный в байтах. Обратите внимание, что это отличается от vanilla FreeRTOS.

pvParameters: указатель, который будет использоваться как параметр для созданной задачи.

uxPriority: приоритет, с которым задача должна работать.

pxStackBuffer: должен быть массив типа StackType_t размером как минимум в ulStackDepth индексов. Этот массив будет использован для стека задачи, память для стека не будет выделяться динамически.

pxTaskBuffer: указатель на переменную типа StaticTask_t, которая будет использоваться для хранения структур данных задачи, память для этой структуры не будет выделяться динамически.

Пример использования:

// Размер буфера, который задача будет использовать для своего стека.
// Замечание: этот размер указан в байтах, а не в количестве слов,
// как это можно увидеть в vanilla FreeRTOS.
#define STACK_SIZE 200
 
// Структура, которая будет хранить TCB создаваемой задачи.
StaticTask_t xTaskBuffer;
 
// Буфер, который задача будет использовать в качестве своего стека.
// Обратите внимание, что массив состоит из переменных типа StackType_t.
// Реальный размер StackType_t зависит от порта FreeRTOS.
StackType_t xStack[ STACK_SIZE ];
 
// Функция, которая реализует создаваемую задачу.
void vTaskCode (void * pvParameters)
{
   // Подразумевается, что значение параметра 1, поскольку 1 было
   // передано в pvParameters при вызове xTaskCreateStatic().
   configASSERT((uint32_t)pvParameters == 1UL);
 
   for( ;; )
   {
      // Сюда вставляется код задачи.
   }
}
 
// Функция, которая создает задачу.
void vOtherFunction (void)
{
   TaskHandle_t xHandle = NULL;
 
   // Задача будет создана без динамического выделения памяти.
   xHandle = xTaskCreateStatic(
                 vTaskCode,       // Функция, которая реализует задачу.
                 "NAME",          // Текстовое имя задачи.
                 STACK_SIZE,      // Размер стека в байтах, а не в словах.
                 (void*)1,        // Параметр, переданный в задачу.
                 tskIDLE_PRIORITY,// Приоритет, с которым задача создается.
                 xStack,          // Массив для использования в качестве стека.
                 &xTaskBuffer );  // Переменная для хранения структуры данных задачи.
 
   // puxStackBuffer и pxTaskBuffer не равны NULL, поэтому задача будет
   // создана, и в переменную xHandle будет записан дескриптор задачи.
   // Этот дескриптор здесь используется для приостановки задачи.
   vTaskSuspend(xHandle);
}

void vTaskAllocateMPURegions(TaskHandle_t xTask,
                             const MemoryRegion_t * const pxRegions) PRIVILEGED_FUNCTION;

Назначаются регионы памяти для ограниченной задачи, когда задача была создана вызовом xTaskCreateRestricted(). Эти регионы можно переназначить с использованием vTaskAllocateMPURegions(). Параметр const pxRegions определяет регионы памяти задачи и связанные с ними разрешения доступа, выделенные для задачи.

Параметры

xTask: дескриптор обновляемой задачи.

pxRegions: указатель на структуру MemoryRegion_t, которая содержит новые определения региона памяти.

Пример использования:

// Определяется массив структур MemoryRegion_t, который конфигурирует
// регион MPU, позволяющий осуществлять доступ на чтение и запись для
// 1024 байт от начала массива ucOneKByte. Другие два из максимально
// трех возможных региона не используются, и установлены в 0.
static const MemoryRegion_t xAltRegions[portNUM_CONFIGURABLE_REGIONS] =
{
   // базовый адрес    длина       параметры доступа
   { ucOneKByte,       1024,       portMPU_REGION_READ_WRITE },
   { 0,                0,          0 },
   { 0,                0,          0 }
};
 
void vATask( void *pvParameters )
{
   // Эта задача была создана так, что у неё есть доступ к определенным
   // регионам памяти, как это задано конфигурацией MPU. В некотором месте
   // программы было принято решение, что эти регионы MPU заменяются на
   // другие, которые определены выше в структуре xAltRegions. Для этой
   // цели используется вызов vTaskAllocateMPURegions(). В качестве
   // первого параметра указан NULL, этим показываетс, что будут
   // модифицированы регионы MPU задачи, из которой был сделан вызов
   // vTaskAllocateMPURegions.
   vTaskAllocateMPURegions(NULL, xAltRegions);
 
   // Теперь задача может продолжить свое функционирование, но с этого
   // момента может иметь доступ только к своему стеку и к массиву
   // ucOneKByte (за исключением любых других, определенных статически
   // или общих регионов, которые были определены где-нибудь еще).
}

BaseType_t xTaskCreateRestricted (const TaskParameters_t * const pxTaskDefinition,
                                  TaskHandle_t * pxCreatedTask) PRIVILEGED_FUNCTION;

Эта функция доступна только когда опция configSUPPORT_DYNAMIC_ALLOCATION определена как 1. Функция xTaskCreateRestricted() должна использоваться только в системах, где есть реализация MPU.

Создает новую задачу, и добавляет её в список задач, готовых к работе. Параметры функции определяют регионы памяти и связанные с ним разрешения доступа для задачи.

См. описание xTaskCreateRestrictedStatic() для версии этой функции, которая не использует динамическое выделение памяти.

Возвратит pdPASS, если задача была успешно создана и добавлена в список ready, иначе будет возвращен код ошибки, определенный в projdefs.h.

Параметры

pxTaskDefinition: указатель на структуру, которая содержит в своих полях нормальные значения параметров, которые передаются в функцию xTaskCreate() (см. документацию API на функцию xTaskCreate), плюс опционально буфер стека и и определения регионов памяти.

pxCreatedTask: используется, чтобы передать обратно дескриптор созданной задачи, через который на задачу можно будет ссылаться впоследствии.

Пример использования:

// Создание структуры TaskParameters_t, определяющей задачу.
static const TaskParameters_t xCheckTaskParameters =
{
   vATask,     // pvTaskCode - функция, где находится код задачи.
   "ATask",    // pcName - просто описательное имя задачи.
   100,        // usStackDepth - размер стека, определенный в словах.
   NULL,       // pvParameters - передается в функцию задачи в качестве параметров.
   (1UL | portPRIVILEGE_BIT), // uxPriority - приоритет задачи. Здесь
               // установлен бит portPRIVILEGE_BIT, он означает, что задача
               // должна работать в привилегированном (системном) режиме.
   cStackBuffer,// puxStackBuffer - буфер для использования в качестве стека задачи.
   // xRegions - выделяется до трех отдельных регионов памяти для доступа
   // со стороны задачи, с подходящими разрешениями для доступа. Разные
   // процессоры имеют разные требования к выравниванию регионов памяти,
   // см. документацию на FreeRTOS для получения полной информации.
   {
      // Базовый адрес               Длина   Параметры доступа
      {cReadWriteArray,              32,     portMPU_REGION_READ_WRITE},
      {cReadOnlyArray,               32,     portMPU_REGION_READ_ONLY},
      {cPrivilegedOnlyAccessArray,   128,    portMPU_REGION_PRIVILEGED_READ_WRITE}
   }
};
 
int main( void )
{
   TaskHandle_t xHandle;
 
   // Создается задача с помощью структуры, определенной выше. При вызове
   // запрашивается дескриптор задачи, который будет сохранен в переменную
   // xHandle (второй параметр != NULL), однако в этом случае это просто
   // для демонстрации, и дескриптор нигде не используется.
   xTaskCreateRestricted(&xRegTest1Parameters, &xHandle);
 
   // Запуск планировщика.
   vTaskStartScheduler();
 
   // Сюда мы попадем только в том случае, если не было достаточно памяти
   // для создания задачи задачи ожидания (idle task) и/или задачи ATask.
   for( ;; );
}

void vTaskDelete (TaskHandle_t xTaskToDelete);

Чтобы эта функция была доступна, опция INCLUDE_vTaskDelete должна быть определена как 1.

Удаляет задачу из системы RTOS. Задача будет удалена из всех списков ready, blocked, suspended и event.

Примечание: idle task отвечает за освобождение памяти системы, связанной с удаляемыми задачами. Поэтому важно, чтобы другие задачи оставляли некоторое процессорное время для idle task, если в приложении используются вызовы vTaskDelete(). Память, выделенная кодом задачи, не освобождается автоматически, и должна быть освобождена перед удалением задачи.

См. демонстрационное приложение в файле death.c, где приведен код примера, использующий vTaskDelete().

Параметры

xTaskToDelete: дескриптор удаляемой задачи. В этом параметре передается NULL, если удаляется задача, из которой была вызвана функция vTaskDelete.

Пример использования:

void vOtherFunction (void)
{
   TaskHandle_t xHandle;
 
   // Создается задача, сохраняется её дескриптор.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);
 
   // Сохраненный дескриптор используется для ссылки на удаляемую задачу.
   vTaskDelete(xHandle);
}

Важное замечание: некоторые порты FreeRTOS (например порт ESP-IDF для чипов ESP32) требуют, чтобы вызов vTaskDelete(NULL) обязательно стоял в конце тела функции потока. Если это условие не выполнить, то состояние задачи никогда не поменяется на eDeleted, и всегда будет eRunning.

void vTaskDelay (const TickType_t xTicksToDelay);

Задерживает выполнение задачи на указанное количество тиков. Реальное время, в течение которого задача остается заблокированной, зависит от частоты тиков. Для вычисления значения параметра xTicksToDelay может использоваться константа portTICK_PERIOD_MS, как показано в примере ниже. Эта константа указывает длительность периода тика в миллисекундах.

Чтобы эта функция была доступна, опция INCLUDE_vTaskDelay должна быть определена как 1.

vTaskDelay() задает время, после истечения которого задача захочет стать разблокированной. Отсчет времени начинается с момента вызова функции vTaskDelay. Будет ли разблокирована задача после этого времени, или нет (т. е. точность выдержки заданного интервала), зависит от загруженности процессора прерываниями и другими задачами с более высоким приоритетом. Таким образом, vTaskDelay() не предоставляет гарантированный метод управления работой кода в реальном времени. См. описание xTaskDelayUntil() для альтернативы, которая была разработана для упрощения реализации кода, работающего с фиксированной частотой. Функция xTaskDelayUntil использует абсолютное время (вместо относительного) на котором задача должна быть разблокирована.

Параметры

xTicksToDelay: количество времени в количестве тиков системы, в течение которого задача должна находится в заблокированном состоянии.

Пример использования:

void vTaskFunction (void * pvParameters)
{
   // Блокировка на 500 мс.
   const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
 
   for( ;; )
   {
      // Задача просто переключает светодиод каждые 500 мс,
      // блокируясь между каждым переключением.
      vToggleLED();
      vTaskDelay( xDelay );
   }
}

BaseType_t xTaskDelayUntil (TickType_t *constpxPreviousWakeTime,
                            const TickType_t xTimeIncrement);

Чтобы эта функция была доступна, опция INCLUDE_xTaskDelayUntil должна быть определена в 1.

Задерживает выполнение задачи до указанного абсолютного времени. Эта функция может быть использована периодическими задачами, чтобы обеспечить постоянную частоту выполнения кода.

Поведение этой функции отличается от vTaskDelay в одном важном аспекте: vTaskDelay блокирует задачу на указанное количество тиков относительно момента, когда была вызвана vTaskDelay. По этой причине затруднительно использовать vTaskDelay для реализации фиксированной частоты работы участков кода между вызовами vTaskDelay (время между вызовами vTaskDelay не может быть фиксированным из-за работы других задач и активности прерываний).

В то время как vTaskDelay задает время пробуждения относительно момента, когда функция была вызвана, функция xTaskDelayUntil задает абсолютный (точный) момент времени, на котором функция хочет быть разблокированной.

Можно использовать макрос pdMS_TO_TICKS() для вычисления количества тиков от времени, заданного в миллисекундах.

Функция возвратит значение, по которому можно проверить, действительно ли функция была задержана. Возвращенное pdTRUE означает, что задача была задержана, иначе будет возвращено pdFALSE. Задача не была задержана, если следующее ожидаемое время пробуждения оказалось уже в прошлом.

Параметры

pxPreviousWakeTime: указатель на переменную, которая хранит время, на котором задача была последний раз разблокирована. Эта переменная должна быть инициализирована текущим временем перед своим первым использованием (см. пример ниже). После этого переменная будет обновлена в рамках вызова xTaskDelayUntil.

xTimeIncrement: период времени. Задача будет разблокирована в момент времени *pxPreviousWakeTime + xTimeIncrement. Вызов xTaskDelayUntil с таким же параметром xTimeIncrement, как и ранее, приведет к тому, что вызовы xTaskDelayUntil будут происходить с фиксированными интервалами времени.

Пример использования:

// Выполняет действие каждые 10 тиков.
void vTaskFunction (void * pvParameters)
{
   TickType_t xLastWakeTime;
   const TickType_t xFrequency = 10;
   BaseType_t xWasDelayed;
 
   // Инициализация переменной xLastWakeTime значением текущего времени.
   xLastWakeTime = xTaskGetTickCount ();
   for( ;; )
   {
      // Ожидание следующей прокрутки цикла.
      xWasDelayed = xTaskDelayUntil(&xLastWakeTime, xFrequency);
 
      // Здесь будет выполняться заданное действие. Значение xWasDelayed
      // может использоваться, чтобы определить, был ли корректно
      // выдержан заданный интервал времени, либо же момент вызова
      // был упущен из-за активности других задач и прерываний.
      ...
   }
}

BaseType_t xTaskAbortDelay (TaskHandle_t xTask);

Чтобы эта функция была доступна, опция INCLUDE_xTaskAbortDelay должна быть определена в значение 1 (в файле FreeRTOSConfig.h).

Задача будет оставаться в состоянии Blocked, когда она ждет наступления события. Ожидаемое событие может быть либо событием по времени (когда функция ожидает продолжения выполнения после вызова vTaskDelay), либо событием разблокировки на объекте (когда был вызов ожидания на очереди xQueueReceive() или был вызов ulTaskNotifyTake). Если в качестве параметра был передан дескриптор задачи, которая находится в состоянии Blocked, то эта задача выйдет из состояния Blocked с возвратом управления в то место своего кода, где было активизировано заблокированное состояние.

Не существует версии FromISR для этой функции, поскольку прерыванию нужно знать, на каком объекте была заблокирована задача, чтобы определить, какие действия нужно предпринять. Например, если задача была заблокирована на очереди, то обработчик прерывания должен знать, заблокирована ли очередь.

Будет возвращено значение pdFAIL, если xTask не находится в состоянии Blocked. Иначе будет возвращено pdPASS.

Параметры

xTask: дескриптор задачи, которая покинет состояние Blocked.

UBaseType_t uxTaskPriorityGet (const TaskHandle_t xTask);

Чтобы эта функция была доступна, опция INCLUDE_uxTaskPriorityGet должна быть определена в 1. Функция вернет значение приоритета для любой указанной задачи.

Параметры

xTask: дескриптор задачи. Передача NULL приведет к возврату приоритета задачи, из которой была вызвана функция.

Пример использования:

void vAFunction (void)
{
   TaskHandle_t xHandle;
 
   // Создается задача и сохраняется её дескриптор в переменной xHandle.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);
 
   // ...
 
   // Сохраненный дескриптор используется для получения приоритета
   // созданной задачи. Задача была создана с приоритетом tskIDLE_PRIORITY,
   // однако задача может для самой себя поменять приоритет.
   if (uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY)
   {
      // У задачи приоритет был изменен.
   }
 
   // ...
 
   // Приоритет нашего кода выше, чем у созданной задачи?
   if( uxTaskPriorityGet(xHandle) < uxTaskPriorityGet(NULL) )
   {
      // В настоящее время приоритет текущей задачи (получен при
      // использовании дескриптора со значением NULL) выше,
      // чем у созданной задачи.
   }
}

UBaseType_t uxTaskPriorityGetFromISR (const TaskHandle_t xTask);

Делает то же самое, что и uxTaskPriorityGet, но функция uxTaskPriorityGetFromISR предназначена для вызова из обработчика прерывания (ISR).

eTaskState eTaskGetState (TaskHandle_txTask);

Чтобы эта функция была доступна, опция INCLUDE_eTaskGetState должна быть определена как 1. Функция получит состояние любой задачи. Состояния кодируются значениями из перечисляемого типа eTaskState.

Возвратит состояние задачи xTask в момент вызова функции. Имейте в виду, что состояние задачи может поменяться в процессе вызова функции, и возвращенное значение из функции проверялось вызывающей задачей.

Параметры

xTask: дескриптор интересующей задачи.

void vTaskGetInfo (TaskHandle_txTask,
                   TaskStatus_t *pxTaskStatus,
                   BaseType_t xGetFreeStackSpace,
                   eTaskState eState);

Чтобы эта функция была доступна, опция configUSE_TRACE_FACILITY должна быть определена как 1.

Заполнит структуру TaskStatus_t информацией задачи.

Параметры

xTask: дескриптор опрашиваемой задачи. Если xTask указано NULL, то будет возвращена информация по текущей задаче (откуда была вызвана функция).

pxTaskStatus: указатель на структуру TaskStatus_t, поля которой будут заполнены информацией о задаче, на которую указывал параметр xTask.

xGetFreeStackSpace: структура TaskStatus_t будет содержать элемент, сообщающий о самой верхней границе использования стека задачи (high water mark). Вычисление water mark занимает относительно много времени, и может привести к тому, что система на некоторое время подвиснет, поэтому параметр xGetFreeStackSpace позволяет пропустить проверку на вычисление high water mark. Значение high watermark value будет записано только в том случае, если параметр xGetFreeStackSpace не установлен в pdFALSE;

eState: структура TaskStatus_t будет содержать элемент для сообщения о состоянии опрашиваемой задачи. Получение состояния задачи также не очень быстрое, по этой причине предоставлен параметр eState, чтобы можно было исключить информацию о состоянии. Для получения состояния установите параметр eState в значение eInvalid, иначе значение, переданное в eState, будет сообщаться как текущее состояние в структуре TaskStatus_t (никакого реального опроса состояния не будет).

Пример использования:

void vAFunction (void)
{
   TaskHandle_t xHandle;
   TaskStatus_t xTaskDetails;
 
   // Получение дескриптора задачи по её имени.
   xHandle = xTaskGetHandle("Task_Name");
 
   // Проверка дескриптора, что он не NULL.
   configASSERT( xHandle );
 
   // Использование дескриптора задачи для получения о ней подробной
   // информации.
   vTaskGetInfo(xHandle,
                &xTaskDetails,
                pdTRUE,       // добавить информацию по использованию стека
                eInvalid);    // добавить информацию о состоянии задачи.
}

void vTaskPrioritySet (TaskHandle_txTask, UBaseType_t uxNewPriority);

Чтобы эта функция была доступна, опция INCLUDE_vTaskPrioritySet должна быть установлена в 1.

Установит приоритет для любой задачи.

Перед возвратом из этой функции произойдет переключение контекста, если приоритет был установлен выше, чем приоритет текущей задачи (из которой была вызвана функция).

Параметры

xTask: дескриптор задачи, для которой был установлен приоритет. Передача NULL приведет к тому, что будет установлен приоритет текущей задачи (из которой была вызвана эта функция).

uxNewPriority: приоритет, который будет установлен для задачи.

Пример использования:

void vAFunction (void)
{
   TaskHandle_t xHandle;
 
   // Создание задачи, сохранение её дескриптора.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);
 
   // ...
 
   // Использование дескриптора для повышения приоритета созданной задачи.
   vTaskPrioritySet(xHandle, tskIDLE_PRIORITY + 1);
 
   // ...
 
   // Используйте дескриптор NULL, чтобы повысить приоритет нашего кода
   // до такого же уровня.
   vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 1);
}

void vTaskSuspend (TaskHandle_t xTaskToSuspend);

Чтобы эта функция была доступна, опция INCLUDE_vTaskSuspend должна быть определена как 1.

Функция приостановит любую задачу. Приостановленная задача не будет занимать время MCU, приоритет задачи при этом не будет играть никакого значения.

Вызов vTaskSuspend не является кумулятивным, т. е. вызов vTaskSuspend дважды эквивалентен однократному её вызову, и для возврата приостановленной задачи в состояние ready будет достаточно одного вызова vTaskResume.

Параметры

xTaskToSuspend: дескриптор приостанавливаемой задачи. Передача NULL приведет к тому, что будет приостановлена текущая задача (код, из которого была вызвана функция).

Пример использования:

void vAFunction (void)
{
   TaskHandle_t xHandle;
 
   // Создание задачи, сохранение её дескриптора.
   xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 
   // ...
 
   // Использование дескриптора для приостановки созданной задачи.
   vTaskSuspend(xHandle);
 
   // ...
 
   // Созданная задача не будет работать, пока из другой задачи не будет
   // сделан вызов vTaskResume(xHandle).
 
   //...
 
   // Приостановка самого себя.
   vTaskSuspend(NULL);
 
   // Сюда мы никогда не попадем, пока другая задача не вызовет
   // vTaskResume с дескриптором нашей задачи.
}

void vTaskResume (TaskHandle_t xTaskToResume);

Чтобы эта функция была доступна, опция INCLUDE_vTaskSuspend должна быть определена как 1.

Возобновляет выполнение приостановленной задачи.

Задача, которая была приостановлена одним из вызовов vTaskSuspend, после вызова vTaskResume будет снова доступна для выполнения.

Параметры

xTaskToResume: дескриптор задачи, которая должна быть возвращена в состояние ready.

Пример использования:

void vAFunction (void)
{
   TaskHandle_t xHandle;
 
   // Создание задачи, сохранение её дескриптора.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);
 
   // ...
 
   // Использование дескриптора для приостановки созданной задачи.
   vTaskSuspend(xHandle);
 
   // ...
 
   // Созданная задача не будет работать, пока из другой задачи не будет
   // сделан вызов vTaskResume(xHandle).
 
   //...
 
   // Возобновление работы приостановленной задачи.
   vTaskResume(xHandle);
 
   // Созданная задача снова будет потреблять вычислительное время MCU
   // в соответствии с её приоритетом в системе.
}

BaseType_t xTaskResumeFromISR (TaskHandle_t xTaskToResume);

Чтобы эта функция была доступна, опция INCLUDE_xTaskResumeFromISR должна быть определена как 1.

Делает то же самое, что и vTaskResume, только эта версия предназначена для вызова из тела ISR.

Задача, которая была приостановлена одним или большим количеством вызовов vTaskSuspend, снова станет доступна для выполнения после одиночного вызова xTaskResumeFromISR.

xTaskResumeFromISR не должна использоваться для синхронизации задачи с прерыванием, если есть шанс, что прерывание может произойти до приостановки задачи, поскольку это может привести к пропуску прерываний. Используйте механизм семафора, чтобы избежать таких событий.

Возвратит pdTRUE если возобновление задачи должно привести к переключению контекста, иначе будет возвращено pdFALSE. В коде ISR это используется для проверки, требуется ли переключение контекста после возврата из ISR.

Параметры

xTaskToResume: дескриптор задачи, которая должна быть возвращена в состояние ready.

void vTaskStartScheduler (void);

Запустит обработку тиков FreeRTOS (начнет работу планировщик задач и задача idle). После вызова этой функции планировщик начнет переключать контекст между задачами в соответствии с их установленными приоритетами и блокировками.

Примечание: порт ESP-IDF FreeRTOS запускает планировщик автоматически во время startup приложения, так что пользователю не нужно вызывать vTaskStartScheduler() из приложений ESP-IDF.

См. файл main.c демонстрационного приложения, где дан пример создания задач и запуска программного ядра FreeRTOS.

Пример использования:

void vAFunction (void)
{
   // Создание как минимум одной задачи перед запуском ядра.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
 
   // Запуск ядра (real time kernel) с вытесняющей многозадачностью.
   vTaskStartScheduler();
 
   // Сюда мы никогда не попадем, кроме как в ситуации, когда задача
   // вызовет vTaskEndScheduler.
}

void vTaskEndScheduler (void);

Останавливает обработку тиков ядра RTOS. Все созданные задачи будут автоматически удалены удалены, и многозадачность (с вытеснением или кооперативная) будет остановлена. Выполнение затем возобновится от момента, где был вызов vTaskStartScheduler, как если бы только что произошел возврат из vTaskStartScheduler.

См. файл main.c демонстрационного приложения в каталоге demo/PC для примера использования vTaskEndScheduler ().

vTaskEndScheduler требует наличия определения функции exit на слое portable (см. vPortEndScheduler() в модуле port.c для порта PC). Это выполнит специфичные для аппаратуры операции, такие как остановка тиков ядра.

vTaskEndScheduler() приведет к тому, что все ресурсы, выделенные ядром, будут освобождены, однако не будут освобождены ресурсы, которые были выделены задачами приложения.

Пример использования:

void vTaskCode (void * pvParameters)
{
   for( ;; )
   {
      // Здесь вставлен код задачи.
      // В некоторый момент мы можем захотеть закончить обработку ядра,
      // для этого вызовем:
      vTaskEndScheduler();
   }
}
 
void vAFunction (void)
{
   // Создание как минимум одной задачи перед запуском ядра.
   xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
 
   // Запуск ядра (real time kernel) с вытесняющей многозадачностью.
   vTaskStartScheduler ();
 
   // Сюда мы попадем только после того, как vTaskCode сделает вызов
   // vTaskEndScheduler(). Тогда управление дойдет до этого места, и мы
   // возвратимся в среду без многозадачности (single task execution).
}

void vTaskSuspendAll (void);

Приостанавливает планировщик без запрета прерываний. После этого переключение контекста больше происходить не будет.

После вызова vTaskSuspendAll текущая активная задача продолжит свое выполнение без риска быть вытесненной, пока не произойдет вызов xTaskResumeAll.

API-функции, которые потенциально вызывают переключение контекста (например vTaskDelayUntil(), xQueueSend(), и т. п.) не должны вызываться, когда планировщик приостановлен.

Пример использования:

void vTask1 (void * pvParameters)
{
   for( ;; )
   {
      // Здесь начинается код алгоритма задачи.
 
      // ...
 
      // В какой-то момент задача захочет выполнить длительное вычисление,
      // во время которого она не должна быть вытеснена другими задачами.
      // Она не может использовать taskENTER_CRITICAL/taskEXIT_CRITICAL,
      // поскольку длительность операции может привести к потере обработки
      // прерываний, включая тики.
 
      // Этот вызов предотвратит вытеснение текущей задачи.
      vTaskSuspendAll();
 
      // Здесь будет выполнена вышеупомянутая операция. Здесь нет
      // необходимости в использовании критических секций, поскольку
      // мы полностью используем все процессорное время MCU.
      // В течение этого времени прерывания все еще будут работать,
      // и будет продолжаться отсчет тиков ядра.
 
      // ...
 
      // Критическая операция завершена. Перезапуск программного
      // ядра RTOS.
      xTaskResumeAll ();
   }
}

BaseType_t xTaskResumeAll (void);

Возобновит работу планировщика после того, как он был остановлен вызовом vTaskSuspendAll().

Функция xTaskResumeAll только лишь возобновляет работу планировщика. Она не возобновляет приостановленные задачи, которые были ранее приостановлены вызовом vTaskSuspend().

Возвратит pdTRUE, если возобновление работы планировщика произведет переключение контекста, иначе будет возвращено pdFALSE.

Пример использования:

void vTask1 (void * pvParameters)
{
   for( ;; )
   {
      // Здесь начинается код алгоритма задачи.
 
      // ...
 
      // В какой-то момент задача захочет выполнить длительное вычисление,
      // во время которого она не должна быть вытеснена другими задачами.
      // Она не может использовать taskENTER_CRITICAL/taskEXIT_CRITICAL,
      // поскольку длительность операции может привести к потере обработки
      // прерываний, включая тики.
 
      // Этот вызов предотвратит вытеснение текущей задачи.
      vTaskSuspendAll();
 
      // Здесь будет выполнена вышеупомянутая операция. Здесь нет
      // необходимости в использовании критических секций, поскольку
      // мы полностью используем все процессорное время MCU.
      // В течение этого времени прерывания все еще будут работать,
      // и будет продолжаться отсчет тиков ядра.
 
      // ...
 
      // Операция была завершена. Перезапуск программного ядра RTOS.
      // Мы хотим в этот момент принудительно запустить переключение
      // контекста, но в этом не будет смысла, если возобновление
      // работы планировщика и так приведет к переключению контекста.
      if(!xTaskResumeAll())
      {
         taskYIELD();
      }
   }
}

TickType_t xTaskGetTickCount (void);

Возвратит прошедшее количество тиков от момента вызова vTaskStartScheduler.

TickType_t xTaskGetTickCountFromISR (void);

Эту версию xTaskGetTickCount можно безопасно вызывать из ISR - при условии, что TickType_t является естественным размером слова используемого MCU, или вложенность прерываний либо не поддерживается, либо не используется.

Возвратит прошедшее количество тиков от момента вызова vTaskStartScheduler.

UBaseType_t uxTaskGetNumberOfTasks (void);

Количество задач, которое в настоящий момент управляется программным ядром RTOS. Это количество включает все задачи в состоянии ready, blocked и suspended. Задача, которая была удалена, но еще не была освобождена задачей ожидания (idle task), также будет добавлена в это количество.

char *pcTaskGetName (TaskHandle_t xTaskToQuery);

Текст (удобочитаемый) имени задачи, на которую ссылаются по дескриптору xTaskToQuery. Задача может узнать собственное имя либо путем передачи собственного дескриптора, либо установкой параметра xTaskToQuery в NULL.

TaskHandle_t xTaskGetHandle (const char *pcNameToQuery);

Возвратит дескриптор задачи (handle) по удобочитамому имени pcNameToQuery. Если не найдено ни одного совпадающего имени, то будет возвращен NULL. ЧТобы эта функция была доступна, должна быть установлена в 1 опция INCLUDE_xTaskGetHandle.

Примечание: эта функция работает довольно медленно, поэтому не должна частот использоваться.

UBaseType_t uxTaskGetStackHighWaterMark (TaskHandle_t xTask);

Чтобы эта функция была доступна, опция INCLUDE_uxTaskGetStackHighWaterMark должна быть установлена в 1 (в FreeRTOSConfig.h).

Возвратит верхнюю границу максимального использования стека задачи, на которую ссылаются по её дескриптору xTask. Т. е. какое было минимальное свободное место в стеке (в байтах, а не в словах, как в vanilla FreeRTOS) с момента запуска задачи. Чем меньше возвращаемое число, тем задача ближе к переполнению своего стека.

uxTaskGetStackHighWaterMark() и uxTaskGetStackHighWaterMark2() одинаковые, за исключением возвращаемого типа. Опция configSTACK_DEPTH_TYPE позволяет выбрать возвращаемый тип. Это решает проблему переполнения 8-битных типов без нарушения обратной совместимости для приложений, которые ожидают возвращения значения 8-разрядного типа.

Параметры

xTask: дескриптор задачи, для которой проверяется расход пространства стека. Установите xTask в NULL, чтобы проверить стек собственной задачи (из которой вызывается эта функция).

configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2 (TaskHandle_t xTask);

Чтобы эта функция была доступна, должна быть установлена в 1 опция INCLUDE_uxTaskGetStackHighWaterMark2FreeRTOSConfig.h).

Возвратит верхнюю границу максимального использования стека задачи, на которую ссылаются по её дескриптору xTask. Т. е. какое было минимальное свободное место в стеке (в в словах, так что на 32-битной машине значение 1 соответствует 4 байтам) с момента запуска задачи. Чем меньше возвращаемое число, тем задача ближе к переполнению своего стека.

uxTaskGetStackHighWaterMark() и uxTaskGetStackHighWaterMark2() одинаковые, за исключением возвращаемого типа. Опция configSTACK_DEPTH_TYPE позволяет выбрать возвращаемый тип. Это решает проблему переполнения 8-битных типов без нарушения обратной совместимости для приложений, которые ожидают возвращения значения 8-разрядного типа.

Параметры

xTask: дескриптор задачи, для которой проверяется расход пространства стека. Установите xTask в NULL, чтобы проверить стек собственной задачи (из которой вызывается эта функция).

uint8_t *pxTaskGetStackStart (TaskHandle_t xTask);

Чтобы эта функция была доступна, опция INCLUDE_pxTaskGetStackStart должна быть установлена в 1 (в FreeRTOSConfig.h).

Возвратит самый маленький адрес памяти пространства стека (указатель на начало стека) задачи, независимо от того, в какую сторону растет стек - вверх или вниз.

Параметры

xTask: дескриптор задачи, для которой будет возвращаться информация о стеке. Установите xTask в NULL, чтобы узнать начало в памяти собственного стека задачи (задачи, которая вызывает эту функцию).

void vTaskSetApplicationTaskTag (TaskHandle_t xTask,
                                 TaskHookFunction_t pxHookFunction);

Установит pxHookFunction в качестве hook-функции, используемой для задачи xTask [7].

Параметры

xTask: дескриптор задачи, для которой устанавливается hook-функцию. Передача xTask = NULL установит hook-функцию для вызывавшей задачи.

pxHookFunction: указатель на hook-функцию.

TaskHookFunction_t xTaskGetApplicationTaskTag (TaskHandle_t xTask);

Возвратит значение pxHookFunction, назначенное задаче xTask. Не вызывайте эту функцию из обработчика прерывания, вместо неё используйте xTaskGetApplicationTaskTagFromISR().

TaskHookFunction_t xTaskGetApplicationTaskTagFromISR (TaskHandle_t xTask);

Возвратит значение pxHookFunction, назначенное задаче xTask. Эту версию функции следует вызывать из обработчика прерывания.

void vTaskSetThreadLocalStoragePointer (TaskHandle_t xTaskToSet,
                                        BaseType_t xIndex,
                                        void *pvValue);

Устанавливает указатель на локальное хранилище для указанной задачи.

Каждая задача содержит массив указателей, размер которого определяется опцией configNUM_THREAD_LOCAL_STORAGE_POINTERS в FreeRTOSConfig.h. Программное ядро RTOS само не использует эти указатели, так что разработчик приложения может использовать эти указатели для любых целей по своему усмотрению.

Параметры

xTaskToSet: задача, для которой устанавливается local storage pointer.

xIndex: индекс устанавливаемого указателя, от 0 до configNUM_THREAD_LOCAL_STORAGE_POINTERS-1.

pvValue: значение для установки указателя.

void *pvTaskGetThreadLocalStoragePointer (TaskHandle_t xTaskToQuery,
                                          BaseType_t xIndex);

Получает указатель локального хранилища для определенной задачи.

Каждая задача содержит массив указателей, размер которого определяется опцией configNUM_THREAD_LOCAL_STORAGE_POINTERS в FreeRTOSConfig.h. Программное ядро RTOS само не использует эти указатели, так что разработчик приложения может использовать эти указатели для любых целей по своему усмотрению.

Функция возвратит значение указателя.

Параметры

xTaskToQuery: задача, для которой будет возвращен указатель на локальное хранилище.

xIndex: индекс получаемого указателя, от 0 до configNUM_THREAD_LOCAL_STORAGE_POINTERS-1.

void vTaskSetThreadLocalStoragePointerAndDelCallback (TaskHandle_t xTaskToSet,
                                                      BaseType_t xIndex,
                                                      void *pvValue,
                                                      TlsDeleteCallbackFunction_t pvDelCallback);

Устанавливает указатель локального хранилища и callback-функцию удаления.

Каждая задача содержит массив указателей, размер которого определяется опцией configNUM_THREAD_LOCAL_STORAGE_POINTERS в FreeRTOSConfig.h. Программное ядро RTOS само не использует эти указатели, так что разработчик приложения может использовать эти указатели для любых целей по своему усмотрению.

Указатели локального хранилища, установленные для задачи, могут ссылаться на динамически выделенные ресурсы. Эта функция подобна vTaskSetThreadLocalStoragePointer, но предоставляет способ освобождения этих ресурсов, когда задача удаляется. Для каждого указателя может быть установлена callback-функция. Эта функция будет вызвана, когда задача удаляется, с индексом локального хранилища указателей и значением, передаваемых в качестве аргументов.

Параметры

xTaskToSet: задача, для которой устанавливается указатель локального хранилища.

xIndex: индекс для устанавливаемого указателя, от 0 до configNUM_THREAD_LOCAL_STORAGE_POINTERS-1.

pvValue: значение устанавливаемого указателя.

pvDelCallback: вызываемая функция при удалении задачи для удаления указателя локального хранилища.

void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer,
                                    StackType_t **ppxIdleTaskStackBuffer,
                                    uint32_t *pulIdleTaskStackSize);

Эта функция используется для предоставления статически выделенного блока памяти для FreeRTOS, чтобы хранить Idle Task TCB. Эта функция требуется, когда установлена опция configSUPPORT_STATIC_ALLOCATION. Для дополнительной информации см. [8].

Параметры

ppxIdleTaskTCBBuffer: дескриптор для выделенного статически буфера TCB.

ppxIdleTaskStackBuffer: дескриптор для статически выделенного буфера стека для idle task.

pulIdleTaskStackSize: указатель для количества элементов, которое помещается в выдеденный буфер стека.

BaseType_t xTaskCallApplicationTaskHook (TaskHandle_t xTask,
                                         void *pvParameter);

Вызывает hook-функцию, связанную с xTask. Передача NULL в xTask приведет к тому, что будет вызвана hook-функция текущей задачи (из которой была вызвана (xTaskCallApplicationTaskHook).

Параметры

xTask: дескриптор задачи, для которой будет вызвана hook-функция.

pvParameter: параметр для передачи в hook-функцию задачи, который будет интерпретирован по своему усмотрению. Возвращаемое значение это значение, которое возвратит hook-функция, зарегистрированная пользователем.

TaskHandle_t xTaskGetIdleTaskHandle (void);

Эта функция доступна только если установлена в 1 опция INCLUDE_xTaskGetIdleTaskHandle (в FreeRTOSConfig.h).

Просто возвратит дескриптор idle task. Недопустимо вызывать xTaskGetIdleTaskHandle до запуска планировщика.

UBaseType_t uxTaskGetSystemState (TaskStatus_t *constpxTaskStatusArray,
                                  const UBaseType_t uxArraySize,
                                  uint32_t *constpulTotalRunTime);

Чтобы эта функция была доступна, опция configUSE_TRACE_FACILITY должна быть установлена в 1 (в FreeRTOSConfig.h).

uxTaskGetSystemState() заполняет структуру TaskStatus_t для каждой задачи в системе. Структура TaskStatus_t содержит, вместе с другой информацией, поля для дескриптора задачи, имени задачи, приоритета задачи, состояния задачи, и также есть общее процессорное время, потребленного задачей.

Примечание: эта функция предназначена только для отладки, поскольку её использование приводит к тому, что планировщик остается приостановленным в течение длительного времени.

Функция возвратит количество структур TaskStatus_t, которые были заполнены. Это значение должно быть равно количеству, которое возвращается вызовом API-функции uxTaskGetNumberOfTasks, но будет равно 0, если значение, переданное в uxArraySize, слишком маленькое.

Параметры

pxTaskStatusArray: указатель на массив структур TaskStatus_t. Этот массив должен содержать как минимум одну структуру TaskStatus_t для каждой задачи, которой управляет RTOS. Количество этих задач может быть определено вызовом uxTaskGetNumberOfTasks.

uxArraySize: размер массива, на который указывает параметр pxTaskStatusArray. Размер указывается в количестве индексов в массиве, или в количестве структур TaskStatus_t, содержащихся в массиве, но не количество байт в этом массиве.

pulTotalRunTime: если опция configGENERATE_RUN_TIME_STATS установлена в 1 (в FreeRTOSConfig.h), то *pulTotalRunTime будет установлен функцией в общее время работы (как это было определено тактами статистики, см. [9]) от момента загрузки системы. Указатель pulTotalRunTime может быть установлен в NULL, чтобы опустить информацию общего времени работы.

Пример использования:

// Этот пример демонстрирует, как можно построить удобную для чтения
// таблицу статистики выполнения задач из данных, предоставленных
// вызовом функции uxTaskGetSystemState(). Эта таблица записывается
// в буфер pcWriteBuffer.
void vTaskGetRunTimeStats (char *pcWriteBuffer)
{
   TaskStatus_t *pxTaskStatusArray;
   volatile UBaseType_t uxArraySize, x;
   uint32_t ulTotalRunTime, ulStatsAsPercentage;
 
   // Гарантируем, что записываемый буфер не будет содержать строку.
   pcWriteBuffer = 0x00;
 
   // Делаем снимок количества задач в случае, если это количество
   // поменялось во время выполнения этой функции.
   uxArraySize = uxTaskGetNumberOfTasks();
 
   // Выделяем динамически (из кучи) структуру TaskStatus_t для каждой
   // задачи. Альтернативно этот массив может быть выделен статически
   // во время компиляции.
   pxTaskStatusArray = pvPortMalloc(uxArraySize * sizeof(TaskStatus_t));
 
   if (pxTaskStatusArray != NULL)
   {
      // Генерируется сырая информация состояния по каждой задаче.
      uxArraySize = uxTaskGetSystemState(pxTaskStatusArray,
                                         uxArraySize,
                                         &ulTotalRunTime);
 
      // Для процента проведенных вычислений.
      ulTotalRunTime /= 100UL;
 
      // Позволяет избежать ошибок деления на 0.
      if( ulTotalRunTime > 0 )
      {
         // Для каждой заполненной позиции в массиве pxTaskStatusArray
         // сырые данные форматируются для приведения в удобочитаемый
         // формат ASCII.
         for (x = 0; x < uxArraySize; x++)
         {
            // Сколько процентов от общего потребленного времени использовала
            // эта задача? Это значение всегда будет округлено вниз до
            // ближайшего целого. ulTotalRunTimeDiv100 уже было поделено
            // на 100.
            ulStatsAsPercentage = pxTaskStatusArray[x].ulRunTimeCounter / ulTotalRunTime;
 
            if(ulStatsAsPercentage > 0UL)
            {
               sprintf(pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n",
                                      pxTaskStatusArray[x].pcTaskName,
                                      pxTaskStatusArray[x].ulRunTimeCounter,
                                      ulStatsAsPercentage);
            }
            else
            {
               // Если процентное значение равно 0, то это значит, что задача
               // потратила меньше 1% общего процессорного времени.
               sprintf(pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n",
                                      pxTaskStatusArray[x].pcTaskName,
                                      pxTaskStatusArray[x].ulRunTimeCounter);
            }
 
            pcWriteBuffer += strlen((char*)pcWriteBuffer);
         }
      }
 
      // Массив больше не нужен, освободим память, где он находился.
      vPortFree(pxTaskStatusArray);
   }
}

void vTaskList (char *pcWriteBuffer);

Генерирует список всех текущих задач.

Чтобы эта функция была доступна, обе опции configUSE_TRACE_FACILITY и configUSE_STATS_FORMATTING_FUNCTIONS должны быть определены как 1.

Замечание: эта функция запретит прерывания во время своего выполнения. Она не предназначена для нормальной работы приложения, и должна использоваться только во время отладки.

Строит список всех текущих задач, вместе с информацией об их текущем состоянии и использовании стека.

Состояние задач обозначается следующими символами: blocked как B, ready как R, deleted как D, suspended как S.

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

vTaskList() вызывает uxTaskGetSystemState(), затем форматирует вывод uxTaskGetSystemState() в удобочитаемый формат, где показаны имена задач, их состояние и использование стека.

Поскольку vTaskList() зависит от библиотечной функции sprintf(), что может привести к раздуванию размера кода, расходу стека, и функция может давать разные результаты на разных платформах. В качестве альтернативы может использоваться урезанная реализация sprintf(), которая есть во многих подкаталогах FreeRTOS/Demo в файле printf-stdarg.c (имейте в виду, что printf-stdarg.c не предоставляет все возможности стандартной sprintf).

В системах, поставляемых в производство, рекомендуется вызывать uxTaskGetSystemState() напрямую для получения доступа к сырым данным статистики, вместо того чтобы вызывать vTaskList().

Параметры

pcWriteBuffer: буфер, куда будет записана вышеупомянутая информационная таблица по задачам в виде удобочитаемого текста ASCII. Подразумевается, что этот буфер достаточного размера, чтобы в нем поместился генерируемый отчет. Будет достаточным приблизительно по 40 байт на каждую задачу.

void vTaskGetRunTimeStats (char *pcWriteBuffer);

Получает состояние текущих задач в виде строки.

Чтобы была доступна эта функция, обе опции configGENERATE_RUN_TIME_STATS и configUSE_STATS_FORMATTING_FUNCTIONS должны быть определены как 1. Приложение также должно предоставить определения для portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() и portGET_RUN_TIME_COUNTER_VALUE(), чтобы сконфигурировать периферийное устройство таймера/счетчика, и возвратить текущее значение счетчика таймера соответственно. Счетчик должен быть как минимум в 10 раз больше счетчика тиков.

Эта функция запрещает прерывания во время своего выполнения. Она не предназначена для нормального функционирования приложения, и должна использоваться только для отладки. Функция предоставлена только для удобства, и используется во многих демонстрационных приложениях. Она вовсе не является частью планировщика.

Установка в 1 опции configGENERATE_RUN_TIME_STATS приведет к сохранению накопленного времени выполнения для каждой задачи. Точность значения накопляемого времени зависит от частоты таймера, сконфигурированного макросом portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(). Вызов vTaskGetRunTimeStats() записывает общее время выполнения каждой задачи в буфер, и как абсолютное значение счетчика, так и процент от общего потребленного процессорного времени системы.

vTaskGetRunTimeStats() вызывает uxTaskGetSystemState(), затем форматирует части вывода uxTaskGetSystemState() в удобочитаемую таблицу, где отображается время для каждой задачи, которое задача провела в состоянии Running, в абсолютном и процентном виде.

vTaskGetRunTimeStats() зависит от библиотечной функции sprintf(), что может привести к раздуванию размера кода, расходу стека, и функция может давать разные результаты на разных платформах. В качестве альтернативы может использоваться урезанная реализация sprintf(), которая есть во многих подкаталогах FreeRTOS/Demo в файле printf-stdarg.c (имейте в виду, что printf-stdarg.c не предоставляет все возможности стандартной sprintf).

В системах, поставляемых в производство, рекомендуется вызывать uxTaskGetSystemState() напрямую для получения доступа к сырым данным статистики, вместо того чтобы вызывать vTaskGetRunTimeStats().

Параметры

pcWriteBuffer: буфер, куда будут записаны времена выполнения в виде удобочитаемого текста ASCII. Подразумевается, что этот буфер достаточного размера, чтобы в нем поместился генерируемый отчет. Будет достаточным приблизительно по 40 байт на каждую задачу.

uint32_t ulTaskGetIdleRunTimeCounter (void);

Чтобы была доступна эта функция, обе опции configGENERATE_RUN_TIME_STATS и configUSE_STATS_FORMATTING_FUNCTIONS должны быть определены как 1. Приложение также должно предоставить определения для portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() и portGET_RUN_TIME_COUNTER_VALUE(), чтобы сконфигурировать периферийное устройство таймера/счетчика, и возвратить текущее значение счетчика таймера соответственно. Счетчик должен быть как минимум в 10 раз больше счетчика тиков.

Установка в 1 опции configGENERATE_RUN_TIME_STATS приведет к сохранению накопленного времени выполнения для каждой задачи. Точность значения накопляемого времени зависит от частоты таймера, сконфигурированного макросом portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(). В то время как uxTaskGetSystemState() и vTaskGetRunTimeStats() записывают в буфер общее время выполнения по каждой задаче, функция ulTaskGetIdleRunTimeCounter() возвратит общее время выполнения только для задачи ожидания (idle task).

Вернет общее время работы idle task. Это количество времени, которое задача ожидания реально выполнялась. Единица времени зависит от частоты, сконфигурированной с использованием макросов portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() и portGET_RUN_TIME_COUNTER_VALUE().

BaseType_t xTaskGenericNotify (TaskHandle_t xTaskToNotify,
                               UBaseType_t uxIndexToNotify,
                               uint32_t ulValue,
                               eNotifyAction eAction,
                               uint32_t *pulPreviousNotificationValue);

Отправляет прямое оповещение (task notification) от одной задачи к другой, передавая опциональное значение (ulValue) и действие (eAction). Подробную информацию по этой функции см. в [10]. Чтобы функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть определена в 1.

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

Задача может использовать xTaskNotifyWaitIndexed() чтобы (опционально) блокироваться на ожидании оповещения, или ulTaskNotifyTakeIndexed() чтобы (опционально) блокироваться для ожидания значения оповещения, чтобы получить не нулевое значение. Задача не тратит процессорное время, когда находится в заблокированном состоянии (состояние Blocked).

Уведомление, отправленное задаче, будет оставаться в состоянии ожидания до тех пор, пока не будет очищено задачей вызовом xTaskNotifyWaitIndexed() или ulTaskNotifyTakeIndexed() (или их un-indexed эквивалентами). Если задача уже находится в состоянии Blocked для ожидания оповещения, то оповещение доставлено, задача автоматически выходит из состояния Blocked (разблокируется) и оповещение очищается.

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotify() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotify() эквивалентен вызову xTaskNotifyIndexed() с параметром uxIndexToNotify, установленным в 0.

eSetBits - целевое значение оповещения, на которое накладывается операция OR со значением ulValue. xTaskNotifyIndexed() в таком случае всегда вернет pdPASS.

Параметры

xTaskToNotify: дескриптор задачи, которая оповещается. Дескриптор задачи может быть возвращен из API-функции xTaskCreate(), используемой для создания задачи, и дескриптор работающей в настоящий момент задачи может быть получен вызовом xTaskGetCurrentTaskHandle().

uxIndexToNotify: индекс в массиве значений оповещения целевой задачи, куда отправляется оповещение. Значение uxIndexToNotify должно быть меньше, чем значение опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У xTaskNotify() нет такого параметра, и она всегда шлет оповещение по индексу 0.

ulValue: данные, которые можно отправить с оповещением. Каки используются эти данные, зависит от значения параметра eAction.

eAction: задает, как оповещение обновляет значение оповещения задачи, если оно вообще есть. Для eAction допустимы следующие значения:

eIncrement - значение оповещения цели инкрементируется. ulValue не используется, и xTaskNotifyIndexed() в этом случае всегда вернет pdPASS.

eSetValueWithOverwrite - значение оповещения цели будет установлено в значение ulValue, даже если оповещаемая задача еще не обработало предыдущее оповещение по тому же самому индексу в массиве (у задачи уже есть ожидающее обработки оповещение по этому индексу). В этом случае xTaskNotifyIndexed() всегда вернет pdPASS.

eSetValueWithoutOverwrite - если оповещаемая задача пока не имеет ожидающее обработки оповещение по тому же самому индексу, то значение оповещения цели установится в ulValue и xTaskNotifyIndexed() вернет pdPASS. Если же оповещаемая задача уже имеет оповещение, ожидающее по тому же самому индексу, то никакого действия произведено не будет, и будет возвращено pdFAIL.

eNoAction - задача получает оповещение по указанному индексу массива, без обновления значения оповещения по обновляемому индексу. ulValue не используется, и xTaskNotifyIndexed() в этом случае всегда возвратит pdPASS.

pulPreviousNotificationValue: этот параметр может использоваться для передачи значения оповещения задачи-субъекта до того, как функцией оповещения будут изменены любые биты.

Возвращаемое функцией xTaskGenericNotify значение зависит от значения параметра eAction, см. описание этого параметра.

BaseType_t xTaskGenericNotifyFromISR (TaskHandle_t xTaskToNotify,
                                      UBaseType_t uxIndexToNotify,
                                      uint32_t ulValue,
                                      eNotifyActioneAction,
                                      uint32_t *pulPreviousNotificationValue,
                                      BaseType_t *pxHigherPriorityTaskWoken);

Это версия xTaskGenericNotify, которая может использоваться из обработчика прерывания (ISR). Чтобы эти функции были доступны, опция configUSE_TASK_NOTIFICATIONS должна быть сконфигурирована в 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

Задача может использовать xTaskNotifyWaitIndexed() чтобы (опционально) блокироваться на ожидании оповещения, или ulTaskNotifyTakeIndexed() чтобы (опционально) блокироваться для ожидания значения оповещения, чтобы получить не нулевое значение. Задача не тратит процессорное время, когда находится в заблокированном состоянии (состояние Blocked).

Уведомление, отправленное задаче, будет оставаться в состоянии ожидания до тех пор, пока не будет очищено задачей вызовом xTaskNotifyWaitIndexed() или ulTaskNotifyTakeIndexed() (или их un-indexed эквивалентами). Если задача уже находится в состоянии Blocked для ожидания оповещения, то оповещение доставлено, задача автоматически выходит из состояния Blocked (разблокируется) и оповещение очищается.

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotify() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotify() эквивалентен вызову xTaskNotifyIndexed() с параметром uxIndexToNotify, установленным в 0.

eSetBits - целевое значение оповещения, на которое накладывается операция OR со значением ulValue. xTaskNotifyIndexed() в таком случае всегда вернет pdPASS.

Параметры

xTaskToNotify: дескриптор задачи, которая оповещается. Дескриптор задачи может быть возвращен из API-функции xTaskCreate(), используемой для создания задачи, и дескриптор работающей в настоящий момент задачи может быть получен вызовом xTaskGetCurrentTaskHandle().

uxIndexToNotify: индекс в массиве значений оповещения целевой задачи, куда отправляется оповещение. Значение uxIndexToNotify должно быть меньше, чем значение опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У xTaskNotifyFromISR() нет такого параметра, и она всегда шлет оповещение по индексу 0.

ulValue: данные, которые можно отправить с оповещением. Каки используются эти данные, зависит от значения параметра eAction.

eAction: задает, как оповещение обновляет значение оповещения задачи, если оно вообще есть. Для eAction допустимы следующие значения:

eIncrement - значение оповещения цели инкрементируется. ulValue не используется, и xTaskNotifyIndexed() в этом случае всегда вернет pdPASS.

eSetValueWithOverwrite - значение оповещения цели будет установлено в значение ulValue, даже если оповещаемая задача еще не обработало предыдущее оповещение по тому же самому индексу в массиве (у задачи уже есть ожидающее обработки оповещение по этому индексу). В этом случае xTaskNotifyIndexed() всегда вернет pdPASS.

eSetValueWithoutOverwrite - если оповещаемая задача пока не имеет ожидающее обработки оповещение по тому же самому индексу, то значение оповещения цели установится в ulValue и xTaskNotifyIndexed() вернет pdPASS. Если же оповещаемая задача уже имеет оповещение, ожидающее по тому же самому индексу, то никакого действия произведено не будет, и будет возвращено pdFAIL.

eNoAction - задача получает оповещение по указанному индексу массива, без обновления значения оповещения по обновляемому индексу. ulValue не используется, и xTaskNotifyIndexed() в этом случае всегда возвратит pdPASS.

pulPreviousNotificationValue: этот параметр может использоваться для передачи значения оповещения задачи-субъекта до того, как функцией оповещения будут изменены любые биты.

pxHigherPriorityTaskWoken: xTaskNotifyFromISR() установит *pxHigherPriorityTaskWoken в pdTRUE, если отправка оповещения приведет к выводу из состояния Blocked задачи, которой оповещение отправляется, и разблокированная задача имеет приоритет выше, чем задача, которая выполняется в настоящий момент. Если xTaskNotifyFromISR() установит это значение в pdTRUE, то должно быть запрошено переключение контекста до выхода из прерывания. Как именно запрашивается переключение контекста из ISR, зависит от конкретного порта FreeRTOS, см. соответствующую информацию по используемому порту.

Возвращаемое функцией xTaskGenericNotifyFromISR значение зависит от значения параметра eAction, см. описание этого параметра.

BaseType_t xTaskGenericNotifyWait (UBaseType_t uxIndexToWaitOn,
                                   uint32_t ulBitsToClearOnEntry,
                                   uint32_t ulBitsToClearOnExit,
                                   uint32_t *pulNotificationValue,
                                   TickType_t xTicksToWait);

Ожидает поступление прямого оповещения от другой задачи по указанному индексу в массиве значений оповещения. Чтобы эта функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть сконфигурирована в 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

Задача может использовать xTaskNotifyWaitIndexed() чтобы (опционально) блокироваться на ожидании оповещения, или ulTaskNotifyTakeIndexed() чтобы (опционально) блокироваться для ожидания значения оповещения, чтобы получить не нулевое значение. Задача не тратит процессорное время, когда находится в заблокированном состоянии (состояние Blocked).

Уведомление, отправленное задаче, будет оставаться в состоянии ожидания до тех пор, пока не будет очищено задачей вызовом xTaskNotifyWaitIndexed() или ulTaskNotifyTakeIndexed() (или их un-indexed эквивалентами). Если задача уже находится в состоянии Blocked для ожидания оповещения, то оповещение доставлено, задача автоматически выходит из состояния Blocked (разблокируется) и оповещение очищается.

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotify() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotify() эквивалентен вызову xTaskNotifyIndexed() с параметром uxIndexToNotify, установленным в 0.

Если было получено оповещение (включая оповещения, которые уже ожидают, когда xTaskNotifyWait была вызвана), то функция pdPASS, иначе будет возвращено pdFAIL.

Параметры

uxIndexToWaitOn: индекс в массиве значений оповещения задачи, откуда вызвана функция. На значении по этому индексу задача будет ждать поступления оповещения. Значение uxIndexToWaitOn должно быть меньше значения опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У функции xTaskNotifyWait() нет этого параметра, и она всегда ждет оповещения по индексу 0.

ulBitsToClearOnEntry: биты, которые установлены в ulBitsToClearOnEntry, будут очищены в значении оповещения вызывающей функции до того, как задача проверит, находятся ли какие-либо оповещения в состоянии ожидания и опционально заблокируется, если таких оповещений не было. Установка ulBitsToClearOnEntry в ULONG_MAX (если подключен limits.h) или в 0xffffffffUL (если limits.h не подключен) даст эффект сброса в 0 значения оповещения задачи. Установка ulBitsToClearOnEntry в 0 оставит неизменным значение оповещения задачи.

ulBitsToClearOnExit: если оповещение ожидает обработки, или получено до того, как вызывающая функция выйдет из функции xTaskGenericNotifyWait(), то значение уведомления задачи (см. описание API-функции xTaskNotify()) будет передано обратно с помощью параметра pulNotificationValue. Тогда любые биты, установленные в ulBitsToClearOnExit, будут очищены в значении оповещения задачи (обратите внимание, что *pulNotificationValue устанавливается перед очисткой любых бит). Установка ulBitsToClearOnExit в ULONG_MAX (если подключен limits.h) или в 0xffffffffUL (если limits.h не подключен) дает эффект сброса в 0 значения оповещения задачи перед выходом из функции. Установка ulBitsToClearOnExit в 0 оставит значение оповещения задачи неизменным при выходе из функции (в этом случае значение, переданное наружу в pulNotificationValue, будет совпадать со значением оповещения задачи).

pulNotificationValue: используется для передачи обратно из функции значения оповещения задачи. Обратите внимание, что передаваемое обратно значение не будет зависеть от очистки любых бит, которые ненулевые в ulBitsToClearOnExit.

xTicksToWait: максимальное время, которое задача должна ждать в состоянии Blocked для получения оповещения, если оповещение еще не поступило, когда была вызвана xTaskGenericNotifyWait(). В состоянии Blocked задача не будет потреблять процессорное время. Время ожидания задается в тиках программного ядра, и может использоваться макрос pdMS_TO_TICKS(значение_в_мс) для преобразования времени в миллисекундах в тики системы. Если указать значение portMAX_DELAY, то задача будет ждать оповещения без таймаута (бесконечно долго).

void vTaskGenericNotifyGiveFromISR (TaskHandle_t xTaskToNotify,
                                    UBaseType_t uxIndexToNotify,
                                    BaseType_t *pxHigherPriorityTaskWoken);

Версия xTaskNotifyGiveIndexed(), которую можно использовать из обработчика прерывания (ISR). Чтобы эта функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть не определена, либо определена как 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

Макрос vTaskNotifyGiveIndexedFromISR() предназначен для применения, когда оповещения задачи используются как облегченный и ускоренный эквивалент двоичного семафора или семафора со счетчиком. Реальные семафоры FreeRTOS выдаются из ISR с использованием API-функции xSemaphoreGiveFromISR(), и соответствующее эквивалентное действие использует оповещение задачи с помощью vTaskNotifyGiveIndexedFromISR().

Когда оповещения задачи используются в качестве эквивалента двоичного семафора или семафора со счетчиком, оповещаемая задача должна ждать получения оповещения с помощью вызова API-функции ulTaskNotificationTakeIndexed() вместо API-функции xTaskNotifyWaitIndexed().

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotifyFromISR() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotifyGiveFromISR() эквивалентен вызову xTaskNotifyGiveIndexedFromISR() с параметром uxIndexToNotify, установленным в 0.

Параметры

xTaskToNotify: дескриптор задачи, которая оповещается. Дескриптор задачи может быть возвращен из API-функции xTaskCreate(), используемой для создания задачи, и дескриптор работающей в настоящий момент задачи может быть получен вызовом xTaskGetCurrentTaskHandle().

uxIndexToNotify: индекс в массиве значений оповещения целевой задачи, куда отправляется оповещение. Значение uxIndexToNotify должно быть меньше, чем значение опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У xTaskNotifyGiveFromISR() нет такого параметра, и она всегда шлет оповещение по индексу 0.

pxHigherPriorityTaskWoken: vTaskNotifyGiveFromISR() установит *pxHigherPriorityTaskWoken в pdTRUE, если отправка оповещения приведет к выводу из состояния Blocked задачи, которой оповещение отправляется, и разблокированная задача имеет приоритет выше, чем задача, которая выполняется в настоящий момент. Если vTaskNotifyGiveFromISR() установит это значение в pdTRUE, то должно быть запрошено переключение контекста до выхода из прерывания. Как именно запрашивается переключение контекста из ISR, зависит от конкретного порта FreeRTOS, см. соответствующую информацию по используемому порту.

uint32_t ulTaskGenericNotifyTake (UBaseType_t uxIndexToWaitOn,
                                  BaseType_t xClearCountOnExit,
                                  TickType_t xTicksToWait);

Ожидает поступления прямого оповещения задачи по определенному индексу в массиве значений оповещения, аналогично использованию семафора со счетчиком. Чтобы эта функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть определена в 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

Функция ulTaskNotifyTakeIndexed() предназначена для применения, когда оповещения задачи используются как облегченный и ускоренный эквивалент двоичного семафора или семафора со счетчиком. Реальные семафоры FreeRTOS берутся с использованием API-функции xSemaphoreTake(), и соответствующее эквивалентное действие использует оповещение задачи с помощью ulTaskNotifyTakeIndexed().

Когда задача использует это значение оповещения в качестве двоичного семафора или семафора со счетчиком, другие задачи должны посылать ей оповещения с использованием макроса xTaskNotifyGiveIndexed(), или функции xTaskNotifyIndex(), в которых параметр eAction установлен в значение eIncrement.

ulTaskNotifyTakeIndexed() может либо при выходе очистить значение оповещения задачи в 0 по индексу, заданному параметром uxIndexToWaitOn (в таком случае значение оповещения работает в качестве двоичного семафора), либо декрементировать при выходе значение оповещения (в таком случае значение оповещения работает как семафор со счетчиком).

Задача может использовать ulTaskNotifyTakeIndexed() для (опциональной) блокировки на ожидании ненулевого значения оповещения. Задача не потребляет процессорное время, когда находится в заблокированном (Blocked) состоянии.

В то время как xTaskNotifyWaitIndexed() сделает возврат, когда ожидается оповещение, функция ulTaskNotifyTakeIndexed() делает возврат, когда значение оповещения задачи ненулевое.

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. ulTaskNotifyTake() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов ulTaskNotifyTake() эквивалентен вызову ulTaskNotifyTakeIndexed() с параметром uxIndexToWaitOn, установленным в 0.

Функция возвратит значение счетчика оповещений задачи до того, как он будет очищен в 0 или декрементирован (см. описание параметра xClearCountOnExit).

Параметры

uxIndexToWaitOn: индекс в массиве значений оповещения вызывающей задачи, на котором она ждет оповещения с ненулевым значением. Параметр uxIndexToWaitOn должен быть меньше значения опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У xTaskNotifyTake() нет этого параметра, и она всегда ждет оповещений по индексу 0.

xClearCountOnExit: если xClearCountOnExit равен pdFALSE, то значение оповещения задачи декрементируется, когда происходит выход из функции. При таком способе значение оповещения работает подобно семафору со счетчиком. Если же xClearCountOnExit не pdFALSE, то значение оповещения задач очищается в 0 при выходе из функции. В таком случае значение оповещения работает как двоичный семафор.

xTicksToWait: максимальное количество времени, которое задача должна ждать в состоянии Blocked, когда значение оповещения станет больше 0, если при вызове ulTaskNotifyTake() значение оповещения не было больше 0. В состоянии Blocked задача не потребляет процессорное время. Время ожидания задается в тиках программного ядра, и может использоваться макрос pdMS_TO_TICKS(значение_в_мс) для преобразования времени в миллисекундах в тики системы. Если указать значение portMAX_DELAY, то задача будет ждать оповещения без таймаута (бесконечно долго).

BaseType_t xTaskGenericNotifyStateClear (TaskHandle_t xTask,
                                         UBaseType_t uxIndexToClear);

Чтобы эта функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть установлена в 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

Если оповещение отправлено по индексу в массиве оповещений, то оповещение по этому индексу считается "ожидающим" (pending) до тех пор, пока оно не будет явно прочитано или сброшено получающей оповещение задачей (receiving task). xTaskNotifyStateClearIndexed() это макрос, который очищает ожидающее оповещение без чтения значения оповещения. Значение оповещения по тому же самому индексу ни изменяется. Установка xTask в NULL очистит состояние оповещения для вызывающей задачи.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotifyStateClear() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotifyStateClear() эквивалентен вызову xTaskNotifyStateClearIndexed() с параметром uxIndexToNotify, установленным в 0.

Функция возвратит pdTRUE, если состояние оповещения задачи было установлено в eNotWaitingNotification, иначе возвратит pdFALSE.

Параметры

xTask: дескриптор задачи RTOS, состояние оповещения для которой очищается. Установите xTask в NULL для очистки состояния оповещения для вызывающей задачи. Для получения дескриптора задачи создайте её с использованием xTaskCreate(), и используйте параметр pxCreatedTask, либо создайте задачу с использованием xTaskCreateStatic() и сохраните её возвращаемое значение, либо используйте имя задачи в вызове xTaskGetHandle().

uxIndexToClear: индекс в массиве значений оповещения целевой задачи для применяемого действия. Например, установка uxIndexToClear в 1 очистит состояние оповещение по индексу 1 в массиве. Параметр uxIndexToClear должен быть меньше значения опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У ulTaskNotifyStateClear() нет такого параметра, и она всегда работает со значением оповещения по индексу 0.

uint32_t ulTaskGenericNotifyValueClear (TaskHandle_t xTask,
                                        UBaseType_t uxIndexToClear,
                                        uint32_t ulBitsToClear);

Чтобы эта функция была доступна, опция configUSE_TASK_NOTIFICATIONS должна быть установлена в 1. Подробно про оповещения задач см. [10].

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

ulTaskNotifyValueClearIndexed() очистит биты в значении оповещения массива задачи (задача указывается параметром xTask), заданные битовой маской ulBitsToClear. Значение оповещения в массиве указывается индексом uxIndexToClear.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. ulTaskNotifyValueClear() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов ulTaskNotifyValueClear() эквивалентен вызову ulTaskNotifyValueClearIndexed() с параметром uxIndexToClear, установленным в 0.

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

Параметры

xTask: дескриптор задачи RTOS, для которой очищаются биты в одном из её значений оповещения. Установите xTask в NULL для очистки бит в значении оповещения вызывающей задачи. Для получения дескриптора задачи создайте её с использованием xTaskCreate(), и используйте параметр pxCreatedTask, либо создайте задачу с использованием xTaskCreateStatic() и сохраните её возвращаемое значение, либо используйте имя задачи в вызове xTaskGetHandle().

uxIndexToClear: индекс в массиве значений оповещения целевой задачи, где биты очищаются. Параметр uxIndexToClear должен быть меньше значения опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У ulTaskNotifyValueClear() нет такого параметра, и она всегда работает со значением оповещения по индексу 0.

ulBitsToClear: битовая маска для тех бит, которые должны быть очищены в значении оповещения задачи xTask. Установка бита в 1 приведет к очистке соответствующего бита в значении оповещения задачи. Установка ulBitsToClear в 0xffffffff (UINT_MAX на 32-битной архитектуре) очистит значение оповещения в 0. Установка ulBitsToClear в 0 приведет к запросу значения оповещения задачи без очистки его бит.

void vTaskSetTimeOutState (TimeOut_t* const pxTimeOut) PRIVILEGED_FUNCTION;

Захватывает текущее время для будущего использования совместно с xTaskCheckForTimeOut().

Параметры

pxTimeOut: указатель на объект таймаута, в который будет захвачено текущее время. Захваченное время включает счетчик тика и количество раз, когда счетчик тиков переполнялся с момента первой загрузки системы.

BaseType_t xTaskCheckForTimeOut (TimeOut_t *const pxTimeOut,
                                 TickType_t *const pxTicksToWait);

Определяет, прошло ли pxTicksToWait тиков с момента времени, которое было захвачено с использованием вызова vTaskSetTimeOutState(). Захваченное время включает счетчик тиков и количество переполнения счетчика тиков. Подробное описание функции xTaskCheckForTimeOut см. в документации [11].

Возвратит pdTRUE, если произошел таймаут, иначе вернет pdFALSE и pxTicksToWait обновится, чтобы отразить количество оставшихся тиков.

Параметры

pxTimeOut: состояние времени, которое было ранее захвачено с помощью vTaskSetTimeOutState. Если таймаут еще не произошел, то это значение по этому указателю обновится, чтобы отразить текущий статус таймаута.

pxTicksToWait: количество тиков для проверки таймаута. Например, если pxTicksToWait тиков передано с момента последнего обновления pxTimeOut (либо с помощью vTaskSetTimeOutState(), либо с помощью xTaskCheckForTimeOut()), то произойдет таймаут. Если таймаут не произошел, то pxTicksToWait обновится, чтобы отразить оставшееся количество тиков.

BaseType_t xTaskCatchUpTicks (TickType_t xTicksToCatchUp) PRIVILEGED_FUNCTION;

Функция корректирует значение счетчика тиков после того, как код приложение удерживает отключенными прерывания в течение длительного времени, что приводит к пропуску обработки прерывания тиков.

Эта функция подобна vTaskStepTick(), однако, в отличие от vTaskStepTick(), функция xTaskCatchUpTicks() может переместить счетчик тиков вперед за время, на котором задача должна быть выведена из состояния блокировки (состояния Blocked). Это значит, что задачи могут быть выведены из состояния блокировки при перемещении счетчика тиков.

Функция вернет pdTRUE, если перемещение счетчика тиков вперед приведет к выходу задачи из состояния блокировки и будет выполнено переключение контекста. Иначе будет возвращено pdFALSE.

Параметры

xTicksToCatchUp: количество прерываний тиков, которое было пропущено из-за запрета прерываний. Это значение не вычисляется автоматически, так что оно должно быть вычислено вручную разработчиком приложения.

[Макросы]

tskKERNEL_VERSION_NUMBER

tskKERNEL_VERSION_MAJOR

tskKERNEL_VERSION_MINOR

tskKERNEL_VERSION_BUILD

tskMPU_REGION_READ_ONLY

tskMPU_REGION_READ_WRITE

tskMPU_REGION_EXECUTE_NEVER

tskMPU_REGION_NORMAL_MEMORY

tskMPU_REGION_DEVICE_MEMORY

tskDEFAULT_INDEX_TO_NOTIFY

tskNO_AFFINITY

tskIDLE_PRIORITY Определяет приоритет, используемый задачей ожидания (idle task). Это значение менять не следует.

taskYIELD() макрос для принудительного переключения контекста.

taskENTER_CRITICAL() макрос для пометки начала критического региона кода. В критическом регионе коде не может произойти вытесняющее (preemptive) переключение контекста.

Примечание: taskENTER_CRITICAL/taskEXIT_CRITICAL может привести к изменению стека (в зависимости от реализации порта) поэтому следует использовать с осторожностью!

taskENTER_CRITICAL_FROM_ISR()

taskENTER_CRITICAL_ISR()

taskEXIT_CRITICAL() макрос для пометки завершения критического региона кода. В критическом регионе коде не может произойти вытесняющее (preemptive) переключение контекста.

Примечание: taskENTER_CRITICAL/taskEXIT_CRITICAL может привести к изменению стека (в зависимости от реализации порта) поэтому следует использовать с осторожностью!

taskEXIT_CRITICAL_FROM_ISR(x)

taskEXIT_CRITICAL_ISR()

taskDISABLE_INTERRUPTS() макрос для запрета всех маскируемых прерываний.

taskENABLE_INTERRUPTS() макрос для разрешения прерываний MCU.

taskSCHEDULER_SUSPENDED

taskSCHEDULER_NOT_STARTED

taskSCHEDULER_RUNNING

vTaskDelayUntil (pxPreviousWakeTime, xTimeIncrement)

xTaskNotify (xTaskToNotify, ulValue, eAction)

xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction)

xTaskNotifyAndQuery (xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue)

Подробное описание оповещений задач см. в документации [10].

xTaskNotifyAndQueryIndexed() выполняет то же действие, что и xTaskNotifyIndexed(), однако с дополнением, что он также возвратит предыдущее значение задачи-субъекта (значение оповещения в момент вызова функции, а не при возврате из функции) в дополнительном параметре pulPreviousNotifyValue.

xTaskNotifyAndQuery() выполняет то же действие, что и xTaskNotify(), однако с дополнением, что также возвратит предыдущее значение оповещения задачи-субъекта (значение оповещения в момент вызова функции, а не при возврате из функции) в дополнительном параметре pulPreviousNotifyValue.

xTaskNotifyAndQueryIndexed (xTaskToNotify,
                            uxIndexToNotify,
                            ulValue,
                            eAction,
                            pulPreviousNotifyValue)

xTaskNotifyFromISR (xTaskToNotify,
                    ulValue,
                    eAction,
                    pxHigherPriorityTaskWoken)

xTaskNotifyIndexedFromISR (xTaskToNotify,
                           uxIndexToNotify,
                           ulValue,
                           eAction,
                           pxHigherPriorityTaskWoken)

xTaskNotifyAndQueryIndexedFromISR (xTaskToNotify,
                                   uxIndexToNotify,
                                   ulValue,
                                   eAction,
                                   pulPreviousNotificationValue,
                                   pxHigherPriorityTaskWoken)

Подробное описание оповещений задач см. в документации [10].

xTaskNotifyAndQueryIndexedFromISR() выполняет то же действие, что и xTaskNotifyIndexedFromISR() с дополнением, что также возвратит предыдущее значение оповещения задачи-субъекта (значение оповещения в момент вызова функции, а не при выходе из функции) в дополнительном параметре pulPreviousNotifyValue.

xTaskNotifyAndQueryFromISR() выполняет то же действие, что и xTaskNotifyFromISR()  с дополнением, что также возвратит предыдущее значение оповещения задачи-субъекта (значение оповещения в момент вызова функции, а не при выходе из функции) в дополнительном параметре pulPreviousNotifyValue.

xTaskNotifyAndQueryFromISR (xTaskToNotify,
                            ulValue,
                            eAction,
                            pulPreviousNotificationValue,
                            pxHigherPriorityTaskWoken)

xTaskNotifyWait (ulBitsToClearOnEntry,
                 ulBitsToClearOnExit,
                 pulNotificationValue,
                 xTicksToWait)

xTaskNotifyWaitIndexed (uxIndexToWaitOn,
                        ulBitsToClearOnEntry,
                        ulBitsToClearOnExit,
                        pulNotificationValue,
                        xTicksToWait)

xTaskNotifyGive (xTaskToNotify)

Отправляет прямое оповещение в массив значений оповещения целевой задачи по определенному индексу, что работает подобно семафору со счетчиком. Подробнее про оповещения задач см. документацию [10].

Чтобы этот макрос был доступен, опция configUSE_TASK_NOTIFICATIONS должна быть определена как 1.

У каждой задачи есть приватный массив значений оповещения ("notification values", или ‘notifications’), каждое значение это 32-bit битное беззнаковое целое (uint32_t). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES устанавливает количество индексов в этом массиве, и по умолчанию, если она не определена, принимается равной 1 (для обратной совместимости). До версии FreeRTOS V10.4.0 было только одно значение оповещения на задачу.

События (events) могут быть отправлены от одной задачи к другой с использованием промежуточного объекта. Примеры таких объектов - очереди, семафоры, мьютексы и группы событий (event groups). Оповещения задачи (task notifications) это метод прямой отправки события в задачу без необходимости применения такого промежуточного объекта.

Оповещение (уведомление, notification), отправленное в задачу, может опционально выполнить действие (action), такое как обновление, перезапись или инкремент одного из значений оповещения задачи. Таким образом, оповещения задачи (task notifications) могут использоваться для отправки данных в задачу, или в качестве легких и быстрых двоичных семафоров или семафоров со счетчиком.

xTaskNotifyGiveIndexed() это макрос, облегчающий использование оповещений, когда они используются как облегченная и быстрая альтернатива двоичным семафорам или семафорам со счетчиком. Реальные семафоры FreeRTOS выдаются с использованием API-функции xSemaphoreGive(), и вместо этого эквивалентный функционал достигается отправкой оповещения задаче с помощью xTaskNotifyGiveIndexed().

Когда оповещения задачи используются в качестве эквивалента двоичного семафора или семафора со счетчиком, оповещаемая задача должна ждать оповещения с помощью вызова API-функции ulTaskNotificationTakeIndexed() вместо API-функции xTaskNotifyWaitIndexed().

Обратите внимание, что каждое оповещение в массиве работает независимо - задача за один раз может заблокироваться только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным в массив по другому индексу.

Информация для обратной совместимости: до версии FreeRTOS V10.4.0 у каждой задачи было только одно значение оповещения ("notification value"), и все API-функции оповещения работали на этом значении. Замена одного значения оповещения на массив таких значений потребовала нового напора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. xTaskNotifyGive() это оригинальная API-функция, и она осталась для обратной совместимости, работая со значением оповещения в массиве с индексом 0. Вызов xTaskNotifyGive() эквивалентен вызову xTaskNotifyGiveIndexed() с параметром uxIndexToNotify, установленным в 0.

Возвращаемое значение: макрос xTaskNotifyGive() делает вызов xTaskNotify() с параметром eAction, установленным в значение eIncrement - поэтому всегда будет возвращено значение pdPASS.

Параметры

xTaskToNotify: дескриптор оповещаемой задачи. Дескриптор задачи может быть возвращен из вызова API-функции xTaskCreate() при создании задачи, и дескриптор текущей работающей задачи может быть получен вызовом xTaskGetCurrentTaskHandle().

uxIndexToNotify: индекс, по которому значение оповещения отправляется в массив значений оповещения целевой задачи. Параметр uxIndexToNotify должне быть меньше значения опции configTASK_NOTIFICATION_ARRAY_ENTRIES. У макроса xTaskNotifyGive() нет этого параметра, и он всегда отправляет оповещение по индексу 0.

xTaskNotifyGiveIndexed (xTaskToNotify, uxIndexToNotify)

vTaskNotifyGiveFromISR (xTaskToNotify, pxHigherPriorityTaskWoken)

vTaskNotifyGiveIndexedFromISR (xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken)

ulTaskNotifyTake (xClearCountOnExit, xTicksToWait)

ulTaskNotifyTakeIndexed (uxIndexToWaitOn, xClearCountOnExit, xTicksToWait)

xTaskNotifyStateClear (xTask)

xTaskNotifyStateClearIndexed (xTask, uxIndexToClear)

ulTaskNotifyValueClear (xTask, ulBitsToClear)

ulTaskNotifyValueClearIndexed (xTask, uxIndexToClear, ulBitsToClear)

[Определения типов]

typedefstruct tskTaskControlBlock *TaskHandle_t

typedefBaseType_t (*TaskHookFunction_t)(void *)

typedefvoid (*TlsDeleteCallbackFunction_t)(int, void *) прототип callback-функции удаления указателя на локальное хранилище.

[Перечисления]

enum eTaskState значения состояния задачи, возвращаемые eTaskGetState.

Значения:

eRunning = 0
eReady
eBlocked
eSuspended
eDeleted
eInvalid

enum eNotifyAction

Значения:

eNoAction = 0
eSetBits
eIncrement
eSetValueWithOverwrite
eSetValueWithoutOverwrite

enum eSleepModeStatus возможные возвращаемые значения для eTaskConfirmSleepModeStatus().

Значения:

eAbortSleep = 0
eStandardSleep
eNoTasksWaitingTimeout

[Словарик]

IPC Inter-Processor Call, организация взаимодействия между процессорами (задачами). Внимание: в данном контексте IPC не означает Inter-Process Communication, что можно обнаружить в других операционных системах.

ISR Interrupt Service Routine, обработчик прерывания.

MCU MicroController Unit, микроконтроллер.

MPU Memory Protection Unit, аппаратный блок защиты памяти.

SMP Symmetric Multiprocessing, параллельное выполнение кода с помощью нескольких процессорных ядер.

TCB Task Control Block, структура для хранения служебной информации задачи.

[Ссылки]

1. ESP-IDF System API FreeRTOS site:docs.espressif.com.
2ESP-IDF FreeRTOS SMP.
3. ESP32: функции поддержки FreeRTOS.
4. Установка среды разработки ESP-IDF для ESP32.
5. Конфигурация проекта ESP-IDF.
6. ESP-IDF FreeRTOS SMP.
7. Hook Functions site:freertos.org.
8. configSUPPORT_STATIC_ALLOCATION site:freertos.org.
9FreeRTOS: как получить информацию о загрузке процессора.
10. FreeRTOS: оповещения задач.
11. FreeRTOS: функция xTaskCheckForTimeOut.
12. FreeRTOS: практическое применение, часть 1 (управление задачами).
13ESP32 Inter-Processor Call.
14FreeRTOS: управление памятью.

 

Добавить комментарий


Защитный код
Обновить

Top of Page