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).
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
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.