# FreeRTOS（附加功能）

[English]

ESP-IDF 为 FreeRTOS 提供了多种附加功能。这些附加功能适用于 ESP-IDF 支持的所有 FreeRTOS 实现，即 ESP-IDF FreeRTOS 和 Amazon SMP FreeRTOS。本文档介绍了这些附加功能，内容包括以下几个部分：

## 概述

ESP-IDF 为 FreeRTOS 提供了以下附加功能：

- 环形 buffer：FIFO 缓冲区，支持任意长度的数据项。

- ESP-IDF tick 钩子和 idle 钩子：ESP-IDF 提供了多个自定义的 tick 钩子和 idle 钩子，相较于 FreeRTOS，支持的钩子数量更多且更灵活。

- 线程本地存储指针 (TLSP) 删除回调：当一个任务被删除时，TLSP 删除回调会自动运行，从而自动清理 TLSP。

- IDF 附加 API：专用于 ESP-IDF 的附加函数，用于增强 FreeRTOS 的功能。

- 组件专用功能：目前只添加了一个专用于组件的功能，即 `ORIG_INCLUDE_PATH`。

## 环形 buffer

FreeRTOS 提供了流 buffer 和消息 buffer，作为在任务和 ISR 之间发送任意大小数据的主要机制。然而，FreeRTOS 流 buffer 和消息 buffer 具有以下限制：

- 仅支持单一的发送者和单一的接收者

- 数据通过复制的方式进行传递

- 无法为延迟发送（即发送获取）预留 buffer 空间

为此，ESP-IDF 提供了一个单独的环形 buffer 来解决上述问题。

ESP-IDF 环形 buffer 是一个典型的 FIFO buffer，支持任意大小的数据项。在数据项大小可变的情况下，环形 buffer 比 FreeRTOS 队列更节约内存，可以替代 FreeRTOS 队列使用。环形 buffer 的容量不是由可以存储的数据项数量衡量的，而是由用于存储数据项的内存量来衡量的。

环形 buffer 提供了 API 来发送数据项，或为环形 buffer 中的数据项分配空间，以便进行手动填充。为提高效率， 数据项都通过引用的方式从环形 buffer 中检索出来。因此，所有检索出的数据项也 必须 通过 `vRingbufferReturnItem()` 或 `vRingbufferReturnItemFromISR()` 返回到环形 buffer，以便将其从环形 buffer 中完全移除。

环形 buffer 分为以下三种类型：

不可分割 buffer：确保将一个数据项存储在连续的内存中，并且在任何情况下都不会尝试分割数据项。当数据项必须占用连续的内存时，请使用不可分割 buffer。 仅不可分割 buffer 允许为延迟发送保留缓冲空间。 更多信息请参考函数 `xRingbufferSendAcquire()` 和 `xRingbufferSendComplete()` 的文档。

可分割 buffer：当数据项在 buffer 末尾绕回时，如果 buffer 头部和尾部的总空间足够，则支持将一个数据项分成两部分进行存储。可分割 buffer 比不可分割 buffer 更节省内存，但在检索时可能会返回数据项的两个部分。

字节 buffer：不将数据存储为单独的数据项。所有数据都存储为字节序列，每次可以发送或检索任意大小的字节。当不需要单独维护数据项时，推荐使用字节 buffer，例如字节流。

备注

不可分割 buffer 和可分割 buffer 在 32 位对齐地址上存储数据项。因此，在检索一个数据项时，数据项指针一定也是 32 位对齐的。这在向 DMA 发送数据时非常有用。

备注

存储在不可分割或可分割 buffer 中的每个数据项 需要额外的 8 字节用于标头。数据项大小会向上取整为 32 位对齐大小，即 4 字节的倍数，实际的数据项大小则记录在标头中。不可分割和可分割 buffer 的大小在创建时也会向上取整。

### 使用方法

以下示例演示了如何使用 `xRingbufferCreate()` 和 `xRingbufferSend()` 来创建环形 buffer，并向其发送数据项：

    #include "freertos/ringbuf.h"
    static char tx_item[] = "test_item";

    ...

        //创建环形 buffer
        RingbufHandle_t buf_handle;
        buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
        if (buf_handle == NULL) {
            printf("Failed to create ring buffer\n");
        }

        //发送一个数据项
        UBaseType_t res =  xRingbufferSend(buf_handle, tx_item, sizeof(tx_item), pdMS_TO_TICKS(1000));
        if (res != pdTRUE) {
            printf("Failed to send item\n");
        }

以下示例演示了如何使用 `xRingbufferSendAcquire()` 和 `xRingbufferSendComplete()` 代替 `xRingbufferSend()` 来获取环形 buffer（`RINGBUF_TYPE_NOSPLIT` 类型）上的内存，然后向其发送一个数据项。虽然增加了一个步骤，但可以实现获取要写入内存的地址，并自行写入内存。

    #include "freertos/ringbuf.h"
    #include "soc/lldesc.h"

    typedef struct {
        lldesc_t dma_desc;
        uint8_t buf[1];
    } dma_item_t;

    #define DMA_ITEM_SIZE(N) (sizeof(lldesc_t)+(((N)+3)&(~3)))

    ...

        //为 DMA 描述符和相应的数据 buffer 检索空间
        //此步骤必须通过 SendAcquire 完成，否则，复制时地址可能会不同
        dma_item_t *item;
        UBaseType_t res =  xRingbufferSendAcquire(buf_handle,
                           (void**) &item, DMA_ITEM_SIZE(buffer_size), pdMS_TO_TICKS(1000));
        if (res != pdTRUE) {
            printf("Failed to acquire memory for item\n");
        }
        item->dma_desc = (lldesc_t) {
            .size = buffer_size,
            .length = buffer_size,
            .eof = 0,
            .owner = 1,
            .buf = item->buf,
        };
        //实际发送到环形 buffer 以供使用
        res = xRingbufferSendComplete(buf_handle, (void *)item);
        if (res != pdTRUE) {
            printf("Failed to send item\n");
        }

以下示例演示了使用 `xRingbufferReceive()` 和 `vRingbufferReturnItem()` 从 不可分割环形 buffer 中检索和返回数据项：

    ...

        //从不可分割环形 buffer 中接收一个数据项
        size_t item_size;
        char *item = (char *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(1000));

        //Check received item
        if (item != NULL) {
            //Print item
            for (int i = 0; i < item_size; i++) {
                printf("%c", item[i]);
            }
            printf("\n");
            //返回数据项
            vRingbufferReturnItem(buf_handle, (void *)item);
        } else {
            //数据项检索失败
            printf("Failed to receive item\n");
        }

以下示例演示了使用 `xRingbufferReceiveSplit()` 和 `vRingbufferReturnItem()` 从 可分割环形 buffer 中检索和返回数据项：

    ...

        //从可分割环形 buffer 中接收一个数据项
        size_t item_size1, item_size2;
        char *item1, *item2;
        BaseType_t ret = xRingbufferReceiveSplit(buf_handle, (void **)&item1, (void **)&item2, &item_size1, &item_size2, pdMS_TO_TICKS(1000));

        //检查收到的数据项
        if (ret == pdTRUE && item1 != NULL) {
            for (int i = 0; i < item_size1; i++) {
                printf("%c", item1[i]);
            }
            vRingbufferReturnItem(buf_handle, (void *)item1);
            //Check if item was split
            if (item2 != NULL) {
                for (int i = 0; i < item_size2; i++) {
                    printf("%c", item2[i]);
                }
                vRingbufferReturnItem(buf_handle, (void *)item2);
            }
            printf("\n");
        } else {
            //接收数据项失败
            printf("Failed to receive item\n");
        }

以下示例演示了使用 `xRingbufferReceiveUpTo()` 和 `vRingbufferReturnItem()` 从 字节 buffer 中检索和返回数据项：

    ...

        //从字节 buffer 中接收数据
        size_t item_size;
        char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(1000), sizeof(tx_item));

        //检查接收到的数据
        if (item != NULL) {
            //Print item
            for (int i = 0; i < item_size; i++) {
                printf("%c", item[i]);
            }
            printf("\n");
            //返回数据项
            vRingbufferReturnItem(buf_handle, (void *)item);
        } else {
            //接收数据项失败
            printf("Failed to receive item\n");
        }

对于以上函数的 ISR 安全版本，请调用 `xRingbufferSendFromISR()`、 `xRingbufferReceiveFromISR()`、 `xRingbufferReceiveSplitFromISR()`、 `xRingbufferReceiveUpToFromISR()` 和 `vRingbufferReturnItemFromISR()`。

备注

当字节在环形 buffer 的末端绕回时，需调用 `RingbufferReceive[UpTo][FromISR]()` 两次。

### 发送到环形 buffer

以下图表将不可分割和可分割 buffer 与字节 buffer 进行对比，说明了三者在发送数据或数据项方面的差异。图表中，假设分别向 128 字节的 buffer 发送大小为 18、3 和 27 字节 的三个数据项：

向不可分割或可分割的环形 buffer 发送数据项

对于不可分割和可分割 buffer，每个数据项前都有 8 字节标头信息。此外，为了保持整体的 32 位对齐，每个数据项占用的空间都会 向上取整到最接近的 32 位对齐大小。数据项的实际大小会记录在标头中，并在检索数据项时返回。

参考上图，18、3 和 27 字节的数据项分别 向上取整为 20、4 和 28 字节，然后在每个数据项前面添加一个 8 字节的标头。

向字节 buffer 发送数据项

字节 buffer 将数据视为一个字节序列，不会产引入任何额外开销，不添加标头信息。因此，发送到字节 buffer 的所有数据都会合并成一个数据项。

参考上图，18、3 和 27 字节的数据项被顺序写入字节 buffer，并 合并成一个 48 字节的数据项。

### 使用 SendAcquire 和 SendComplete

不可分割 buffer 中的数据项严格按照 FIFO 顺序通过 `SendAcquire` 获取，并且必须通过 `SendComplete` 发送到 buffer 以便访问。也可以发送或获取多个数据项，且无需严格遵照获取顺序，但接收数据项却必须遵循 FIFO。所以，如果不为最早获取的数据项调用 `SendComplete`，就无法接收后续数据项。

以下图表说明了当 `SendAcquire` 和 `SendComplete` 顺序不同时的情形。一开始，已经有一个 16 字节的数据项发送到环形 buffer。然后调用 `SendAcquire` 在环形 buffer 上获取 20、8、24 字节的空间。

在不可分割环形 buffer 中 SendAcquire/SendComplete 数据项

然后填充 buffer，按照 8、24、20 字节的顺序通过 `SendComplete` 将数据项发送到环形 buffer。当 8 字节和 24 字节的数据发送后，仍只能获取 16 字节的数据项。因此，如果不为 20 字节数据项调用 `SendComplete`，就无法获取该数据项，也无法获取 20 字节后的数据项。

当 20 字节数据项最终发送完成后，就可以在 buffer 中最初的 16 字节数据项之后，按照 20、8、24 字节的顺序接收所有的三个数据项。

由于 `SendAcquire` 及 `SendComplete` 要求所获取的 buffer 必须是完整的（未包装的），故可分割 buffer 和字节 buffer 不支持上述调用操作。

### 绕回

以下图表说明了发送数据项需要绕回时，不可分割、可分割和字节 buffer 之间的差异。图表假设有一个 128 字节的 buffer，其中有 56 字节的空闲空间可以绕回使用，并发送了一个 28 字节 的数据项。

在不可分割 buffer 中绕回

不可分割 buffer 只在连续的空闲空间中存储数据项，在任何情况下都不分割数据项。当 buffer 尾部的空闲空间不足以完全存储数据项及其标头时，尾部的空闲空间将被 标记为虚拟数据。然后，数据项将绕回并存储在 buffer 头部的空闲空间中。

参考上图， buffer 尾部的 16 字节空闲空间不足以存储 28 字节的数据项，因此，这 16 字节被标记为虚拟数据，然后将数据项写入了 buffer 头部的空闲空间中。

在可分割 buffer 中绕回

当 buffer 尾部的空闲空间不足以存储数据项及其标头时，可分割 buffer 会尝试 将数据项分割成两部分。分割的的两部分数据项都将有自己的标头，因此会产生额外的 8 字节开销。

参考上图， buffer 尾部的 16 字节空闲空间不足以存储 28 字节的数据项。因此将数据项分割成两部分（8 字节和 20 字节），并将两部分写入 buffer。

备注

可分割 buffer 将其分割好的两部分数据视为两个独立的数据项，因此不应调用 `xRingbufferReceive()`。需调用 `xRingbufferReceiveSplit()` 以线程安全的方式接收分割的两部分数据项。

在字节 buffer 中绕回

字节 buffer 将尽可能多的数据存储到 buffer 尾部的空闲空间 中。剩余的数据会存储在 buffer 头部的空闲空间。在字节 buffer 中绕回不会产生任何额外开销。

参考上图，buffer 尾部的 16 字节空闲空间不足以完全存储 28 字节的数据，因此，将数据填入这 16 字节空闲空间后，剩余的 12 字节会被写入 buffer 头部的空闲空间。此时，buffer 包含两个独立的连续数据，并且每个连续数据都被字节 buffer 视为一个独立数据项。

### 检索/返回

以下图表说明了在检索和返回数据时，不可分割、可分割 buffer 和字节 buffer 之间的差异：

在不可分割和可分割环形 buffer 中检索/返回数据项

不可分割 buffer 和可分割 buffer 中的数据项 按严格的 FIFO 顺序检索 并 必须返回，以释放占用的空间。在返回之前可以检索多个数据项，且不必按照检索的顺序返回数据项。但是，释放空间必须按 FIFO 顺序进行，因此如果不返回最早检索的数据项，就无法释放后续数据项占用的空间。

参考上图， 16、20 和 8 字节的数据项按 FIFO 顺序被检索出来。但是，这些数据项并不是按照被检索的顺序返回的。最先返回的是 20 字节的数据项，然后分别返回 8 字节和 16 字节的数据项。直到第一个数据项（即 16 字节的数据项）返回后，空间才会被释放。

在字节 buffer 中检索/返回数据

字节 buffer 不允许在返回之前进行多次检索 （每次检索必须在下一次检索之前返回结果）。使用 `xRingbufferReceive()` 或 `xRingbufferReceiveFromISR()` 时，会检索所有连续存储的数据。使用 `xRingbufferReceiveUpTo()` 或 `xRingbufferReceiveUpToFromISR()` 可限制检索的最大字节数。由于每次检索后都必须返回，因此数据一返回就会释放空间。

参考上图， buffer 尾部 38 字节连续存储的数据被检索、返回和释放。然后，下一次调用 `xRingbufferReceive()` 或 `xRingbufferReceiveFromISR()` 时，buffer 将绕回并对头部的 30 字节连续存储数据进行同样的处理。

备注

从可分割 buffer 中检索数据项必须使用 `xRingbufferReceiveSplit()` 或 `xRingbufferReceiveSplitFromISR()`，而不是 `xRingbufferReceive()` 或 `xRingbufferReceiveFromISR()`。

### 使用队列集的环形 buffer

使用 `xRingbufferAddToQueueSetRead()` 可以将环形 buffer 添加到 FreeRTOS 队列集中，这样每次环形 buffer 接收一个数据项或数据时，队列集都会收到通知。添加到队列集后，每次从环形 buffer 检索数据项时都应该先调用 `xQueueSelectFromSet()`。要检查选定的队列集成员是否为环形 buffer，调用 `xRingbufferCanRead()`。

以下示例演示了如何使用包含环形 buffer 的队列集：

    #include "freertos/queue.h"
    #include "freertos/ringbuf.h"

    ...

        //创建环形 buffer 和队列集
        RingbufHandle_t buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
        QueueSetHandle_t queue_set = xQueueCreateSet(3);

        //向队列集中添加环形 buffer
        if (xRingbufferAddToQueueSetRead(buf_handle, queue_set) != pdTRUE) {
            printf("Failed to add to queue set\n");
        }

    ...

        //阻塞队列集
        QueueSetMemberHandle_t member = xQueueSelectFromSet(queue_set, pdMS_TO_TICKS(1000));

        //检查成员是否为环形 buffer
        if (member != NULL && xRingbufferCanRead(buf_handle, member) == pdTRUE) {
            //Member is ring buffer, receive item from ring buffer
            size_t item_size;
            char *item = (char *)xRingbufferReceive(buf_handle, &item_size, 0);

            //处理数据项
            ...

        } else {
            ...
        }

### 使用静态分配的环形 buffer

`xRingbufferCreateStatic()` 可用于创建具有特定内存需求的环形 buffer（如在外部 RAM 中分配的环形 buffer）。环形 buffer 使用的所有内存块都必须在创建之前手动分配，然后传递给 `xRingbufferCreateStatic()` 以初始化为环形 buffer。这些内存块中包括：

- 环形 buffer 的数据结构类型 `StaticRingbuffer_t`。

- 环形 buffer 的存储区域，大小为 `xBufferSize`。注意，对于不可分割和可分割 buffer，`xBufferSize` 必须为 32 位对齐大小。

这些块的分配方式取决于具体的需求。例如，静态声明所有块，或动态分配为具有特定功能的块，如外部 RAM。

备注

当删除通过 `xRingbufferCreateStatic()` 创建的环形 buffer 时，`vRingbufferDelete()` 函数不会释放任何内存块。释放内存必须在调用 `vRingbufferDelete()` 后手动完成。

下面的代码片段演示了一个完全在外部 RAM 中分配的环形 buffer：

    #include "freertos/ringbuf.h"
    #include "freertos/semphr.h"
    #include "esp_heap_caps.h"

    #define BUFFER_SIZE     400      //32 位对齐大小
    #define BUFFER_TYPE     RINGBUF_TYPE_NOSPLIT
    ...

    //将 环形 buffer 数据结构体和存储区分配到外部 RAM 中
    StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
    uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*BUFFER_SIZE, MALLOC_CAP_SPIRAM);

    //使用手动分配的内存创建环形 buffer
    RingbufHandle_t handle = xRingbufferCreateStatic(BUFFER_SIZE, BUFFER_TYPE, buffer_storage, buffer_struct);

    ...

    //使用后删除环形 buffer
    vRingbufferDelete(handle);

    //手动释放所有内存块
    free(buffer_struct);
    free(buffer_storage);

## ESP-IDF tick 钩子 和 idle 钩子

FreeRTOS 允许应用程序在编译时提供一个 tick 钩子和一个 idle 钩子：

- FreeRTOS tick 钩子可以通过 CONFIG_FREERTOS_USE_TICK_HOOK 选项启用。应用程序必须提供 `void vApplicationTickHook( void )` 回调。

- FreeRTOS idle 钩子可以通过 CONFIG_FREERTOS_USE_IDLE_HOOK 选项启用。应用程序必须提供 `void vApplicationIdleHook( void )` 回调。

然而，FreeRTOS tick 钩子和 idle 钩子有以下不足：

- FreeRTOS 钩子是在编译时注册的

- 每种钩子只能注册一个

- 在多核目标芯片上，FreeRTOS 钩子是对称的，即每个内核的 tick 中断和 idle 任务最终都会调用同一个钩子

因此，ESP-IDF 提供了 tick 钩子和 idle 钩子来补充 FreeRTOS tick 和 idle 钩子的功能。ESP-IDF 钩子具有以下功能：

- 钩子可以在运行时注册和注销

- 可以注册多个钩子。每个内核中，同一类型的钩子最多可以注册 8 个

- 在多核目标芯片上，钩子可以是不对称的，即可以为每个内核注册不同的钩子

使用以下 API 注册和注销 ESP-IDF 钩子：

- 对于 tick 钩子：

  > - 用 `esp_register_freertos_tick_hook()` 或 `esp_register_freertos_tick_hook_for_cpu()` 注册

  > - 用 `esp_deregister_freertos_tick_hook()` 或 `esp_deregister_freertos_tick_hook_for_cpu()` 注销

- 对于 idle 钩子：

  > - 使用 `esp_register_freertos_idle_hook()` 或 `esp_register_freertos_idle_hook_for_cpu()` 注册

  > - 使用 `esp_deregister_freertos_idle_hook()` 或 `esp_deregister_freertos_idle_hook_for_cpu()` 注销

备注

在 cache 被禁用时，tick 中断仍保持活动，因此任何 tick 钩子（FreeRTOS 或 ESP-IDF）函数都必须放在内部 RAM 中。请参考 SPI flash API documentation 了解详情。

## TLSP 删除回调

原生 FreeRTOS 提供了线程本地存储指针 (TLSP) 功能，这些指针直接存储在特定任务的任务控制块 (TCB) 中。TLSP 允许每个任务拥有自己的数据结构指针集合。在原生 FreeRTOS 中：

- 在任务创建后，需调用 `vTaskSetThreadLocalStoragePointer()` 设置任务的 TLSP。

- 在任务的生命周期中，需调用 `pvTaskGetThreadLocalStoragePointer()` 获取任务的 TLSP。

- 在删除任务前，需释放 TLSP 指向的内存。

然而，为了能够欧自动释放 TLSP 内存，ESP-IDF 额外提供了 TLSP 删除回调功能。当删除任务时，这些删除回调函数会被自动调用，从而清除 TLSP 内存，无需在每个任务的代码中显式添加内存清除逻辑。

设置 TLSP 删除回调的方式与设置 TLSP 类似。

- `vTaskSetThreadLocalStoragePointerAndDelCallback()` 设置了特定的 TLSP 及其关联的回调。

- 调用原生 FreeRTOS 函数 `vTaskSetThreadLocalStoragePointer()` 只会将 TLSP 的关联删除回调设置为 NULL，也就是说，在任务删除期间不会调用该 TLSP 的回调。

在实现 TLSP 回调时，应注意以下几点：

- 回调 绝对不能尝试阻塞或让出，并且应尽可能缩短临界区的时间。

- 回调是在删除任务的内存即将被释放前调用的。因此，回调可以通过 `vTaskDelete()` 本身调用，也可以从空闲任务中调用。

## IDF 附加 API

freertos/esp_additions/include/freertos/idf_additions.h 头文件包含了 ESP-IDF 添加的与 FreeRTOS 相关的辅助函数。通过 `#include "freertos/idf_additions.h"` 可添加此头文件。

## 组件专用功能

除了基本 CMake 构建属性中提供的标准组件变量外，FreeRTOS 组件还提供了参数（目前只有一个参数）以简化与其他模块的集成：

- ORIG_INCLUDE_PATH - 包含指向 freeRTOS 根包含文件夹的绝对路径。因此可以直接用 #include "FreeRTOS.h" 引用头文件，而无需使用 #include "freertos/FreeRTOS.h"。

## API 参考

### 环形 buffer API

### Header File

- components/esp_ringbuf/include/freertos/ringbuf.h

- This header file can be included with:

  >     #include "freertos/ringbuf.h"

- This header file is a part of the API provided by the `esp_ringbuf` component. To declare that your component depends on `esp_ringbuf`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_ringbuf

  > or

  >     PRIV_REQUIRES esp_ringbuf

### Functions

RingbufHandle_t xRingbufferCreate(size_t xBufferSize, RingbufferType_t xBufferType)

  Create a ring buffer.

  备注

  xBufferSize of no-split/allow-split buffers will be rounded up to the nearest 32-bit aligned size.

  参数:

    - xBufferSize -- [in] Size of the buffer in bytes. Note that items require space for a header in no-split/allow-split buffers

    - xBufferType -- [in] Type of ring buffer, see documentation.

  返回:

    A handle to the created ring buffer, or NULL in case of error.

RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum)

  Create a ring buffer of type RINGBUF_TYPE_NOSPLIT for a fixed item_size.

  This API is similar to xRingbufferCreate(), but it will internally allocate additional space for the headers.

  参数:

    - xItemSize -- [in] Size of each item to be put into the ring buffer

    - xItemNum -- [in] Maximum number of items the buffer needs to hold simultaneously

  返回:

    A RingbufHandle_t handle to the created ring buffer, or NULL in case of error.

RingbufHandle_t xRingbufferCreateStatic(size_t xBufferSize, RingbufferType_t xBufferType, uint8_t *pucRingbufferStorage, StaticRingbuffer_t *pxStaticRingbuffer)

  Create a ring buffer but manually provide the required memory.

  备注

  xBufferSize of no-split/allow-split buffers MUST be 32-bit aligned.

  参数:

    - xBufferSize -- [in] Size of the buffer in bytes.

    - xBufferType -- [in] Type of ring buffer, see documentation

    - pucRingbufferStorage -- [in] Pointer to the ring buffer's storage area. Storage area must have the same size as specified by xBufferSize

    - pxStaticRingbuffer -- [in] Pointed to a struct of type StaticRingbuffer_t which will be used to hold the ring buffer's data structure

  返回:

    A handle to the created ring buffer

BaseType_t xRingbufferSend(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, TickType_t xTicksToWait)

  Insert an item into the ring buffer.

  Attempt to insert an item into the ring buffer. This function will block until enough free space is available or until it times out.

  备注

  For no-split/allow-split ring buffers, the actual size of memory that the item will occupy will be rounded up to the nearest 32-bit aligned size. This is done to ensure all items are always stored in 32-bit aligned fashion.

  备注

  For no-split/allow-split buffers, an xItemSize of 0 will result in an item with no data being set (i.e., item only contains the header). For byte buffers, an xItemSize of 0 will simply return pdTRUE without copying any data.

  参数:

    - xRingbuffer -- [in] Ring buffer to insert the item into

    - pvItem -- [in] Pointer to data to insert. NULL is allowed if xItemSize is 0.

    - xItemSize -- [in] Size of data to insert.

    - xTicksToWait -- [in] Ticks to wait for room in the ring buffer.

  返回:

    - pdTRUE if succeeded

    - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer

BaseType_t xRingbufferSendFromISR(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, BaseType_t *pxHigherPriorityTaskWoken)

  Insert an item into the ring buffer in an ISR.

  Attempt to insert an item into the ring buffer from an ISR. This function will return immediately if there is insufficient free space in the buffer.

  备注

  For no-split/allow-split ring buffers, the actual size of memory that the item will occupy will be rounded up to the nearest 32-bit aligned size. This is done to ensure all items are always stored in 32-bit aligned fashion.

  备注

  For no-split/allow-split buffers, an xItemSize of 0 will result in an item with no data being set (i.e., item only contains the header). For byte buffers, an xItemSize of 0 will simply return pdTRUE without copying any data.

  参数:

    - xRingbuffer -- [in] Ring buffer to insert the item into

    - pvItem -- [in] Pointer to data to insert. NULL is allowed if xItemSize is 0.

    - xItemSize -- [in] Size of data to insert.

    - pxHigherPriorityTaskWoken -- [out] Value pointed to will be set to pdTRUE if the function woke up a higher priority task.

  返回:

    - pdTRUE if succeeded

    - pdFALSE when the ring buffer does not have space.

BaseType_t xRingbufferSendAcquire(RingbufHandle_t xRingbuffer, void **ppvItem, size_t xItemSize, TickType_t xTicksToWait)

  Acquire memory from the ring buffer to be written to by an external source and to be sent later.

  Attempt to allocate buffer for an item to be sent into the ring buffer. This function will block until enough free space is available or until it times out.

  The item, as well as the following items `SendAcquire` or `Send` after it, will not be able to be read from the ring buffer until this item is actually sent into the ring buffer.

  备注

  Only applicable for no-split ring buffers now, the actual size of memory that the item will occupy will be rounded up to the nearest 32-bit aligned size. This is done to ensure all items are always stored in 32-bit aligned fashion.

  备注

  An xItemSize of 0 will result in a buffer being acquired, but the buffer will have a size of 0.

  参数:

    - xRingbuffer -- [in] Ring buffer to allocate the memory

    - ppvItem -- [out] Double pointer to memory acquired (set to NULL if no memory were retrieved)

    - xItemSize -- [in] Size of item to acquire.

    - xTicksToWait -- [in] Ticks to wait for room in the ring buffer.

  返回:

    - pdTRUE if succeeded

    - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer

BaseType_t xRingbufferSendComplete(RingbufHandle_t xRingbuffer, void *pvItem)

  Actually send an item into the ring buffer allocated before by `xRingbufferSendAcquire`.

  备注

  Only applicable for no-split ring buffers. Only call for items allocated by `xRingbufferSendAcquire`.

  参数:

    - xRingbuffer -- [in] Ring buffer to insert the item into

    - pvItem -- [in] Pointer to item in allocated memory to insert.

  返回:

    - pdTRUE if succeeded

    - pdFALSE if fail for some reason.

void *xRingbufferReceive(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait)

  Retrieve an item from the ring buffer.

  Attempt to retrieve an item from the ring buffer. This function will block until an item is available or until it times out.

  备注

  A call to vRingbufferReturnItem() is required after this to free the item retrieved.

  备注

  It is possible to receive items with a pxItemSize of 0 on no-split buffers.

  备注

  To retrieve an item from an allow-split buffer, use `xRingbufferReceiveSplit()` instead.

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - pxItemSize -- [out] Pointer to a variable to which the size of the retrieved item will be written.

    - xTicksToWait -- [in] Ticks to wait for items in the ring buffer.

  返回:

    - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.

    - NULL on timeout, *pxItemSize is untouched in that case.

void *xRingbufferReceiveFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize)

  Retrieve an item from the ring buffer in an ISR.

  Attempt to retrieve an item from the ring buffer. This function returns immediately if there are no items available for retrieval

  备注

  A call to vRingbufferReturnItemFromISR() is required after this to free the item retrieved.

  备注

  Byte buffers do not allow multiple retrievals before returning an item

  备注

  Two calls to RingbufferReceiveFromISR() are required if the bytes wrap around the end of the ring buffer.

  备注

  It is possible to receive items with a pxItemSize of 0 on no-split buffers.

  备注

  To retrieve an item from an allow-split buffer, use `xRingbufferReceiveSplitFromISR()` instead.

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - pxItemSize -- [out] Pointer to a variable to which the size of the retrieved item will be written.

  返回:

    - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.

    - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.

BaseType_t xRingbufferReceiveSplit(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize, TickType_t xTicksToWait)

  Retrieve a split item from an allow-split ring buffer.

  Attempt to retrieve a split item from an allow-split ring buffer. If the item is not split, only a single item is retried. If the item is split, both parts will be retrieved. This function will block until an item is available or until it times out.

  备注

  Call(s) to vRingbufferReturnItem() is required after this to free up the item(s) retrieved.

  备注

  This function should only be called on allow-split buffers

  备注

  It is possible to receive items with a pxItemSize of 0 on allow split buffers.

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - ppvHeadItem -- [out] Double pointer to first part (set to NULL if no items were retrieved)

    - ppvTailItem -- [out] Double pointer to second part (set to NULL if item is not split)

    - pxHeadItemSize -- [out] Pointer to size of first part (unmodified if no items were retrieved)

    - pxTailItemSize -- [out] Pointer to size of second part (unmodified if item is not split)

    - xTicksToWait -- [in] Ticks to wait for items in the ring buffer.

  返回:

    - pdTRUE if an item (split or unsplit) was retrieved

    - pdFALSE when no item was retrieved

BaseType_t xRingbufferReceiveSplitFromISR(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize)

  Retrieve a split item from an allow-split ring buffer in an ISR.

  Attempt to retrieve a split item from an allow-split ring buffer. If the item is not split, only a single item is retried. If the item is split, both parts will be retrieved. This function returns immediately if there are no items available for retrieval

  备注

  Calls to vRingbufferReturnItemFromISR() is required after this to free up the item(s) retrieved.

  备注

  This function should only be called on allow-split buffers

  备注

  It is possible to receive items with a pxItemSize of 0 on allow split buffers.

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - ppvHeadItem -- [out] Double pointer to first part (set to NULL if no items were retrieved)

    - ppvTailItem -- [out] Double pointer to second part (set to NULL if item is not split)

    - pxHeadItemSize -- [out] Pointer to size of first part (unmodified if no items were retrieved)

    - pxTailItemSize -- [out] Pointer to size of second part (unmodified if item is not split)

  返回:

    - pdTRUE if an item (split or unsplit) was retrieved

    - pdFALSE when no item was retrieved

void *xRingbufferReceiveUpTo(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait, size_t xMaxSize)

  Retrieve bytes from a byte buffer, specifying the maximum amount of bytes to retrieve.

  Attempt to retrieve data from a byte buffer whilst specifying a maximum number of bytes to retrieve. This function will block until there is data available for retrieval or until it times out.

  备注

  A call to vRingbufferReturnItem() is required after this to free up the data retrieved.

  备注

  This function should only be called on byte buffers

  备注

  Byte buffers do not allow multiple retrievals before returning an item

  备注

  Two calls to RingbufferReceiveUpTo() are required if the bytes wrap around the end of the ring buffer.

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - pxItemSize -- [out] Pointer to a variable to which the size of the retrieved item will be written.

    - xTicksToWait -- [in] Ticks to wait for items in the ring buffer.

    - xMaxSize -- [in] Maximum number of bytes to return.

  返回:

    - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.

    - NULL on timeout, *pxItemSize is untouched in that case.

void *xRingbufferReceiveUpToFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize, size_t xMaxSize)

  Retrieve bytes from a byte buffer, specifying the maximum amount of bytes to retrieve. Call this from an ISR.

  Attempt to retrieve bytes from a byte buffer whilst specifying a maximum number of bytes to retrieve. This function will return immediately if there is no data available for retrieval.

  备注

  A call to vRingbufferReturnItemFromISR() is required after this to free up the data received.

  备注

  This function should only be called on byte buffers

  备注

  Byte buffers do not allow multiple retrievals before returning an item

  参数:

    - xRingbuffer -- [in] Ring buffer to retrieve the item from

    - pxItemSize -- [out] Pointer to a variable to which the size of the retrieved item will be written.

    - xMaxSize -- [in] Maximum number of bytes to return. Size of 0 simply returns NULL.

  返回:

    - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.

    - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.

void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem)

  Return a previously-retrieved item to the ring buffer.

  备注

  If a split item is retrieved, both parts should be returned by calling this function twice

  参数:

    - xRingbuffer -- [in] Ring buffer the item was retrieved from

    - pvItem -- [in] Item that was received earlier

void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken)

  Return a previously-retrieved item to the ring buffer from an ISR.

  备注

  If a split item is retrieved, both parts should be returned by calling this function twice

  参数:

    - xRingbuffer -- [in] Ring buffer the item was retrieved from

    - pvItem -- [in] Item that was received earlier

    - pxHigherPriorityTaskWoken -- [out] Value pointed to will be set to pdTRUE if the function woke up a higher priority task.

void vRingbufferDelete(RingbufHandle_t xRingbuffer)

  Delete a ring buffer.

  备注

  This function will not deallocate any memory if the ring buffer was created using xRingbufferCreateStatic(). Deallocation must be done manually be the user.

  参数:

    xRingbuffer -- [in] Ring buffer to delete

size_t xRingbufferGetMaxItemSize(RingbufHandle_t xRingbuffer)

  Get maximum size of an item that can be placed in the ring buffer.

  This function returns the maximum size an item can have if it was placed in an empty ring buffer.

  备注

  The max item size for a no-split buffer is limited to ((buffer_size/2)-header_size). This limit is imposed so that an item of max item size can always be sent to an empty no-split buffer regardless of the internal positions of the buffer's read/write/free pointers.

  参数:

    xRingbuffer -- [in] Ring buffer to query

  返回:

    Maximum size, in bytes, of an item that can be placed in a ring buffer.

size_t xRingbufferGetCurFreeSize(RingbufHandle_t xRingbuffer)

  Get current free size available for an item/data in the buffer.

  This gives the real time free space available for an item/data in the ring buffer. This represents the maximum size an item/data can have if it was currently sent to the ring buffer.

  备注

  An empty no-split buffer has a max current free size for an item that is limited to ((buffer_size/2)-header_size). See API reference for xRingbufferGetMaxItemSize().

  参数:

    xRingbuffer -- [in] Ring buffer to query

  返回:

    Current free size, in bytes, available for an entry

BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet)

  Add the ring buffer to a queue set. Notified when data has been written to the ring buffer.

  This function adds the ring buffer to a queue set, thus allowing a task to block on multiple queues/ring buffers. The queue set is notified when the new data becomes available to read on the ring buffer.

  参数:

    - xRingbuffer -- [in] Ring buffer to add to the queue set

    - xQueueSet -- [in] Queue set to add the ring buffer to

  返回:

    - pdTRUE on success, pdFALSE otherwise

static inline BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember)

  Check if the selected queue set member is a particular ring buffer.

  This API checks if queue set member returned from xQueueSelectFromSet() is a particular ring buffer. If so, this indicates the ring buffer has items waiting to be retrieved.

  参数:

    - xRingbuffer -- [in] Ring buffer to check

    - xMember -- [in] Member returned from xQueueSelectFromSet

  返回:

    - pdTRUE when selected queue set member is the ring buffer

    - pdFALSE otherwise.

BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet)

  Remove the ring buffer from a queue set.

  This function removes a ring buffer from a queue set. The ring buffer must have been previously added to the queue set using xRingbufferAddToQueueSetRead().

  参数:

    - xRingbuffer -- [in] Ring buffer to remove from the queue set

    - xQueueSet -- [in] Queue set to remove the ring buffer from

  返回:

    - pdTRUE on success

    - pdFALSE otherwise

void vRingbufferGetInfo(RingbufHandle_t xRingbuffer, UBaseType_t *uxFree, UBaseType_t *uxRead, UBaseType_t *uxWrite, UBaseType_t *uxAcquire, UBaseType_t *uxItemsWaiting)

  Get information about ring buffer status.

  Get information of a ring buffer's current status such as free/read/write/acquire pointer positions, and number of items waiting to be retrieved. Arguments can be set to NULL if they are not required.

  参数:

    - xRingbuffer -- [in] Ring buffer handle

    - uxFree -- [out] Pointer use to store free pointer position

    - uxRead -- [out] Pointer use to store read pointer position

    - uxWrite -- [out] Pointer use to store write pointer position

    - uxAcquire -- [out] Pointer use to store acquire pointer position

    - uxItemsWaiting -- [out] Pointer use to store number of items (bytes for byte buffer) waiting to be retrieved

void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer)

  Debugging function to print the internal pointers in the ring buffer.

  参数:

    xRingbuffer -- Ring buffer to show

BaseType_t xRingbufferGetStaticBuffer(RingbufHandle_t xRingbuffer, uint8_t **ppucRingbufferStorage, StaticRingbuffer_t **ppxStaticRingbuffer)

  Retrieve the pointers to a statically created ring buffer.

  参数:

    - xRingbuffer -- [in] Ring buffer

    - ppucRingbufferStorage -- [out] Used to return a pointer to the queue's storage area buffer

    - ppxStaticRingbuffer -- [out] Used to return a pointer to the queue's data structure buffer

  返回:

    pdTRUE if buffers were retrieved, pdFALSE otherwise.

RingbufHandle_t xRingbufferCreateWithCaps(size_t xBufferSize, RingbufferType_t xBufferType, UBaseType_t uxMemoryCaps)

  Creates a ring buffer with specific memory capabilities.

  This function is similar to xRingbufferCreate(), except that it allows the memory allocated for the ring buffer to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A queue created using this function must only be deleted using vRingbufferDeleteWithCaps()

  参数:

    - xBufferSize -- [in] Size of the buffer in bytes

    - xBufferType -- [in] Type of ring buffer, see documentation.

    - uxMemoryCaps -- [in] Memory capabilities of the queue's memory (see esp_heap_caps.h)

  返回:

    Handle to the created ring buffer or NULL on failure.

void vRingbufferDeleteWithCaps(RingbufHandle_t xRingbuffer)

  Deletes a ring buffer previously created using xRingbufferCreateWithCaps()

  参数:

    xRingbuffer -- Ring buffer

### Structures

struct xSTATIC_RINGBUFFER

  Struct that is equivalent in size to the ring buffer's data structure.

  The contents of this struct are not meant to be used directly. This structure is meant to be used when creating a statically allocated ring buffer where this struct is of the exact size required to store a ring buffer's control data structure.

### Type Definitions

typedef void *RingbufHandle_t

  Type by which ring buffers are referenced. For example, a call to xRingbufferCreate() returns a RingbufHandle_t variable that can then be used as a parameter to xRingbufferSend(), xRingbufferReceive(), etc.

typedef struct xSTATIC_RINGBUFFER StaticRingbuffer_t

  Struct that is equivalent in size to the ring buffer's data structure.

  The contents of this struct are not meant to be used directly. This structure is meant to be used when creating a statically allocated ring buffer where this struct is of the exact size required to store a ring buffer's control data structure.

### Enumerations

enum RingbufferType_t

  Values:

  enumerator RINGBUF_TYPE_NOSPLIT

    No-split buffers will only store an item in contiguous memory and will never split an item. Each item requires an 8 byte overhead for a header and will always internally occupy a 32-bit aligned size of space.

  enumerator RINGBUF_TYPE_ALLOWSPLIT

    Allow-split buffers will split an item into two parts if necessary in order to store it. Each item requires an 8 byte overhead for a header, splitting incurs an extra header. Each item will always internally occupy a 32-bit aligned size of space.

  enumerator RINGBUF_TYPE_BYTEBUF

    Byte buffers store data as a sequence of bytes and do not maintain separate items, therefore byte buffers have no overhead. All data is stored as a sequence of byte and any number of bytes can be sent or retrieved each time.

  enumerator RINGBUF_TYPE_MAX

### 钩子 API

### Header File

- components/esp_system/include/esp_freertos_hooks.h

- This header file can be included with:

  >     #include "esp_freertos_hooks.h"

### Functions

esp_err_t esp_register_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t new_idle_cb, UBaseType_t cpuid)

  Register a callback to be called from the specified core's idle hook. The callback should return true if it should be called by the idle hook once per interrupt (or FreeRTOS tick), and return false if it should be called repeatedly as fast as possible by the idle hook.

  警告

  Idle callbacks MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.

  参数:

    - new_idle_cb -- [in] Callback to be called

    - cpuid -- [in] id of the core

  返回:

    - ESP_OK: Callback registered to the specified core's idle hook

    - ESP_ERR_NO_MEM: No more space on the specified core's idle hook to register callback

    - ESP_ERR_INVALID_ARG: cpuid is invalid

esp_err_t esp_register_freertos_idle_hook(esp_freertos_idle_cb_t new_idle_cb)

  Register a callback to the idle hook of the core that calls this function. The callback should return true if it should be called by the idle hook once per interrupt (or FreeRTOS tick), and return false if it should be called repeatedly as fast as possible by the idle hook.

  警告

  Idle callbacks MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.

  参数:

    new_idle_cb -- [in] Callback to be called

  返回:

    - ESP_OK: Callback registered to the calling core's idle hook

    - ESP_ERR_NO_MEM: No more space on the calling core's idle hook to register callback

esp_err_t esp_register_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t new_tick_cb, UBaseType_t cpuid)

  Register a callback to be called from the specified core's tick hook.

  参数:

    - new_tick_cb -- [in] Callback to be called

    - cpuid -- [in] id of the core

  返回:

    - ESP_OK: Callback registered to specified core's tick hook

    - ESP_ERR_NO_MEM: No more space on the specified core's tick hook to register the callback

    - ESP_ERR_INVALID_ARG: cpuid is invalid

esp_err_t esp_register_freertos_tick_hook(esp_freertos_tick_cb_t new_tick_cb)

  Register a callback to be called from the calling core's tick hook.

  参数:

    new_tick_cb -- [in] Callback to be called

  返回:

    - ESP_OK: Callback registered to the calling core's tick hook

    - ESP_ERR_NO_MEM: No more space on the calling core's tick hook to register the callback

void esp_deregister_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t old_idle_cb, UBaseType_t cpuid)

  Unregister an idle callback from the idle hook of the specified core.

  参数:

    - old_idle_cb -- [in] Callback to be unregistered

    - cpuid -- [in] id of the core

void esp_deregister_freertos_idle_hook(esp_freertos_idle_cb_t old_idle_cb)

  Unregister an idle callback. If the idle callback is registered to the idle hooks of both cores, the idle hook will be unregistered from both cores.

  参数:

    old_idle_cb -- [in] Callback to be unregistered

void esp_deregister_freertos_tick_hook_for_cpu(esp_freertos_tick_cb_t old_tick_cb, UBaseType_t cpuid)

  Unregister a tick callback from the tick hook of the specified core.

  参数:

    - old_tick_cb -- [in] Callback to be unregistered

    - cpuid -- [in] id of the core

void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb)

  Unregister a tick callback. If the tick callback is registered to the tick hooks of both cores, the tick hook will be unregistered from both cores.

  参数:

    old_tick_cb -- [in] Callback to be unregistered

### Type Definitions

typedef bool (*esp_freertos_idle_cb_t)(void)

typedef void (*esp_freertos_tick_cb_t)(void)

### 附加 API

### Header File

- components/freertos/esp_additions/include/freertos/idf_additions.h

- This header file can be included with:

  >     #include "freertos/idf_additions.h"

### Functions

BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pxTaskCode, const char *const pcName, const uint32_t ulStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pxCreatedTask, const BaseType_t xCoreID)

  Create a new task that is pinned to a particular core.

  This function is similar to xTaskCreate(), but allows the creation of a pinned task. The task's pinned core is specified by the xCoreID argument. If xCoreID is set to tskNO_AFFINITY, then the task is unpinned and can run on any core.

  备注

  If ( configNUMBER_OF_CORES == 1 ), setting xCoreID to tskNO_AFFINITY will be be treated as 0.

  参数:

    - pxTaskCode -- Pointer to the task entry function.

    - pcName -- A descriptive name for the task.

    - ulStackDepth -- The size of the task stack specified as the NUMBER OF BYTES. Note that this differs from vanilla FreeRTOS.

    - pvParameters -- Pointer that will be used as the parameter for the task being created.

    - uxPriority -- The priority at which the task should run.

    - pxCreatedTask -- Used to pass back a handle by which the created task can be referenced.

    - xCoreID -- The core to which the task is pinned to, or tskNO_AFFINITY if the task has no core affinity.

  返回:

    pdPASS if the task was successfully created and added to a ready list, otherwise an error code defined in the file projdefs.h

TaskHandle_t xTaskCreateStaticPinnedToCore(TaskFunction_t pxTaskCode, const char *const pcName, const uint32_t ulStackDepth, void *const pvParameters, UBaseType_t uxPriority, StackType_t *const puxStackBuffer, StaticTask_t *const pxTaskBuffer, const BaseType_t xCoreID)

  Create a new static task that is pinned to a particular core.

  This function is similar to xTaskCreateStatic(), but allows the creation of a pinned task. The task's pinned core is specified by the xCoreID argument. If xCoreID is set to tskNO_AFFINITY, then the task is unpinned and can run on any core.

  备注

  If ( configNUMBER_OF_CORES == 1 ), setting xCoreID to tskNO_AFFINITY will be be treated as 0.

  参数:

    - pxTaskCode -- Pointer to the task entry function.

    - pcName -- A descriptive name for the task.

    - ulStackDepth -- The size of the task stack specified as the NUMBER OF BYTES. Note that this differs from vanilla FreeRTOS.

    - pvParameters -- Pointer that will be used as the parameter for the task being created.

    - uxPriority -- The priority at which the task should run.

    - puxStackBuffer -- Must point to a StackType_t array that has at least ulStackDepth indexes

    - pxTaskBuffer -- Must point to a variable of type StaticTask_t, which will then be used to hold the task's data structures,

    - xCoreID -- The core to which the task is pinned to, or tskNO_AFFINITY if the task has no core affinity.

  返回:

    The task handle if the task was created, NULL otherwise.

BaseType_t xTaskGetCoreID(TaskHandle_t xTask)

  Get the current core ID of a particular task.

  Helper function to get the core ID of a particular task. If the task is pinned to a particular core, the core ID is returned. If the task is not pinned to a particular core, tskNO_AFFINITY is returned.

  If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.

  [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)

  备注

  If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet() instead.

  备注

  In IDF FreerTOS when configNUMBER_OF_CORES == 1, this function will always return 0,

  参数:

    xTask -- The task to query

  返回:

    The task's core ID or tskNO_AFFINITY

TaskHandle_t xTaskGetCurrentTaskHandleForCore(BaseType_t xCoreID)

  Get the handle of the task currently running on a certain core.

  Because of the nature of SMP processing, there is no guarantee that this value will still be valid on return and should only be used for debugging purposes.

  [refactor-todo] See if this needs to be deprecated (IDF-8145)

  参数:

    xCoreID -- The core to query

  返回:

    Handle of the current task running on the queried core

uint8_t *pxTaskGetStackStart(TaskHandle_t xTask)

  Returns the start of the stack associated with xTask.

  Returns the lowest stack memory address, regardless of whether the stack grows up or down.

  [refactor-todo] Change return type to StackType_t (IDF-8158)

  参数:

    xTask -- Handle of the task associated with the stack returned. Set xTask to NULL to return the stack of the calling task.

  返回:

    A pointer to the start of the stack.

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

  Set local storage pointer and deletion callback.

  Each task contains an array of pointers that is dimensioned by the configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The kernel does not use the pointers itself, so the application writer can use the pointers for any purpose they wish.

  Local storage pointers set for a task can reference dynamically allocated resources. This function is similar to vTaskSetThreadLocalStoragePointer, but provides a way to release these resources when the task gets deleted. For each pointer, a callback function can be set. This function will be called when task is deleted, with the local storage pointer index and value as arguments.

  参数:

    - xTaskToSet -- Task to set thread local storage pointer for

    - xIndex -- The index of the pointer to set, from 0 to configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1.

    - pvValue -- Pointer value to set.

    - pvDelCallback -- Function to call to dispose of the local storage pointer when the task is deleted.

BaseType_t xTaskCreatePinnedToCoreWithCaps(TaskFunction_t pvTaskCode, const char *const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask, const BaseType_t xCoreID, UBaseType_t uxMemoryCaps)

  Creates a pinned task where its stack has specific memory capabilities.

  This function is similar to xTaskCreatePinnedToCore(), except that it allows the memory allocated for the task's stack to have specific capabilities (e.g., MALLOC_CAP_SPIRAM).

  However, the specified capabilities will NOT apply to the task's TCB as a TCB must always be in internal RAM.

  参数:

    - pvTaskCode -- Pointer to the task entry function

    - pcName -- A descriptive name for the task

    - usStackDepth -- The size of the task stack specified as the number of bytes

    - pvParameters -- Pointer that will be used as the parameter for the task being created.

    - uxPriority -- The priority at which the task should run.

    - pvCreatedTask -- Used to pass back a handle by which the created task can be referenced.

    - xCoreID -- Core to which the task is pinned to, or tskNO_AFFINITY if unpinned.

    - uxMemoryCaps -- Memory capabilities of the task stack's memory (see esp_heap_caps.h)

  返回:

    pdPASS if the task was successfully created and added to a ready list, otherwise an error code defined in the file projdefs.h

static inline BaseType_t xTaskCreateWithCaps(TaskFunction_t pvTaskCode, const char *const pcName, configSTACK_DEPTH_TYPE usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *pvCreatedTask, UBaseType_t uxMemoryCaps)

  Creates a task where its stack has specific memory capabilities.

  This function is similar to xTaskCreate(), except that it allows the memory allocated for the task's stack to have specific capabilities (e.g., MALLOC_CAP_SPIRAM).

  However, the specified capabilities will NOT apply to the task's TCB as a TCB must always be in internal RAM.

  备注

  A task created using this function must only be deleted using vTaskDeleteWithCaps()

  参数:

    - pvTaskCode -- Pointer to the task entry function

    - pcName -- A descriptive name for the task

    - usStackDepth -- The size of the task stack specified as the number of bytes

    - pvParameters -- Pointer that will be used as the parameter for the task being created.

    - uxPriority -- The priority at which the task should run.

    - pvCreatedTask -- Used to pass back a handle by which the created task can be referenced.

    - uxMemoryCaps -- Memory capabilities of the task stack's memory (see esp_heap_caps.h)

  返回:

    pdPASS if the task was successfully created and added to a ready list, otherwise an error code defined in the file projdefs.h

void vTaskDeleteWithCaps(TaskHandle_t xTaskToDelete)

  Deletes a task previously created using xTaskCreateWithCaps() or xTaskCreatePinnedToCoreWithCaps()

  备注

  It is recommended to use this API to delete tasks from another task's context, rather than self-deletion. When the task is being deleted, it is vital to ensure that it is not running on another core. This API must not be called from an interrupt context.

  参数:

    xTaskToDelete -- A handle to the task to be deleted

QueueHandle_t xQueueCreateWithCaps(UBaseType_t uxQueueLength, UBaseType_t uxItemSize, UBaseType_t uxMemoryCaps)

  Creates a queue with specific memory capabilities.

  This function is similar to xQueueCreate(), except that it allows the memory allocated for the queue to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A queue created using this function must only be deleted using vQueueDeleteWithCaps()

  参数:

    - uxQueueLength -- The maximum number of items that the queue can contain.

    - uxItemSize -- The number of bytes each item in the queue will require.

    - uxMemoryCaps -- Memory capabilities of the queue's memory (see esp_heap_caps.h)

  返回:

    Handle to the created queue or NULL on failure.

void vQueueDeleteWithCaps(QueueHandle_t xQueue)

  Deletes a queue previously created using xQueueCreateWithCaps()

  参数:

    xQueue -- A handle to the queue to be deleted.

static inline SemaphoreHandle_t xSemaphoreCreateBinaryWithCaps(UBaseType_t uxMemoryCaps)

  Creates a binary semaphore with specific memory capabilities.

  This function is similar to vSemaphoreCreateBinary(), except that it allows the memory allocated for the binary semaphore to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A binary semaphore created using this function must only be deleted using vSemaphoreDeleteWithCaps()

  参数:

    uxMemoryCaps -- Memory capabilities of the binary semaphore's memory (see esp_heap_caps.h)

  返回:

    Handle to the created binary semaphore or NULL on failure.

static inline SemaphoreHandle_t xSemaphoreCreateCountingWithCaps(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, UBaseType_t uxMemoryCaps)

  Creates a counting semaphore with specific memory capabilities.

  This function is similar to xSemaphoreCreateCounting(), except that it allows the memory allocated for the counting semaphore to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A counting semaphore created using this function must only be deleted using vSemaphoreDeleteWithCaps()

  参数:

    - uxMaxCount -- The maximum count value that can be reached.

    - uxInitialCount -- The count value assigned to the semaphore when it is created.

    - uxMemoryCaps -- Memory capabilities of the counting semaphore's memory (see esp_heap_caps.h)

  返回:

    Handle to the created counting semaphore or NULL on failure.

static inline SemaphoreHandle_t xSemaphoreCreateMutexWithCaps(UBaseType_t uxMemoryCaps)

  Creates a mutex semaphore with specific memory capabilities.

  This function is similar to xSemaphoreCreateMutex(), except that it allows the memory allocated for the mutex semaphore to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A mutex semaphore created using this function must only be deleted using vSemaphoreDeleteWithCaps()

  参数:

    uxMemoryCaps -- Memory capabilities of the mutex semaphore's memory (see esp_heap_caps.h)

  返回:

    Handle to the created mutex semaphore or NULL on failure.

static inline SemaphoreHandle_t xSemaphoreCreateRecursiveMutexWithCaps(UBaseType_t uxMemoryCaps)

  Creates a recursive mutex with specific memory capabilities.

  This function is similar to xSemaphoreCreateRecursiveMutex(), except that it allows the memory allocated for the recursive mutex to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A recursive mutex created using this function must only be deleted using vSemaphoreDeleteWithCaps()

  参数:

    uxMemoryCaps -- Memory capabilities of the recursive mutex's memory (see esp_heap_caps.h)

  返回:

    Handle to the created recursive mutex or NULL on failure.

void vSemaphoreDeleteWithCaps(SemaphoreHandle_t xSemaphore)

  Deletes a semaphore previously created using one of the xSemaphoreCreate...WithCaps() functions.

  参数:

    xSemaphore -- A handle to the semaphore to be deleted.

static inline StreamBufferHandle_t xStreamBufferCreateWithCaps(size_t xBufferSizeBytes, size_t xTriggerLevelBytes, UBaseType_t uxMemoryCaps)

  Creates a stream buffer with specific memory capabilities.

  This function is similar to xStreamBufferCreate(), except that it allows the memory allocated for the stream buffer to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A stream buffer created using this function must only be deleted using vStreamBufferDeleteWithCaps()

  参数:

    - xBufferSizeBytes -- The total number of bytes the stream buffer will be able to hold at any one time.

    - xTriggerLevelBytes -- The number of bytes that must be in the stream buffer before unblocking

    - uxMemoryCaps -- Memory capabilities of the stream buffer's memory (see esp_heap_caps.h)

  返回:

    Handle to the created stream buffer or NULL on failure.

static inline void vStreamBufferDeleteWithCaps(StreamBufferHandle_t xStreamBuffer)

  Deletes a stream buffer previously created using xStreamBufferCreateWithCaps()

  参数:

    xStreamBuffer -- A handle to the stream buffer to be deleted.

static inline MessageBufferHandle_t xMessageBufferCreateWithCaps(size_t xBufferSizeBytes, UBaseType_t uxMemoryCaps)

  Creates a message buffer with specific memory capabilities.

  This function is similar to xMessageBufferCreate(), except that it allows the memory allocated for the message buffer to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  A message buffer created using this function must only be deleted using vMessageBufferDeleteWithCaps()

  参数:

    - xBufferSizeBytes -- The total number of bytes (not messages) the message buffer will be able to hold at any one time.

    - uxMemoryCaps -- Memory capabilities of the message buffer's memory (see esp_heap_caps.h)

  返回:

    Handle to the created message buffer or NULL on failure.

static inline void vMessageBufferDeleteWithCaps(MessageBufferHandle_t xMessageBuffer)

  Deletes a stream buffer previously created using xMessageBufferCreateWithCaps()

  参数:

    xMessageBuffer -- A handle to the message buffer to be deleted.

EventGroupHandle_t xEventGroupCreateWithCaps(UBaseType_t uxMemoryCaps)

  Creates an event group with specific memory capabilities.

  This function is similar to xEventGroupCreate(), except that it allows the memory allocated for the event group to have specific capabilities (e.g., MALLOC_CAP_INTERNAL).

  备注

  An event group created using this function must only be deleted using vEventGroupDeleteWithCaps()

  参数:

    uxMemoryCaps -- Memory capabilities of the event group's memory (see esp_heap_caps.h)

  返回:

    Handle to the created event group or NULL on failure.

void vEventGroupDeleteWithCaps(EventGroupHandle_t xEventGroup)

  Deletes an event group previously created using xEventGroupCreateWithCaps()

  参数:

    xEventGroup -- A handle to the event group to be deleted.

### Type Definitions

typedef void (*TlsDeleteCallbackFunction_t)(int, void*)

  Prototype of local storage pointer deletion callback.

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。