Embedded HandbookApps
All sections › Appendices
STM32F103, STM32F407 · level reference · 11 min read
Open in the interactive handbook

Appendix D. FreeRTOS API cheat sheet

Signatures on one page, without explanations. Explanations and calling rules are in section 34, the mechanics in sections 23–33. All names are built with kernel 10.5.1 in _verify/rtos_macros.c.

Notation: ticks is 0, pdMS_TO_TICKS(n) or portMAX_DELAY; *woken is a BaseType_t, initialize it to pdFALSE, afterwards call portYIELD_FROM_ISR(woken).

Cheat sheet objects: what creates them, what you use from a task and what is allowed from an interrupt


D.1 Tasks

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 Task notifications

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 Queues

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 Semaphores and mutexes

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 Software timers

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 Event groups

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 Stream and message buffers

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 Heap

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 Hooks you write yourself

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 Constants

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 Minimal FreeRTOSConfig.h

Units of the FreeRTOSConfig.h lines from D.11: 72000000 Hz and a 1000 Hz tick give 72000 SysTick clock cycles per tick, stacks of 128 and 256 are in words, that is, 512 and 1024 bytes, the heap is 10 × 1024 = 10240 bytes, task priorities 0…4, 10 commands in the timer daemon queue; logical interrupt priorities 15 and 5 are shifted by 8 − 4 = 4 bits and become 0xF0 and 0x50

Three lines, configUSE_IDLE_HOOK, configUSE_TICK_HOOK and configUSE_16_BIT_TICKS, are always required by the kernel: without them FreeRTOS.h stops the build with #error Missing definition. The other additions enable what D.1–D.6 use: the task snapshot (configUSE_TRACE_FACILITY), the queue registry, setting and reading the priority, the task state, the mutex holder and the deferred call through the timer daemon, which xEventGroupSetBitsFromISR relies on.

#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

The last three lines hand SVC, PendSV and SysTick over to the kernel (section 24.4, step 1), and in this form they suit a register-level project. In a HAL project the stubs of these handlers already exist in stm32f1xx_it.c (on F4, stm32f4xx_it.c), and you remove them. But the SysTick_Handler stub contains HAL_IncTick: without it HAL_Delay and the HAL timeouts stop. So the HAL tick is moved to a free timer with your own HAL_InitTick. A template comes with HAL itself: stm32f1xx_hal_timebase_tim_template.c uses TIM2, and the same file on F4 uses TIM6. The ST examples with FreeRTOS do the same, except that the third line there is commented out and their own SysTick_Handler calls the kernel handler.

Open in the interactive handbook