FIFO是一个内核对象,它实现了传统的先进先出队列,允许线程和 ISR 添加和删除任何大小的数据项。

概念

可以定义任意数量的 FIFO(仅受可用 RAM 的限制)。每个FIFO都由其存储器地址引用。
FIFO 具有以下关键属性:

  • 已添加但尚未删除的数据项。队列作为简单的链表实现。

必须先初始化FIFO,然后才能使用。这会将其队列设置为空。
FIFO 数据项必须在字边界上对齐,因为内核保留第一个字,用作指向队列中下一个数据项的指针。因此,保存 N个字节的应用程序数据的数据项需要N+4N+8字节的内存。如果使用k_fifo_alloc_put()添加数据项,则数据项没有对齐或保留空间要求,而是从调用线程的资源池中临时分配额外的内存。
数据项可以通过线程或 ISR 添加到 FIFO。如果存在等待线程,则该项目直接提供给等待线程;否则,该项目将添加到 FIFO 的队列中。
数据项可以通过线程从 FIFO 中删除。如果 FIFO 的队列为空,则线程可以选择等待给出数据项。任意数量的线程可以同时在空FIFO上等待。添加数据项时,会将其提供给等待时间最长的优先级最高的线程。
如果将多个数据项链接在一起形成单链接列表,则可以在单个操作中将多个数据项添加到 FIFO 中。如果多个写入器将相关数据项集添加到 FIFO,则此功能非常有用,因为它可确保每个集中的数据项不会与其他数据项交错。向 FIFO 添加多个数据项也比一次添加一个数据项更有效。

定义FIFO

FIFO 是使用k_fifo类型 定义的变量。然后必须通过调用k_fifo_init()对其进行初始化。

  1. struct k_fifo my_fifo;
  2. k_fifo_init(&my_fifo);

也可以通过调用K_FIFO_DEFINE在编译时定义和初始化空FIFO。

  1. K_FIFO_DEFINE(my_fifo);

写入FIFO

通过调用k_fifo_put()将数据项添加到FIFO。
注意:FIFO在写入时,第一个子为保留字段,用作指向队列中下一个数据项的指针。

  1. struct data_item_t {
  2. void *fifo_reserved; /* 1st word reserved for use by FIFO */
  3. ...
  4. };
  5. struct data_item_t tx_data;
  6. void producer_thread(int unused1, int unused2, int unused3)
  7. {
  8. while (1) {
  9. /* create data item to send */
  10. tx_data = ...
  11. /* send data to consumers */
  12. k_fifo_put(&my_fifo, &tx_data);
  13. ...
  14. }
  15. }

可以通过调用k_fifo_put_list()k_fifo_put_slist()将数据项的单链接列表添加到 FIFO 中。
可以使用k_fifo_alloc_put()将数据项添加到FIFO中。使用此 API,无需为内核在数据项中的使用保留空间,也不需要保留一个子,它是从调用线程的资源池中分配额外的内存,直到读取该项。

读取FIFO

通过调用k_fifo_get()从FIFO中删除数据项。

  1. void consumer_thread(int unused1, int unused2, int unused3)
  2. {
  3. struct data_item_t *rx_data;
  4. while (1) {
  5. rx_data = k_fifo_get(&my_fifo, K_FOREVER);
  6. /* process FIFO data item */
  7. ...
  8. }
  9. }