【FreeRTOS】FreeRTOS操作系统几种典型的进程间通信方式及使用示例

一 进程间通信概述

        【FreeRTOS】FreeRTOS操作系统几种典型的进程间通信方式及使用示例_第1张图片

        FreeRTOS 提供了多种进程间通信(IPC)机制,用于任务之间的同步和数据交换。这边列举几个典型的进程间通信机制,包括 消息队列、信号量、事件组、任务通知。

        更多复杂的机制和用法可以参考官方文档:FreeRTOS Kernel 开发人员文档 - FreeRTOS™

二 消息队列(Queues)

【1】概述

        参考官方文档(FreeRTOS 队列 - FreeRTOS™)。

        队列又称消息队列,是一种常用于任务间通信的数据结构, 队列可以在任务与任务间、 中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息。

FreeRTOS 中使用队列数据结构实现任务异步通信工作,具有如下特性:

  • 消息支持先进先出方式(FIFO)排队,支持异步读写工作方式。
  • 读写队列均支持超时机制。
  • 消息支持后进先出方式排队, 往队首发送消息(LIFO) 。
  • 可以允许不同长度(不超过队列节点最大值)的任意类型消息。
  • 一个任务能够从任意一个消息队列接收和发送消息。
  • 多个任务能够从同一个消息队列接收和发送消息。
  • 当队列使用结束后,可以通过删除队列函数进行删除。

        队列是任务间通信的主要形式。它们可以用于在任务之间 以及中断和任务之间发送消息。在大多数情况下,队列用作线程安全的 FIFO(先进先出)缓冲区, 新数据被发送到队列的后面,但也可以发送到前面。

【FreeRTOS】FreeRTOS操作系统几种典型的进程间通信方式及使用示例_第2张图片

        向队列中写入和从队列中读取。此示例中创建队列来保存 5 个项目,并且 队列永远不会满。
        

    【2】例程

            mian中初始化时,创建一个长度为5的队列 xTemperatureQueue ,用于将 TMP_Task 任务中获取的温度数据,传送给 STA_Task 任务进行打印:

    #include "ddl.h"
    #include "Dbg.h"
    
    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h"
    #include "semphr.h"
    #include "event_groups.h"
    
    static void App_SysClkInit(void)
    {
        stc_sysctrl_clk_cfg_t stcCfg;
        stc_sysctrl_pll_cfg_t stcPLLCfg;
    
        Sysctrl_SetPeripheralGate(SysctrlPeripheralFlash, TRUE);    ///< 使能FLASH模块的外设时钟
        Flash_WaitCycle(FlashWaitCycle1);
        Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);             ///< PLL使用RCH作为时钟源,因此需要先设置RCH
    
        stcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     ///< RCH 4MHz
        stcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  ///< PLL 输出48MHz
        stcPLLCfg.enPllClkSrc = SysctrlPllRch;              ///< 输入时钟源选择RCH
        stcPLLCfg.enPllMul    = SysctrlPllMul12;            ///< 4MHz x 12 = 48MHz
        Sysctrl_SetPLLFreq(&stcPLLCfg);
    
        ///< 选择PLL作为HCLK时钟源;
        stcCfg.enClkSrc  = SysctrlClkPLL;
        ///< HCLK SYSCLK/2
        stcCfg.enHClkDiv = SysctrlHclkDiv1;
        ///< PCLK 为HCLK/8
        stcCfg.enPClkDiv = SysctrlPclkDiv1;
        ///< 系统时钟初始化
        Sysctrl_ClkInit(&stcCfg);
    
    //    ///< 使用外部晶振
    //    Sysctrl_SetXTHFreq(SysctrlXthFreq8_16MHz);
    //    Sysctrl_XTHDriverCfg(SysctrlXtalDriver1);
    //    Sysctrl_SetXTHStableTime(SysctrlXthStableCycle16384);
    //    Sysctrl_ClkSourceEnable(SysctrlClkXTH, TRUE);
    //    delay1ms(10);
    
    //    ///< 时钟切换
    //    Sysctrl_SysClkSwitch(SysctrlClkXTH);
    }
    
    void STA_Task(void* param);
    void TMP_Task(void* param);
    
    static TaskHandle_t AppStaTask_handle = NULL;
    static TaskHandle_t AppTmpTask_handle = NULL;
    
    #define STA_TASK_SIZE 128
    #define TMP_TASK_SIZE 128
    
    int FreeRTOS_TaskCreate(void)
    {
    	BaseType_t xReturn1 = pdPASS;
    	BaseType_t xReturn2 = pdPASS;
        
    	//创建心跳灯任务
    	xReturn1 = xTaskCreate((TaskFunction_t )STA_Task,       //任务入口函数
                            (const char*    )"StaTask",         //任务名字
                            (uint16_t       )STA_TASK_SIZE,     //任务栈大小
                            (void*          )NULL,              //任务入口函数参数
                            (UBaseType_t    )2,                 //任务的优先级
                            (TaskHandle_t*  )&AppStaTask_handle);//任务控制块指针
                            
        //创建加热任务(按键蜂鸣加热温度采样)
    	xReturn2 = xTaskCreate((TaskFunction_t )TMP_Task,       //任务入口函数
                            (const char*    )"TmpTask",         //任务名字
                            (uint16_t       )TMP_TASK_SIZE,     //任务栈大小
                            (void*          )NULL,              //任务入口函数参数
                            (UBaseType_t    )4,                 //任务的优先级
                            (TaskHandle_t*  )&AppTmpTask_handle);//任务控制块指针
    
       if (pdPASS != xReturn1 || pdPASS != xReturn2)
        {
            return -1;  // 任务创建失败
        }
    
       vTaskStartScheduler();//启动调度
       
       return 0;
    }
    
    
    
    QueueHandle_t xTemperatureQueue;
    
    int32_t main(void)
    {
        //系统时钟
        App_SysClkInit();
        
        // 创建队列,队列长度为5,每个元素大小为sizeof(float)
        xTemperatureQueue = xQueueCreate(5, sizeof(float));
        if (xTemperatureQueue == NULL) {
            Dbg_Printf("Failed to create queue\r\n");
            while(1);
        }
    
        //串口调试打印初始化
        Dbg_Init();
        Dbg_Cfg();
        
        //创建任务并启动
        FreeRTOS_TaskCreate();
    
        while(1);
    }
    
    
    
    /************************************************************

    你可能感兴趣的:(嵌入式,单片机,嵌入式硬件,mcu,stm32,rtos)