使用国产GD32C113CBT6芯片在移植完成FreeRTOS后,主程序运行卡死,Debug发现HardFault_Handler错误,卡死在循环里,如图下所示:
(一)这里优先考虑是否是内存访问越界(堆栈溢出),主要是如下问题:
1. 内存溢出 (常见的于数组访问越界)。
2 .堆栈溢出(堆栈设置过小等)。
未调整任务和内存空间前如下:
在Free RTOSConfig里面调整操作系统所有的总堆大小:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 25 * 1024 ) ) //系统所有的总堆大小
以上调整后问题并未解决,继续排查
(二)个人采用的标准库,任务创建前不能有执行时间过长的函数,例如flash的读写、延时等,也会使MCU进入HardFault_Handler(原因:进入main()之前滴答已经开启,操作时间太长,导致freertos不能正常运作,所以进入了hardfault)
博主采用的软件IIC,时序上均加有延时,解决方案:将有延时的初始化部分,放入对应执行的任务中进行初始化,如下图所示:
再次编译,HardFault_Handler问题已经解决,但出现了新问题Default_Handler,继续调试
(三)问题分析:我们使用某个外设时,若开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,当进入中断时,程序就会跳转到启动文件预先写好的空中断服务程序中,并且在这个空函数中无限循环,即程序卡死。
经过检查,发现是移植个人程序时,遗漏了CAN0的中断服务函数,调整如下:
在gd32c11x_it.c和gd32c11x_it.h中分别添加如下代码:
/*!
\brief this function handles CAN0 RX0 exception
\param[in] none
\param[out] none
\retval none
*/
void CAN0_RX0_IRQHandler(void)
{
memset(&g_receive_message,0,sizeof(g_receive_message));//清空接收结构体
/* check the receive message */
can_message_receive(CAN0, CAN_FIFO0, &g_receive_message);
if (g_receive_message.rx_efid == 0x18FEBF0B)
{
memcpy(&Can_Pdu_Receive, &g_receive_message, sizeof(can_receive_message_struct));
can0_receive_flag = SET;
}
}
/* this function handles CAN0 RX0 exception */
void CAN0_RX0_IRQHandler(void);
再次编译,Default_Handler问题已解决