You are here

FreeRTOS ИПП: xTaskCreateRestrictedStatic()

Перевод может содержать ошибки. Читайте первоисточник: FreeRTOS Task Creation API Functions - xTaskCreateRestrictedStatic()

Назад: [xTaskCreateStatic()] Вверх: [ИПП: Создание задач] Вперёд: [vTaskDelete()]

Начиная с версии FreeRTOS V10.0.0

 

xTaskCreateRestrictedStatic()

FreeRTOS-MPU Specific Functions

Функция объявляется в файле task.h

BaseType_t xTaskCreateRestrictedStatic(   TaskParameters_t *pxTaskDefinition,
                                          TaskHandle_t     *pxCreatedTask
                                      );

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

Настройка configSUPPORT_STATIC_ALLOCATION в файле FreeRTOSConfig.h должна быть установлена в 1. Без этого функция недоступна.

Реализация задач во FreeRTOS требует два блока памяти для каждой задачи. Первый блок используется для хранения структуры данных задачи. Второй блок используется в качестве стека задачи. Если задача созаётся с помощью вызова xTaskCreateRestricted(), то память для стека задачи предоставляется разработчиком приложения, а память для структуры данных задачи автоматически выделяется из кучи FreeRTOS. Если же задача создаётся вызовом xTaskCreateRestrictedStatic(), то разработчик приложения должен также предоставить память для структуры данных задачи. Поэтому xTaskCreateRestrictedStatic() позволяет создавать задачи, используя защищённую память, без использования динамического выделения памяти.

Функция xTaskCreateRestrictedStatic() предназначена для использования с FreeRTOS-MPU. Примеры с исчерпывающе документированными примерами имеются в демонстрационных приложениях для похожей функции xTaskCreateRestricted().

Параметры:

pxTaskDefinition Указатель на структуру, определяющую параметры создания задачи. Описание структуры приведено ниже на этой странице.
pxCreatedTask Используется для возврата дескриптора, с помощью которого можно в дальнейшем ссылаться на созданную задачу.

Возвращаемое значение:

Если задача успешно создана и добавлена в список задач, готовых к выполнению, возвращается значение pdPASS. В остальных случаях возвращается код ошибки, описание которого можно найти в файле projdefs.h.

Подробнее о структурах:

Задачи, которые включают поддержку MPU, требуют предоставления ещё большего количества параметров для создания, чем те, которые эту поддержку не используют. Передача каждого параметра в xTaskCreateRestrictedStatic() отдельно была бы чересчур громоздкой, поэтому вместо этого используется структура TaskParameters_t для статической настройки параметров во время компиляции. Структура определяется в файле task.h следующим образом:

typedef struct xTASK_PARAMETERS
{
    TaskFunction_t            pvTaskCode;
    const signed char        * const pcName;
    unsigned short            usStackDepth;
    void                      *pvParameters;
    UBaseType_t               uxPriority;
    portSTACK_TYPE            *puxStackBuffer;
    MemoryRegion_t            xRegions[ portNUM_CONFIGURABLE_REGIONS ];
    #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
        StaticTask_t          * const pxTaskBuffer;
    #endif
} TaskParameters_t;

/* ...где MemoryRegion_t определён как: */

typedef struct xMEMORY_REGION
{
    void           *pvBaseAddress;
    unsigned long  ulLengthInBytes;
    unsigned long  ulParameters;
} MemoryRegion_t;

Ниже приведено описание каждого члена структуры:

pvTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority
Назначение этих параметров совпадает с таковыми функции xTaskCreate(). В частности, uxPriority используется для указания как приоритета задачи, так и режима выполнения задачи. Например, для создания задачи, выполняющейся в пользовательском режиме с приоритетом 2, просто установите uxPriority равным 2, а для создания задачи, выполняющейся в привилегированном режиме, значение должно быть равно ( 2 | portPRIVILEGE_BIT ).
puxStackBuffer Каждый раз, когда происходит переключение на задачу, MPU динамически переконфигурируется для указания региона, который предоставляет задаче доступ к своему стеку для чтения и записи. Области регионов MPU должны соответствовать определённым требованиям - в частности, размер и выравнивание всех таких регионов должны быть равны одной и той же степени двойки.

Стандартные порты FreeRTOS использует pvPortMalloc() для выделения нового стека каждый раз, когда создаётся задача. Предоставление реализации pvPortMalloc(), которая позаботится о требованиях к выравниванию данных MPU, было бы возможно, но также было бы сложным и неэффективным с точки зрения использования ОЗУ. Чтобы устранить необходимость в этой сложности, FreeRTOS-MPU позволяет статически объявлять стеки во время компиляции. Это позволяет управлять выравниванием с помощью расширений компилятора, а компоновщиком управлять эффективностью использования ОЗУ. Например, при использовании GCC стек можно объявить и правильно выровнять с помощью следующего кода:
char cTaskStack[ 1024 ] __attribute__((align(1024));​

puxStackBuffer обычно устанавливается на адрес статически объявленного стека. В качестве альтернативы puxStackBuffer может быть установлен в NULL — в этом случае pvPortMallocAligned() будет вызываться для выделения стека задач, и автор приложения несет ответственность за обеспечение реализации pvPortMallocAligned(), отвечающей требованиям выравнивания MPU.

xRegions xRegions — это массив структур MemoryRegion_t, каждая из которых определяет одну определяемую пользователем область памяти для использования создаваемой задачей. Порт ARM Cortex-M3 FreeRTOS-MPU определяет portNUM_CONFIGURABLE_REGIONS равным 3.

Члены pvBaseAddress и ulLengthInBytes говорят сами за себя как начало области памяти и длина области памяти соответственно.
ulParameters определяет, как задаче разрешен доступ к области памяти, и может принимать побитовое ИЛИ следующих значений:

portMPU_REGION_READ_WRITE
portMPU_REGION_PRIVILEGED_READ_ONLY
portMPU_REGION_READ_ONLY
portMPU_REGION_PRIVILEGED_READ_WRITE
portMPU_REGION_CACHEABLE_BUFFERABLE
portMPU_REGION_EXECUTE_NEVER

pxTaskBuffer Должен указывать на переменную типа StaticTask_t. Переменная будет использоваться для хранения структур данных новой задачи, поэтому она должна быть постоянной (не объявляться в стеке функции).

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

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

/* Создайте структуру TaskParameters_t, определяющую создаваемую задачу.
* Переменная StaticTask_t включается в структуру только тогда, когда
* configSUPPORT_STATIC_ALLOCATION имеет значение 1.
* Макрос PRIVILEGED_DATA может использоваться для принудительного
* размещения переменной в привилегированную область данных ядра FreeRTOS. */

static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
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 }
    }
    
    &xTaskBuffer; /* Хранит структуру данных задачи. */
};

int main( void )
{
    TaskHandle_t xHandle;
    
    /* Создаём задачу из константной структуры, определённой выше. Хэндлер задачи
    * требуется (второй параметр должен быть не NULL), но в данном примере целью
    * является просто демонстрация, поэтому фактически не используется. */
    xTaskCreateRestricted( &xCheckTaskParameters, &xHandle );
    
    /* Запускаем планировщик. */
    vTaskStartScheduler();
    
    /* Сюда попадаем только в случае, если не хватило памяти для создания задачи простоя и/или задачи таймера. */
    for( ;; );
}
Hobby's category: