二、freertos系统中常用机制整理。

软定时
osTimerId_t myTimer03Handle;
const osTimerAttr_t myTimer03_attributes = {
  .name = "myTimer03"
};

myTimer03Handle = osTimerNew(Callback03, osTimerPeriodic, NULL, &myTimer03_attributes);

osTimerStart (myTimer02Handle, 800);

void Callback03(void *argument)
{
  /* USER CODE BEGIN Callback03 */
	printf("stim 03\n");
	
	osTimerStop (myTimer03Handle);
  /* USER CODE END Callback03 */
}
信号(二值)
 myBinarySem02Handle = osSemaphoreNew(1, 0, &myBinarySem02_attributes);

//用于任务间的通知与同步
	if( osOK==osSemaphoreAcquire ( myBinarySem02Handle, osWaitForever))//超时等待,获取操作a的结果
		{
			//获取操作a的结果
		}

	if(osOK== osSemaphoreRelease (myBinarySem02Handle))//释放
		{
			//操作a
		}
信号 (计数)
osSemaphoreId_t myCountingSem01Handle;
const osSemaphoreAttr_t myCountingSem01_attributes = {
  .name = "myCountingSem01"
};
 myCountingSem01Handle = osSemaphoreNew(5,5, &myCountingSem01_attributes);
//第一个5,表示有5个信号量位置,第二个5表示初始化时,有五个计数信号可供申请(获取)。
	if(osOK== osSemaphoreAcquire (myCountingSem01Handle, osWaitForever ))//获取
	{
		printf("count acq num:%d \n",osSemaphoreGetCount (myCountingSem01Handle));//打印计数值
	}
	
	if(osOK== osSemaphoreRelease (myCountingSem01Handle))//释放
	{
		 printf("count release num:%d \n",osSemaphoreGetCount (myCountingSem01Handle));
	}			
信号 (互斥)
a (低)和b(最高),c(中) 任务,存在优先级差别,当低优先级的任务a被高一级的任务c打断,进入任务c里,而不是进入最高的b任务里,导致优先级发生翻转,这时采用互斥会尽量的避免优先级反转现象。(本质:暂时提升低优先级任务的优先级等级)

获取和释放需要在一个任务里配合使用。
osMutexId_t myMutex01Handle;
const osMutexAttr_t myMutex01_attributes = {
  .name = "myMutex01"
};
 myRecursiveMutex01Handle = osMutexNew(&myRecursiveMutex01_attributes);

 osMutexAcquire (myMutex01Handle, osWaitForever);//获取
	任务内容
 osMutexRelease(myMutex01Handle);//释放

事件组
#define EVENT_f1  (0x01 << 0)//设置事件掩码的位0
#define EVENT_f2  (0x01 << 1)//设置事件掩码的位1
osEventFlagsId_t myEvent01Handle;
const osEventFlagsAttr_t myEvent01_attributes = {
  .name = "myEvent01"
};
 myEvent01Handle = osEventFlagsNew(&myEvent01_attributes);

  osEventFlagsSet(myEvent01Handle,EVENT_f1  );//事件1置位
  osEventFlagsSet(myEvent01Handle,EVENT_f2  );//事件2置位
  
  osEventFlagsWait(myEvent01Handle,EVENT_f1  |EVENT_f1  ,osFlagsWaitAll,osWaitForever);
  //当两个标志都置位时,阻塞停止,否则会阻塞,之后内容不进行。

消息队列
typdef struct
{
	uint8_t bufs[10];
	
}udty;
udty uds;

osMessageQueueId_t myQueue01Handle;
const osMessageQueueAttr_t myQueue01_attributes = {
  .name = "myQueue01"
};
 myQueue01Handle = osMessageQueueNew (16, sizeof(udty), &myQueue01_attributes);
//16消息的数量,sizeof 是每个消息的大小。
	if(osMessageQueuePut (myQueue01Handle, (void *)&uds.busfs,0, 0)==osOK)//队列内容发送,不阻塞
	{
		//传输完成					 
	}

uint8_t chbuf[10];
	if(osMessageQueueGet (myQueue01Handle,(void *)&chbuf,NULL,osWaitForever)==osOK)//阻塞等待,获取队列的内容
	{
		//传输完成,得到数据
		printf("date:%s\n",chbuf);	
	}

保护访问的资源不被打断
任务中使用
   taskENTER_CRITICAL();
	
   taskEXIT_CRITICAL();
中断中使用
	uint32_t ulReturn;
	ulReturn = taskENTER_CRITICAL_FROM_ISR();

	taskEXIT_CRITICAL_FROM_ISR( ulReturn );
任务资源状态
	uint8_t List_sysyBuffer[300];
	vTaskList((char *)List_sysyBuffer);
	
	osThreadYield(); //任务调度,尝试更换到其他任务
	osDelay(uint32_t ticks);//阻塞延时,给其他任务执行的机会
	osThreadSuspend (osThreadId_t thread_id);//挂起
	osThreadResume (osThreadId_t thread_id);//恢复
	osThreadGetPriority (osThreadId_t thread_id);//设置优先级
在cmsis_os2.h 里有对应的任务创建等。
<think>好的,我现在需要回答用户关于FreeRTOS中xQueueSend函数是否会进入阻塞状态的问题。首先,我需要回忆一下FreeRTOS的队列操作函数的基本知识。记得队列是用于任务间通信的重要机制,而xQueueSend是常用的发送函数之一。 接下来,我应该确认xQueueSend的参数。这个函数的参数包括队列句柄、要发送的数据指针,以及阻塞时间。可能用户提到的阻塞状态与这个阻塞时间参数有关。如果队列已满,这时候的行为取决于阻塞时间的设置。如果设置为0,函数会立即返回失败;如果设置为portMAX_DELAY,则会无限期阻塞,直到队列有空间。其他数值的话,会阻塞指定的tick数。 然后,我需要考虑用户可能的疑问点。比如,阻塞状态下任务的状态变化。这时候任务会进入阻塞态,让出CPU给其他任务,这是FreeRTOS的调度机制。同时,可能需要提到阻塞时的队列写入机制,比如是否有其他任务或中断服务例程从队列读取数据,释放空间,从而唤醒被阻塞的任务。 另外,需要区分xQueueSend和xQueueSendToBack其实是同一个函数,而xQueueSendToFront则是将数据插入队列前端。这里可能需要注意用户是否混淆了这些函数,但问题明确提到xQueueSend,所以可以暂时忽略这点,但可能需要在回答中简要说明。 还要考虑中断安全的问题。如果在中断服务程序中使用xQueueSendFromISR,这时候不能使用阻塞,因为ISR中不允许阻塞。但用户的问题可能是在任务上下文中使用xQueueSend,所以重点应放在任务中的阻塞行为。 需要检查是否有其他可能的情况导致阻塞,比如调度器被挂起,或者是否有优先级更高的任务一直运行导致无法阻塞。不过一般来说,阻塞时间的设置是主要因素。 最后,要确保回答结构清晰,按照用户要求的步骤来,先结论,再参数说明,行为分析,使用建议,可能的应用场景示例。同时,要使用中文,避免技术术语的直译,保持口语化但准确。 可能还需要对比其他类似的函数,比如xQueueSendToBack和xQueueSendToFront,但用户的问题不涉及这些,所以可以省略或简单提及。重点放在xQueueSend的阻塞行为上。 现在整理思路,组织回答的结构:首先明确回答会或不会,然后解释参数的影响,详细说明不同情况下的行为,以及使用时需要注意的事项。可能还需要举例说明,帮助用户理解不同阻塞时间的应用场景。 检查是否有遗漏的点,比如任务优先级对阻塞的影响,或者阻塞期间其他任务的操作如何影响当前任务的状态。这些细节可以适当提及,以增强回答的全面性。 确保LaTeX格式正确,但用户的问题中可能不需要数学表达式,所以这一步可能不需要。但按照系统指令,如果有行内公式需要用$...$,但当前问题可能不涉及,所以暂时不需要处理。 最后,确保回答符合用户可见层的要求:结构清晰,逐步解决问题,真实可靠。避免错误信息,比如混淆函数名称或错误参数说明。</think>FreeRTOS中的`xQueueSend`函数**可能进入阻塞状态**,具体行为取决于其参数配置和使用场景。以下是逐步分析: --- ### 1. **函数原型与参数** ```c BaseType_t xQueueSend( QueueHandle_t xQueue, // 队列句柄 const void * pvItemToQueue, // 发送数据的指针 TickType_t xTicksToWait // 阻塞时间(单位:Tick) ); ``` --- ### 2. **阻塞条件分析** #### a. **队列未满时** - **行为**:立即将数据写入队列,函数直接返回`pdPASS`,**不会阻塞**。 - **示例**:如果队列剩余空间充足,发送操作瞬间完成。 #### b. **队列已满时** - **行为**:根据`xTicksToWait`参数决定是否阻塞: - **`xTicksToWait = 0`**:立即返回`errQUEUE_FULL`,**不阻塞**。 - **`xTicksToWait > 0`**:任务进入**阻塞状态**,等待队列有空间释放,最长等待时间为`xTicksToWait`个Tick。 - **`xTicksToWait = portMAX_DELAY`**:无限期阻塞,直到队列有空间(需配置`INCLUDE_vTaskSuspend`为1)。 --- ### 3. **阻塞状态下的任务行为** - **任务状态**:任务从`Running`态转为`Blocked`态,让出CPU给其他任务。 - **唤醒条件**:当其他任务或中断从队列中读取数据(如调用`xQueueReceive`),释放出空间时,发送任务被唤醒。 - **超时机制**:若在`xTicksToWait`时间内未获得空间,任务恢复为`Ready`态,函数返回`errQUEUE_FULL`。 --- ### 4. **使用场景示例** #### a. **非阻塞发送** ```c // 尝试发送数据,若队列满则立即返回 xQueueSend(xQueue, &data, 0); ``` 适用场景:实时性要求高,允许数据丢失的情况。 #### b. **有限阻塞发送** ```c // 等待最多100个Tick(如100ms,假设1 Tick=1ms) xQueueSend(xQueue, &data, 100); ``` 适用场景:允许短暂等待,平衡实时性和数据可靠性。 #### c. **无限阻塞发送** ```c // 阻塞直到队列有空间 xQueueSend(xQueue, &data, portMAX_DELAY); ``` 适用场景:数据必须发送成功,无实时性约束。 --- ### 5. **注意事项** - **中断中调用**:在中断服务程序(ISR)中需使用`xQueueSendFromISR`,且**禁止阻塞**。 - **优先级影响**:高优先级任务可能抢占当前任务,影响阻塞时间精度。 - **内存安全**:确保`pvItemToQueue`指向的数据在发送过程中有效(如不使用栈变量)。 --- ### 总结 `xQueueSend`是否阻塞取决于**队列状态**和`xTicksToWait`参数。合理设置阻塞时间可平衡系统实时性与数据可靠性,需根据具体场景选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值