FIFO的应用案例(基于Zephyr OS )

目录

概述

1.  软硬件环境

1.1 软件开发环境

1.2 硬件环境 

2 FIFO的函数接口

3 FIFO的应用函数实现

3.1 实现步骤

3.2  代码设计 

3.3 测试代码实现

3.4 源代码文件

4 编译和测试

4.1 编译代码

 4.2 测试


概述

本文介绍了在nRF52832开发板上使用Zephyr操作系统进行FIFO(先进先出队列)功能开发的软硬件环境及实现步骤。软件开发环境基于Nordic提供的nRF Connect SDK,集成了Zephyr平台、编译工具链和VS Code开发环境。硬件环境为nRF52832开发板,具备丰富的接口和调试功能。文章详细描述了FIFO的API函数及其使用方法,包括初始化、数据放入和获取等操作。通过生产者-消费者模型,展示了如何在Zephyr中实现FIFO功能,并提供了完整的代码示例。最后,文章介绍了使用VS Code编译和测试代码的过程,确保功能正常运行。

1.  软硬件环境

1.1 软件开发环境

nordic提供了基于zephyr平台sdk, 其提供了大量的demo可供开发者参考和使用,同时nordi还提供一个集成的软件库工具,方便开发者安装相应的SDK和编译工具链。集成环境同时包含了其他的一些软件,非常便于进行项目开发。

软件工具功能版本信息
nRF Connect SDK nordic提供基于zephyr的代码库v2.9.0 
nRF Connect SDK Toolchain代码编译工具v2.9.1
VS-CODE集成开发环境v1.99.3 
nRF Connect for Desktopnordic集成工具链v5.1.0
nRF Connect手机App

手机App下载地址:

https://nav.nordicsemi.com/search?query=nRF%20Connect

1.2 硬件环境 

本案例是在nRF52832开发板(nRF52-DK)上实现的,该开发板nRF52832的主要特点如下:

1)板载j-link调试接口

2)引出所有 IO接口,用户可根据实际应用,外载其他设备

3)支持4个LED

4)支持4路Key接口

5)板载UART调试接口,方便打印调试信息

2 FIFO的函数接口

zephyr OS提供了操作FIFO API,其具体函数如下:

函数描述
K_FIFO_DEFINE(name)定义并初始化FIFO
k_fifo_init(fifo)运行时初始化FIFO
k_fifo_put(fifo, data)向FIFO放入数据
k_fifo_get(fifo, timeout)从FIFO获取数据
k_fifo_is_empty(fifo)检查FIFO是否为空

 具有使用方法可以参考原文:

Zephyr OS 中的 FIFO 接口应用介绍-CSDN博客

3 FIFO的应用函数实现

3.1 实现步骤

在zephyr OS使用FIFO功能的步骤如下:

Step-1: 使用K_FIFO_DEFINE初始化一个FIFO

Step-2:   使用k_fifo_put接口发送数据

Step-3:   使用 k_fifo_get 函数接收数据,同时释放内存 


注意点:
在在zephyr OS使用FIFO需要包括如下头文件:

#include <zephyr/kernel.h>

3.2  代码设计 

1)定义User的数据格式

struct user_data_t {
    void *fifo_reserved;
    int value;
};

2)创建和初始化FIFO

static K_FIFO_DEFINE(fifo_tx_data);

 3) 设计Producer用于生产数据

void producer_thread( void )
{
    printk(" \r\n");
    printk(" \r\n");

    printk("Produced: run thread \r\n ");
    for (int i = 0; i < 300; i++) 
    {
        // 动态分配数据项
        struct user_data_t *tx = k_malloc(sizeof(*tx));
        tx->value = i;
        
        // 放入FIFO
        k_fifo_put(&fifo_tx_data, tx);
        
        printk("Produced: %d \r\n", i);
        k_sem_give(&nus_write_sem);
        k_sleep(K_MSEC(100));
    }
}

4)设计consumer用于使用数据

void consumer_thread( void )
{
    int err;

    printk(" \r\n");
    printk(" \r\n");
    err = k_sem_take(&nus_write_sem, K_MSEC(1000));
    if (err) {
        printk("Consumed: NUS send timeout  \r\n");
    }

    struct user_data_t *item = k_fifo_get(&fifo_tx_data, K_NO_WAIT);
    if (item != NULL) 
    {
        printk("Consumed: %d \r\n", item->value);
        k_free(item);
    } 
    else 
    {
        printk("Consumed: Timeout waiting for data \r\n");
    }
}

3.3 测试代码实现

1)定义生产者线程 

 /**
  *    producer 
  */

 int main_producer_handler(void)
 {
     for (;;) 
     {
        producer_thread();
     }
 }


 #define STACKSIZE                        1024
 #define PRIORITY                         7


 K_THREAD_DEFINE(  main_producer_id, STACKSIZE, main_producer_handler, NULL, NULL,
                   NULL, PRIORITY, 0, 0);

2) 定义消费者线程 

 /**
  *    consumer  
  */
 int main_customers_handler(void)
 {
     for (;;) 
     {
        consumer_thread();
     }
 }


 #define STACKSIZE_CUSTOMER               1024
 #define PRIORITY_CUSTOMER                8


 K_THREAD_DEFINE(  main_customers_id, STACKSIZE_CUSTOMER, main_customers_handler, NULL, NULL,
                   NULL, PRIORITY_CUSTOMER, 0, 0);      

3.4 源代码文件

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name        :  test_fifo.h
 * Description      :  FIFO test demo 
 ******************************************************************************
 * @attention
 *
 *  COPYRIGHT:    Copyright (c) 2025  mingfei_tang
 *  DATE:         MAR 27th, 2025
 ******************************************************************************
 */
/* USER CODE END Header */
#include "test_fifo.h"
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>


 K_SEM_DEFINE(nus_write_sem, 0, 1);


// 数据项结构
struct user_data_t {
    void *fifo_reserved;
    int value;
};
 
static K_FIFO_DEFINE(fifo_tx_data);


void producer_thread( void )
{
    printk(" \r\n");
    printk(" \r\n");

    printk("Produced: run thread \r\n ");
    for (int i = 0; i < 300; i++) 
    {
        // 动态分配数据项
        struct user_data_t *tx = k_malloc(sizeof(*tx));
        tx->value = i;
        
        // 放入FIFO
        k_fifo_put(&fifo_tx_data, tx);
        
        printk("Produced: %d \r\n", i);
        k_sem_give(&nus_write_sem);
        k_sleep(K_MSEC(100));
    }
}

void consumer_thread( void )
{
    int err;

    printk(" \r\n");
    printk(" \r\n");
    err = k_sem_take(&nus_write_sem, K_MSEC(1000));
    if (err) {
        printk("Consumed: NUS send timeout  \r\n");
    }

    struct user_data_t *item = k_fifo_get(&fifo_tx_data, K_NO_WAIT);
    if (item != NULL) 
    {
        printk("Consumed: %d \r\n", item->value);
        k_free(item);
    } 
    else 
    {
        printk("Consumed: Timeout waiting for data \r\n");
    }
}

 /**
  *    producer 
  */

 int main_producer_handler(void)
 {
     for (;;) 
     {
        producer_thread();
     }
 }


 #define STACKSIZE                        1024
 #define PRIORITY                         7


 K_THREAD_DEFINE(  main_producer_id, STACKSIZE, main_producer_handler, NULL, NULL,
                   NULL, PRIORITY, 0, 0);


 /**
  *    consumer  
  */
 int main_customers_handler(void)
 {
     for (;;) 
     {
        consumer_thread();
     }
 }


 #define STACKSIZE_CUSTOMER               1024
 #define PRIORITY_CUSTOMER                8


 K_THREAD_DEFINE(  main_customers_id, STACKSIZE_CUSTOMER, main_customers_handler, NULL, NULL,
                   NULL, PRIORITY_CUSTOMER, 0, 0);                   
 /** End of  */

4 编译和测试

4.1 编译代码

使用Vs-code创建工程,并且编写代码,其软件架构如下:

 4.2 测试

编译完成后,下载代码至MCU,运行代码,其运行结果如下:

1) 启动过程

2) 使用FIFO生产和消费数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值