FIFO是一个内核对象,它实现了传统的先进先出队列,允许线程和 ISR 添加和删除任何大小的数据项。
概念
可以定义任意数量的 FIFO(仅受可用 RAM 的限制)。每个FIFO都由其存储器地址引用。
FIFO 具有以下关键属性:
- 已添加但尚未删除的数据项。队列作为简单的链表实现。
必须先初始化FIFO,然后才能使用。这会将其队列设置为空。
FIFO 数据项必须在字边界上对齐
,因为内核保留第一个字,用作指向队列中下一个数据项的指针。因此,保存 N个字节的应用程序数据的数据项需要N+4
或N+8
字节的内存。如果使用k_fifo_alloc_put()
添加数据项,则数据项没有对齐或保留空间要求,而是从调用线程的资源池中临时分配额外的内存。
数据项可以通过线程或 ISR 添加到 FIFO。如果存在等待线程,则该项目直接提供给等待线程;否则,该项目将添加到 FIFO 的队列中。
数据项可以通过线程从 FIFO 中删除。如果 FIFO 的队列为空,则线程可以选择等待给出数据项。任意数量的线程可以同时在空FIFO上等待。添加数据项时,会将其提供给等待时间最长的优先级最高的线程。
如果将多个数据项链接在一起形成单链接列表
,则可以在单个操作中将多个数据项添加到 FIFO 中。如果多个写入器将相关数据项集添加到 FIFO,则此功能非常有用,因为它可确保每个集中的数据项不会与其他数据项交错。向 FIFO 添加多个数据项也比一次添加一个数据项更有效。
定义FIFO
FIFO 是使用k_fifo
类型 定义的变量。然后必须通过调用k_fifo_init()
对其进行初始化。
struct k_fifo my_fifo;
k_fifo_init(&my_fifo);
也可以通过调用K_FIFO_DEFINE
在编译时定义和初始化空FIFO。
K_FIFO_DEFINE(my_fifo);
写入FIFO
通过调用k_fifo_put()
将数据项添加到FIFO。
注意:FIFO在写入时,第一个子为保留字段,用作指向队列中下一个数据项的指针。
struct data_item_t {
void *fifo_reserved; /* 1st word reserved for use by FIFO */
...
};
struct data_item_t tx_data;
void producer_thread(int unused1, int unused2, int unused3)
{
while (1) {
/* create data item to send */
tx_data = ...
/* send data to consumers */
k_fifo_put(&my_fifo, &tx_data);
...
}
}
可以通过调用k_fifo_put_list()
或k_fifo_put_slist()
将数据项的单链接列表
添加到 FIFO 中。
可以使用k_fifo_alloc_put()
将数据项添加到FIFO中。使用此 API,无需为内核在数据项中的使用保留空间,也不需要保留一个子,它是从调用线程的资源池中分配额外的内存,直到读取该项。
读取FIFO
通过调用k_fifo_get()
从FIFO中删除数据项。
void consumer_thread(int unused1, int unused2, int unused3)
{
struct data_item_t *rx_data;
while (1) {
rx_data = k_fifo_get(&my_fifo, K_FOREVER);
/* process FIFO data item */
...
}
}