解决STM32运行μC/OS-II系统时出现任务突然无法调度的情况办法
本文为笔者遇到的问题,所总结的经验。
一、调用了采用Systick做延迟。
因为μC/OS-II实时操作系统的心跳一般就是用Systick提供的,而采用Systick做延迟会打断心跳,或者直接停止了Systick时钟的运行,导致系统无法进入调度。当然也可以在延迟函数做一些改动来避免。
二、进入中断时没有“告诉”操作系统进入了中断
进入中断的时候一般需要调用OSIntEnter();和OSIntExit();函数把中断服务函数里的内容框起来。这两个函数其实里面是一个计数器,进入中断计数器+1,离开中断计数器-1 ,这样操作系统可以避免在中断或中断嵌套中发生任务调度而发生错误。例如下:
void USB_LP_CAN1_RX0_IRQHandler()
{
static unsigned char cData[8];
unsigned char err;
CanRxMsg RxMessage;
int i=0;//
OSIntEnter();//通知系统进入了中断
CAN_Receive(CAN1, 0, &RxMessage);
g_iCanID = RxMessage.StdId;//读取CANID
g_cCanRTR = RxMessage.RTR;//读取帧类型
g_cCanDLC = RxMessage.DLC;//读取长度
for(i=0;i<g_cCanDLC;i++)
{
cData[i] = RxMessage.Data[i];//读取CAN数据
}
for(i=0;i<3;i++)//如果发送失败尝试连续发送3次
{
err = OSMboxPost(BoxCan,cData);//发送cData的数据
if(err == OS_NO_ERR)//如果发送成功
{
break;//跳出循环
}
}
OSIntExit();//通知系统完成了中断
}
三、中断过早打开
这个情况是笔者在调试CAN总线的时候遇到的,一般笔者习惯在最一开始就吧所有的硬件外设初始化完毕,包括NVIC。然后在初始化系统等相关软件。
如果一旦单片机在没有上电的时候CAN总线就有数据,当上电后单片机可能在系统没有成功初始化之前就发生中断,并且在中断中有影响系统的语句例如关于:邮箱、信号量等操作时就极有可能会出现错误。可能会出现系统运行一会突然就无法进行任务调度了。
建议在第一个任务启动心跳之后再初始化NVIC。保证系统再初始化完成之前或创建任务完成之前没有任何的打扰。