FreeRTOS任务间通信,怎么实现?

描述

FreeRTOS 是一个可裁剪、可剥夺型的多任务内核,十分好用,而且没有任务数限制,在此之前分析过很多了,简单来说,FreeRTOS实时系统能够创建多个独立的任务,并且任务之间互不干扰,为了这一点的实现,每个任务都应该有自己的堆栈空间。当任务进行切换,执行环境则保存到该任务的堆栈中,所以,当一段时间后切换回该任务,它能够精确地回复上次工作时的状态。

之前也汇总了一些教程,参考精选汇总 | freertos从基础到高级篇系列

FreeRTOS 提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等,本篇主要说一下任务通信,任务创建之后并不是一起运行的,而是通过优先级顺序进行任务的调用来实现的。

轮子也造好了,很多我们可以直接拿来用,ARM Cortex 微控制器软件接口标准是cmsis,且是与供应商无关的硬件抽象层,CMSIS-RTOS是实时操作系统的通用API,简单来说就是将Freertos、Rtthread等操作系统再进行一次封装,形成通用的API函数,目的是使移植更方便。这里我们选用接口是CMSIS_V2,之前也讲到过stm32CubeIDE中CMSIS_V1和CMSIS_V2选项的区别。

FreeRTOS

首先创建两个任务myTask01和myTask02,如下图所示:

FreeRTOS

创建2个事件myEvent01,myEvent02,如下图所示:

FreeRTOS

拉下来也可以配置以下信息,在此我们默认配置计数信号量、分配方式、控制块名称等配置信息。

生成代码之后任务和事件如下代码:

 

/* Definitions for myTask01 */
osThreadId_t myTask01Handle;
const osThreadAttr_t myTask01_attributes = {
  .name = "myTask01",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
...
/* Definitions for myEvent02 */
osEventFlagsId_t myEvent02Handle;
const osEventFlagsAttr_t myEvent02_attributes = {
  .name = "myEvent02"
};

 

这个是创建任务的句柄,代码如下:

 

  /* creation of myTask01 */
  myTask01Handle = osThreadNew(StartTask01, NULL, &myTask01_attributes);

  /* creation of myTask02 */
  myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);

 

我们改写代码,实现task2往task发送信号,实现简单的任务通信,代码如下。

 

/* USER CODE END Header_StartTask01 */
void StartTask01(void *argument)
{
    /* USER CODE BEGIN StartTask01 */
    /* Infinite loop */
    osStatus_t os_Status;

   while(1)
   {
    os_Status = osEventFlagsWait(myTask02Handle,   /* 事件标志组ID */
            COMM2_EVENT,       /* 等待事件标志位0与事件标志位1 */
            osFlagsWaitAny,    /* 逻辑或 */
               osWaitForever      /* 一直等待 */
            );
    if(os_Status == COMM1_EVENT)
    {
       printf("startTask02 is running.
");
    }
   }
    /* USER CODE END StartTask01 */
}

/* USER CODE BEGIN Header_StartTask02 */

 

osEventFlagsWait函数的具体实现以及定义如下图所示:

FreeRTOS

osEventFlagsSet就是往某个任务的句柄发送一个信号,实现如下

 

/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
 /* USER CODE BEGIN StartTask02 */
 /* Infinite loop */
 for(;;)
 {
   osEventFlagsSet(myEvent01Handle, COMM1_EVENT);
   osDelay(1);
 }
 /* USER CODE END StartTask02 */
}
   

 

最后就可以实现多个任务间的通信了。

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分