关于freertos任务通知模拟队列无法传输任务值为0的问题

文章讨论了在使用FreeRTOS的freertos任务通知功能时,如何处理0值数据的传输问题,对比了与队列的差异,指出任务通知模拟队列在接收到0值时不会让任务退出阻塞状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    最近在学习freertos任务通知的时候,跟着正点原子教程做了个用任务通知模拟队列和事件标志组的小实验,结果发现用队列是可以传递为0的数据的,而用任务通知模拟队列就无法传递为0的数据,在用xTaskNotify(myTask01Handle, key ,eSetValueWithoutOverwrite);传递为值0的数据key时,此时任务通知模拟队列的接收函数xTaskNotifyWait(0,0xFFFFFFFF,&value,portMAX_DELAY);不会让任务退出阻塞状态。

硬件:正点原子miniV3.0开发板

软件:keil5、stm32cubemx

实验主要代码如下:

void StartTask01(void *argument)
{
  /* USER CODE BEGIN StartTask01 */
  /* Infinite loop */
	QueueSetMemberHandle_t member_handle;
	uint32_t value;
  for(;;)
  {
		//osMessageQueueGet(myQueue02Handle ,&key ,0 , portMAX_DELAY);
		//myprintf("获取队列数据:%d\r\n", key);
		
		xTaskNotifyWait(0,0xFFFFFFFF,&value,portMAX_DELAY);
		if(value != NULL)
			myprintf("任务通知值为:%d\r\n",value);
		osDelay(1000);
  }
}


uint8_t state;
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
	uint32_t key = 0;

  for(;;)
  {
		key = KEY_Scan(0);    //保存返回值,方便后面判断
		
		if(key == KEY0_PRES)
		{
			if(myTask01Handle != NULL)
			{
				  key = 0;
				  
			    state = xTaskNotify(myTask01Handle, key ,eSetValueWithoutOverwrite);
				  if(state == pdPASS)  myprintf("任务通知模拟队列传输:%d\r\n",key);
			}
		}
		if(key == KEY1_PRES)
		{
				if(myTask01Handle != NULL)
			{
				  key = 200;
				  myprintf("任务通知模拟队列传输:%d\r\n",key);
			    xTaskNotify(myTask01Handle, key ,eSetValueWithoutOverwrite);
			}
        }
       if(key == WKUP_PRES)
		{
			key = 0;
			state = osMessageQueuePut(myQueue02Handle ,&key ,0 , portMAX_DELAY);
			if(state == osOK)  myprintf("往队列写入数据为:%d\r\n",key);
		}
		
    osDelay(10);
   }
}

分别测试队列写入读取数据和任务通知模拟队列写入读取数据,按下key_wkup就是向队列中写入数据,按下key0、key1就是通过任务通知模拟队列写入数据,结果分别如下:

我们可以看到,用队列写入为0的数据,另一个任务可以接收到;而用任务通知模拟队列写入为0的数据,另一个任务无法接收;

至于原因是为什么,首先我们直到队列接收函数判断队列中是否有数据是通过一个指针,只要该指针指向的地址不为NULL即有数据,不管这个地址中的值是0还是其他值,该队列接收函数都会让任务退出阻塞并读取该数据,因此队列可以传输为0的数据;

那为什么任务通知模拟队列无法传输为0的数据呢?我个人没有找到具体代码来进行验证,希望有大佬能说一下。不过由于xTaskNotifyWait(0,0xFFFFFFFF,&value,portMAX_DELAY)函数既可以做任务通知模拟队列接收函数,也可以做任务通知模拟事件标志组接收函数,再结合这位作者的博客中所说:FreeRTOS操作系统——任务通知模拟消息邮箱及事件标志组(十八)-优快云博客

因此我们可以推断,在该函数的具体代码实现中,只有任务通知值不为0才可以使该任务退出阻塞状态;这也就说明了为什么传输为0的数据时,目标任务无法接收到该数据并退出阻塞状态;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值