FreeRTOS 多任务系统——任务切换、任务管理方式心得

目前在进行对使用FreeRTOS的项目的代码升级,之前采用的主逻辑任务切换模式:由一个任务来进行逻辑上为串行的不同功能切换,其他任务分别负责通信实时传输、传感器检测和电机控制,系统中断中采用变量传递参数而非二值信号量。

这个模式有两个问题:

(1)传感器的信号传递过于复杂:当一个传感器信号(如上升沿)到来时,改变传感器标志变量的值,然后等待任务轮询到该变量的改变,再改变任务中的逻辑步骤变量值,来使任务下一次轮询时进入下一步逻辑,且任务通过轮询来不断检测来自队列的逻辑执行命令。这样的机制会导致传感器信号传递的实时性降低。
(2)由于需要接收队列中的命令的同时还需要自动执行当前的逻辑步骤,任务设计就必须设计成轮询机制,这样无法利用阻塞机制来提高系统资源的利用率,还大大增加了任务设计的复杂性,出BUG概率大大增加,且修改BUG牵一发动全身的现象极其严重。

基于以上原因我决定重新设计任务切换、管理系统,以充分利用RTOS任务阻塞和二值信号量同步中断、任务的优点。

这个项目的特点是:

1.功能性任务不可同时运行
2.对传感器信号和串口通信实时性要求高
3.对电机的电流检测实时性要求高
4.每次执行功能性任务都要求从任务头开始执行,即使中途被其他功能性任务中断

基于以上特点,我决定采用添加/删除任务的方式来进行任务切换。
在串口接收任务中进行任务的创建,每个功能性任务都由以下结构组成,以系统初始化任务举例:

void InitTask(void const * argument)
{
  /* USER CODE BEGIN InitTask */
	PeriStatus.SystemStatue = TASK_Init;//记录任务类型用于状态上传
	HandleTemp = TaskInitHandle;//记录任务句柄
	if(PeriStatus.FeedRest != Motor_Init)MotorCtrl(FeedRestType, Motor_Reset);//电机1复位
	FLASH_EEPROM_Write();//写入FLASH
	RotateReset();//主执行机构复位
	if(PeriStatus.Hold != Motor_Init)MotorCtrl(HoldType, Motor_Reset);//电机2复位
	if(PeriStatus.Slide != Motor_Init)MotorCtrl(SlideType, Motor_Reset);//电机3复位
  /* Infinite loop */
  for(;;)
  {
	if((PeriStatus.Hold == Motor_Init)&&
	(PeriStatus.Slide == Motor_Init)&&
	(PeriStatus.Rotate == Motor_Init)&&
	(PeriStatus.FeedRest == Motor_Init)&&
	(PeriStatus.Feed == Motor_Init))//所有机构复位完成
	{
		PeriStatus.SystemStatue = TASK_Default;//清除当前任务类型
		HandleTemp = defaultTaskHandle;//任务句柄恢复为默认任务
		vTaskDelete(NULL);//删除当前任务
	}
    osDelay(50);
  }
  /* USER CODE END InitTask */
}

任务在执行完毕后会自行删除,如果中途串口接收任务想要创建别的功能性任务,只需利用HandleTemp储存的当前任务句柄将任务删除,再创建新的任务即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

食熊鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值