Embedded HandbookПриложения
Все разделы › Приложения
STM32F103, STM32F407 · уровень справочник · 11 мин чтения
Открыть в интерактивном справочнике

Приложение D. Шпаргалка FreeRTOS API

Сигнатуры — одной страницей, без пояснений. Пояснения и правила вызова — в разделе 34, механика — в разделах 23–33. Все имена собраны с ядром 10.5.1 в _verify/rtos_macros.c.

Обозначения: ticks — 0, pdMS_TO_TICKS(n) или portMAX_DELAY; *woken — BaseType_t, инициализировать pdFALSE, после — portYIELD_FROM_ISR(woken).

Объекты шпаргалки: чем создать, чем пользоваться из задачи и что позволено из прерывания


D.1 Задачи

BaseType_t   xTaskCreate(TaskFunction_t fn, const char *name, uint16_t depthWords,
                         void *arg, UBaseType_t prio, TaskHandle_t *h);
TaskHandle_t xTaskCreateStatic(fn, name, depthWords, arg, prio,
                               StackType_t *stack, StaticTask_t *tcb);
void         vTaskDelete(TaskHandle_t h);                 /* NULL — себя */
void         vTaskStartScheduler(void);                   /* не возвращается */

void         vTaskDelay(TickType_t ticks);                /* от момента вызова */
BaseType_t   xTaskDelayUntil(TickType_t *last, TickType_t period);
TickType_t   xTaskGetTickCount(void);
TickType_t   xTaskGetTickCountFromISR(void);
void         taskYIELD(void);

void         vTaskSuspend(TaskHandle_t h);
void         vTaskResume(TaskHandle_t h);
BaseType_t   xTaskResumeFromISR(TaskHandle_t h);
void         vTaskPrioritySet(TaskHandle_t h, UBaseType_t prio);
UBaseType_t  uxTaskPriorityGet(TaskHandle_t h);
eTaskState   eTaskGetState(TaskHandle_t h);
char        *pcTaskGetName(TaskHandle_t h);
UBaseType_t  uxTaskGetStackHighWaterMark(TaskHandle_t h);  /* в словах */
TaskHandle_t xTaskGetCurrentTaskHandle(void);
BaseType_t   xTaskGetSchedulerState(void);
UBaseType_t  uxTaskGetNumberOfTasks(void);
void         vTaskGetInfo(TaskHandle_t h, TaskStatus_t *st, BaseType_t getStack, eTaskState hint);
UBaseType_t  uxTaskGetSystemState(TaskStatus_t *arr, UBaseType_t size, uint32_t *totalRun);

void         vTaskSuspendAll(void);
BaseType_t   xTaskResumeAll(void);
void         taskENTER_CRITICAL(void);
void         taskEXIT_CRITICAL(void);
UBaseType_t  taskENTER_CRITICAL_FROM_ISR(void);
void         taskEXIT_CRITICAL_FROM_ISR(UBaseType_t saved);
void         portYIELD_FROM_ISR(BaseType_t woken);

D.2 Уведомления задачи

BaseType_t   xTaskNotifyGive(TaskHandle_t h);
void         vTaskNotifyGiveFromISR(TaskHandle_t h, BaseType_t *woken);
uint32_t     ulTaskNotifyTake(BaseType_t clearOnExit, TickType_t ticks);
BaseType_t   xTaskNotify(TaskHandle_t h, uint32_t value, eNotifyAction action);
BaseType_t   xTaskNotifyFromISR(TaskHandle_t h, uint32_t value, eNotifyAction action,
                                BaseType_t *woken);
BaseType_t   xTaskNotifyWait(uint32_t clearOnEntry, uint32_t clearOnExit,
                             uint32_t *value, TickType_t ticks);
BaseType_t   xTaskNotifyStateClear(TaskHandle_t h);
uint32_t     ulTaskNotifyValueClear(TaskHandle_t h, uint32_t mask);
/* eNotifyAction: eNoAction, eSetBits, eIncrement,
                  eSetValueWithOverwrite, eSetValueWithoutOverwrite */

D.3 Очереди

QueueHandle_t xQueueCreate(UBaseType_t len, UBaseType_t itemSize);
QueueHandle_t xQueueCreateStatic(len, itemSize, uint8_t *storage, StaticQueue_t *buf);
BaseType_t    xQueueSend(QueueHandle_t q, const void *item, TickType_t ticks);
BaseType_t    xQueueSendToBack(q, item, ticks);
BaseType_t    xQueueSendToFront(q, item, ticks);
BaseType_t    xQueueOverwrite(q, item);                    /* только len == 1 */
BaseType_t    xQueueReceive(q, void *item, ticks);
BaseType_t    xQueuePeek(q, void *item, ticks);
BaseType_t    xQueueSendFromISR(q, item, BaseType_t *woken);
BaseType_t    xQueueSendToBackFromISR(q, item, woken);
BaseType_t    xQueueSendToFrontFromISR(q, item, woken);
BaseType_t    xQueueOverwriteFromISR(q, item, woken);
BaseType_t    xQueueReceiveFromISR(q, item, woken);
BaseType_t    xQueuePeekFromISR(q, item);
UBaseType_t   uxQueueMessagesWaiting(q);
UBaseType_t   uxQueueMessagesWaitingFromISR(q);
UBaseType_t   uxQueueSpacesAvailable(q);
BaseType_t    xQueueIsQueueEmptyFromISR(q);
BaseType_t    xQueueIsQueueFullFromISR(q);
BaseType_t    xQueueReset(q);
void          vQueueDelete(q);
void          vQueueAddToRegistry(q, const char *name);    /* имя для отладчика */

D.4 Семафоры и мьютексы

SemaphoreHandle_t xSemaphoreCreateBinary(void);
SemaphoreHandle_t xSemaphoreCreateBinaryStatic(StaticSemaphore_t *buf);
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t max, UBaseType_t initial);
SemaphoreHandle_t xSemaphoreCreateCountingStatic(max, initial, buf);
SemaphoreHandle_t xSemaphoreCreateMutex(void);
SemaphoreHandle_t xSemaphoreCreateMutexStatic(buf);
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(buf);
BaseType_t        xSemaphoreTake(SemaphoreHandle_t s, TickType_t ticks);
BaseType_t        xSemaphoreTakeFromISR(s, BaseType_t *woken);      /* не мьютекс */
BaseType_t        xSemaphoreGive(s);
BaseType_t        xSemaphoreGiveFromISR(s, woken);                  /* не мьютекс */
BaseType_t        xSemaphoreTakeRecursive(s, ticks);
BaseType_t        xSemaphoreGiveRecursive(s);
UBaseType_t       uxSemaphoreGetCount(s);
TaskHandle_t      xSemaphoreGetMutexHolder(s);   /* INCLUDE_xSemaphoreGetMutexHolder */
void              vSemaphoreDelete(s);

D.5 Программные таймеры

TimerHandle_t xTimerCreate(const char *name, TickType_t period, BaseType_t autoReload,
                           void *id, TimerCallbackFunction_t cb);
TimerHandle_t xTimerCreateStatic(name, period, autoReload, id, cb, StaticTimer_t *buf);
BaseType_t    xTimerStart(TimerHandle_t t, TickType_t ticksToWaitForQueue);
BaseType_t    xTimerStop(t, ticks);
BaseType_t    xTimerReset(t, ticks);
BaseType_t    xTimerChangePeriod(t, TickType_t newPeriod, ticks);   /* запускает */
BaseType_t    xTimerDelete(t, ticks);
BaseType_t    xTimerStartFromISR(t, BaseType_t *woken);
BaseType_t    xTimerStopFromISR(t, woken);
BaseType_t    xTimerResetFromISR(t, woken);
BaseType_t    xTimerChangePeriodFromISR(t, newPeriod, woken);
BaseType_t    xTimerIsTimerActive(t);
TickType_t    xTimerGetPeriod(t);
TickType_t    xTimerGetExpiryTime(t);
void         *pvTimerGetTimerID(t);
void          vTimerSetTimerID(t, void *id);
BaseType_t    xTimerGetReloadMode(t);
void          vTimerSetReloadMode(t, BaseType_t autoReload);
TaskHandle_t  xTimerGetTimerDaemonTaskHandle(void);
BaseType_t    xTimerPendFunctionCall(PendedFunction_t fn, void *arg1, uint32_t arg2, ticks);
BaseType_t    xTimerPendFunctionCallFromISR(fn, arg1, arg2, BaseType_t *woken);
/* обратный вызов: void cb(TimerHandle_t t) — не блокироваться */

D.6 Группы событий

EventGroupHandle_t xEventGroupCreate(void);
EventGroupHandle_t xEventGroupCreateStatic(StaticEventGroup_t *buf);
EventBits_t        xEventGroupSetBits(EventGroupHandle_t eg, EventBits_t bits);
BaseType_t         xEventGroupSetBitsFromISR(eg, bits, BaseType_t *woken);  /* через демона */
EventBits_t        xEventGroupClearBits(eg, bits);
BaseType_t         xEventGroupClearBitsFromISR(eg, bits);
EventBits_t        xEventGroupGetBits(eg);
EventBits_t        xEventGroupGetBitsFromISR(eg);
EventBits_t        xEventGroupWaitBits(eg, EventBits_t bits, BaseType_t clearOnExit,
                                       BaseType_t waitAll, TickType_t ticks);
EventBits_t        xEventGroupSync(eg, EventBits_t set, EventBits_t waitFor, ticks);
void               vEventGroupDelete(eg);
/* биты 0..23; возвращаемое значение — группа в момент пробуждения */

D.7 Буферы потоков и сообщений

StreamBufferHandle_t  xStreamBufferCreate(size_t bytes, size_t trigger);
StreamBufferHandle_t  xStreamBufferCreateStatic(bytes, trigger, uint8_t *storage /* bytes+1 */,
                                                StaticStreamBuffer_t *buf);
size_t  xStreamBufferSend(StreamBufferHandle_t sb, const void *data, size_t len, TickType_t ticks);
size_t  xStreamBufferSendFromISR(sb, data, len, BaseType_t *woken);
size_t  xStreamBufferReceive(sb, void *data, size_t max, ticks);
size_t  xStreamBufferReceiveFromISR(sb, data, max, woken);
size_t  xStreamBufferBytesAvailable(sb);
size_t  xStreamBufferSpacesAvailable(sb);
BaseType_t xStreamBufferIsEmpty(sb);
BaseType_t xStreamBufferIsFull(sb);
BaseType_t xStreamBufferSetTriggerLevel(sb, size_t trigger);
BaseType_t xStreamBufferReset(sb);
void       vStreamBufferDelete(sb);

MessageBufferHandle_t xMessageBufferCreate(size_t bytes);
MessageBufferHandle_t xMessageBufferCreateStatic(bytes, uint8_t *storage, StaticMessageBuffer_t *buf);
size_t  xMessageBufferSend(MessageBufferHandle_t mb, const void *data, size_t len, ticks);
size_t  xMessageBufferSendFromISR(mb, data, len, woken);
size_t  xMessageBufferReceive(mb, void *data, size_t max, ticks);   /* max ≥ самого длинного */
size_t  xMessageBufferReceiveFromISR(mb, data, max, woken);
size_t  xMessageBufferSpaceAvailable(mb);
BaseType_t xMessageBufferIsEmpty(mb);
BaseType_t xMessageBufferIsFull(mb);
BaseType_t xMessageBufferReset(mb);
void       vMessageBufferDelete(mb);

D.8 Куча

void   *pvPortMalloc(size_t bytes);
void    vPortFree(void *p);
size_t  xPortGetFreeHeapSize(void);
size_t  xPortGetMinimumEverFreeHeapSize(void);       /* heap_4, heap_5 */
void    vPortGetHeapStats(HeapStats_t *stats);        /* heap_4, heap_5 */
void    vPortDefineHeapRegions(const HeapRegion_t *regions);   /* heap_5, по возрастанию */

D.9 Ловушки — пишете вы

void vApplicationStackOverflowHook(TaskHandle_t task, char *name);
void vApplicationMallocFailedHook(void);
void vApplicationIdleHook(void);                      /* не блокироваться */
void vApplicationTickHook(void);                      /* только FromISR */
void vApplicationGetIdleTaskMemory(StaticTask_t **tcb, StackType_t **stack, uint32_t *size);
void vApplicationGetTimerTaskMemory(StaticTask_t **tcb, StackType_t **stack, uint32_t *size);

D.10 Константы

pdMS_TO_TICKS(ms)      portTICK_PERIOD_MS      portMAX_DELAY
pdTRUE  pdFALSE        pdPASS  pdFAIL          errQUEUE_FULL == errQUEUE_EMPTY == 0
tskIDLE_PRIORITY == 0  configMAX_PRIORITIES    configMINIMAL_STACK_SIZE  /* слова */

D.11 Минимальный FreeRTOSConfig.h

Единицы строк FreeRTOSConfig.h из D.11: 72 000 000 Гц и тик 1000 Гц дают 72 000 тактов SysTick на тик, стеки 128 и 256 — в словах, то есть 512 и 1024 байта, куча 10 × 1024 = 10 240 байт, приоритеты задач 0…4, 10 команд в очереди демона таймеров; логические приоритеты прерываний 15 и 5 сдвигаются на 8 − 4 = 4 бита и становятся 0xF0 и 0x50

Три строки — configUSE_IDLE_HOOK, configUSE_TICK_HOOK и configUSE_16_BIT_TICKS — ядро требует всегда: без них FreeRTOS.h останавливает сборку с #error Missing definition. Остальные добавки включают то, чем пользуются D.1–D.6: снимок задач (configUSE_TRACE_FACILITY), реестр очередей, смену и чтение приоритета, состояние задачи, владельца мьютекса и отложенный вызов через демона таймеров — на нём стоит xEventGroupSetBitsFromISR.

#define configUSE_PREEMPTION                1
#define configUSE_IDLE_HOOK                 0
#define configUSE_TICK_HOOK                 0
#define configUSE_16_BIT_TICKS              0
#define configCPU_CLOCK_HZ                  72000000u
#define configTICK_RATE_HZ                  1000u
#define configMAX_PRIORITIES                5
#define configMINIMAL_STACK_SIZE            128
#define configTOTAL_HEAP_SIZE               (10 * 1024)
#define configUSE_MUTEXES                   1
#define configUSE_RECURSIVE_MUTEXES         1
#define configUSE_COUNTING_SEMAPHORES       1
#define configUSE_TIMERS                    1
#define configTIMER_TASK_PRIORITY           (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH            10
#define configTIMER_TASK_STACK_DEPTH        256
#define configSUPPORT_STATIC_ALLOCATION     1
#define configSUPPORT_DYNAMIC_ALLOCATION    1
#define configCHECK_FOR_STACK_OVERFLOW      2
#define configUSE_MALLOC_FAILED_HOOK        1
#define configUSE_TRACE_FACILITY            1
#define configQUEUE_REGISTRY_SIZE           8
#define configPRIO_BITS                     4
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY  5
#define configKERNEL_INTERRUPT_PRIORITY     (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configASSERT(x) if ((x) == 0) { taskDISABLE_INTERRUPTS(); for (;;); }
#define INCLUDE_vTaskDelay                  1
#define INCLUDE_xTaskDelayUntil             1
#define INCLUDE_vTaskDelete                 1
#define INCLUDE_vTaskSuspend                1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetSchedulerState      1
#define INCLUDE_vTaskPrioritySet            1
#define INCLUDE_uxTaskPriorityGet           1
#define INCLUDE_eTaskGetState               1
#define INCLUDE_xSemaphoreGetMutexHolder    1
#define INCLUDE_xTimerPendFunctionCall      1
#define vPortSVCHandler     SVC_Handler
#define xPortPendSVHandler  PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

Три последние строки отдают ядру SVC, PendSV и SysTick (раздел 24.4, шаг 1) и в таком виде годятся для проекта на регистрах. В проекте с HAL заготовки этих обработчиков уже лежат в stm32f1xx_it.c (у F4 — stm32f4xx_it.c), и их убирают. Но в заготовке SysTick_Handler стоит HAL_IncTick: без него встанут HAL_Delay и тайм-ауты HAL. Поэтому тик HAL переводят на свободный таймер своей HAL_InitTick. Образец лежит в самом HAL: stm32f1xx_hal_timebase_tim_template.c на TIM2, у F4 такой же файл — на TIM6. В примерах ST с FreeRTOS сделано так же, только третья строка там закомментирована, а свой SysTick_Handler вызывает обработчик ядра.

Открыть в интерактивном справочнике