冷启动与热启动估计是在大多数入门学51的时候接触到的知识,总结一下:
所谓冷启动,也就是一般所说的
上电复位
,
冷启动后片内外RAM的内容是随机的
,通常是0x00或0xFF;单片机的热启动是通过外部电路给运行中的单片机的复位端一复位电平而实现的,也就是所说的
按键复位或看门狗复位
。复位后,
RAM的内容都没有改变。
一般来说我们不需要对此特别注意,在对STM32的程序设计中,涉及到冷启动或者热启动的操作无非是断电上电或者按下复位按钮。但是在基于RTOS中的设计,可能就需要注意一个容易入坑的地方了。
先说问题吧。在RTOS中编写创建了多个线程,以两个线程为例,一个是点灯的线程,用于指示系统是否跑飞;第二个线程为用户线程,用于操作某种外设A。程序下载到stm32F1XX的芯片后,可以看到点灯线程正常运行,小灯1S的频率在闪烁,但是A却无法正常工作,除非在此时按下复位按键,才能正常工作,但是只要断电并且上电(相当于冷启动),A就无法跑起来,只能通过按下复位按键(热启动),才能让A正常工作。与之相对应的,点灯线程一切正常,无论冷启动还是热启动,均能在启动后正常工作。
到这里就可以排除KEIL软件的配置问题,因为有时候下载配置没有勾选reset and run 也会导致该问题的发生,如下图:
那么问题到底在哪,其实原因就在于冷热启动的问题,单片机内部通过boot0和boot1的跳帽配置会选择进入用户代码区还是底层下载。那么无论配置成什么模式。单片机均需要一定的时间进行操作,这一点在基于RTOS的编程中更加明显,因为多任务的初始化均需要时间。
导致这个问题的发生就在于我们冷启动的时候任务在调用某外设初始化的时候单片机内部其他的任务或者片内资源正在运行或者载入,类似于任务之间的依赖关系,只有任务A初始化完毕任务B才能进行初始化。但热启动的时候是不掉电的,此时RAM不改变,该启动方式的前提是内部该载入的,该分配资源的都结束了。
解决方法:在RTOS中进行任务初始化创建的前面进行等待,调用系统时钟延时一段时间即可:
int main(void)
{
HAL_Init();
SystemClock_Config();
bCut_Bsp_Init();
HAL_Delay(1000); //进行延时等待一段时间
。。。
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
osThreadDef(UsartRev, UsartRevTask, osPriorityIdle, 0, 128);
UsartRevHandle = osThreadCreate(osThread(UsartRev), NULL);
osThreadDef(UsartSend, UsartSendTask, osPriorityIdle, 0, 128);
UsartSendHandle = osThreadCreate(osThread(UsartSend), NULL);
。。。
}