单片机型号:STM32L053R8T6
W5500驱动程序完成后,运行时,单片机死机。W5500驱动程序先前已经在项目中具体应用过,运行的比较稳定。这次移植后,没有做改动,但是单片机运行时死机。
此项目与先前项目的不同点在于,项目中有FreeRTOS操作系统运行,原先的项目没有,最后将问题聚焦于W5500的构造函数上,如下程序所示:
CW5500::CW5500(void):CSpi()
{
//uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};
//注册相关的函数
reg_wizchip_cris_cbfunc(w5500_cris_enter, w5500_cris_exit);
reg_wizchip_cs_cbfunc(w5500_cs_select, w5500_cs_deselect);
reg_wizchip_spi_cbfunc(w5500_spi_readbyte, w5500_spi_writebyte);
//硬件复位w5500
this->reset();
//软件复位w5500
ctlwizchip(CW_RESET_WIZCHIP, (void*)NULL);
//初始化socket buffer
ctlwizchip(CW_INIT_WIZCHIP, (void*)memsize);
}
void CW5500::reset(void)
{
this->W5500_RESET.Set_1();
Target.Delayms(10);
this->W5500_RESET.Set_0();
Target.Delayms(10);
this->W5500_RESET.Set_1();
Target.Delayms(10);
}
驱动程序在构造函数中调用了延时函数,而延时函数具体的实现如下:
void CTarget::Delayms(uint16_t u16_ms)
{
osDelay(u16_ms);
}
延时函数直接调用了FreeRTOS操作系统的osDelay。原先程序的延时函数是如下实现的:
void CTarget::Delayms(uint16_t u16_ms)
{
HAL_Delay(u16_ms);
#if IWDG_MODE != 0
this->Iwdg.Refresh();
#endif
}
再看main函数,程序如下:
int main(void)
{
osThreadDef(DefaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
DefaultTaskHandle = osThreadCreate(osThread(DefaultTask), NULL);
osKernelStart();
//以下程序不会被执行
while (1)
{
}
}
FreeRTOS操作系统是在main函数中启动的,也就是只有执行完osKernelStart函数,osDelay函数才会起作用。而构造函数是先于main函数之前执行的,所以驱动程序调用延时函数时,操作系统还没有启动,导致死机现象的出现。
解决方法:
(1)用上述2种方式实现延时函数,通过参数传递加以选择;
(2)或者不在构造函数中调用延时函数。
我觉得第2种方法是比较好的。
原创性文章,转载请注明出处CSDN:http://blog.csdn.net/qingwufeiyang12346。