运行环境:
GD32F450ZGT6(cortex-M4) + ST7735 LCD
代码框架使用cubemx生成F429ZGT系列的基础代码
移植LVGL v8.3
问题描述
第一次进行LVGL代码移植,在测试是否移植成功时尝试运行官方的Demo程序:lv_demo_widgets,结果卡死并且显示停止在初始化结束一刻。
使用keil的调试功能查找原因
解决方法:
堆栈溢出,增大Stack Size
在启动文件:startup.s
中进行修改
Cubemx生成的代码一般默认栈的最小空间为0x400
,测试改为0x800
后可以正常运行demo,具体需要改多大还需实际使用后自行拿捏。
分析过程:
使用debug连接MCU运行后,一段时间后停止运行,发现程序进入HardFault_Handler的循环中,
意味着发生了一个异常
发生异常时,硬件会自动执行将LR保存EXC_RETURN值,
并将8个寄存器的值(xPSR、PC、LR、R12以及 R3~R0)压入异常发生时所使用的堆栈中并更新SP、MSP、PSP等
因此可以通过调试功能查看R14(LR)寄存器,判断产生异常时所使用的堆栈,并找出对应的错误代码
LR | 对应 |
---|---|
0xFFFFFFF1 | 返回MSP并使用handler模式 |
0xFFFFFFFD | 返回PSP并使用thread模式 |
0xFFFFFFF9 | 返回MSP并使用thread模式 |
MSP:Main Stack Pointer PSP:Process Stack Pointer
如图可见LR的值为0xFFFFFFF9,说明在MSP运行时中断,查看MSP中对应地址的值:
可以看到MSP指向的地址单元与理论中存入的前几个寄存器相对应,由此看到LR返回地址(即正常情况下即将执行的下一行代码)所对应的汇编代码和C代码,
由此可知是LR的前一段代码运行时发生异常
此子函数的作用是:刷新绘图缓冲区的内容
发生异常代码的作用:等待所有后台操作完成。
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
一般HardFault发生原因有两种:
1.内存溢出(一般是由于代码问题如数组越界引起,由于是移植的官方代码暂时排除)
2.堆栈溢出
由于对LVGL接触尚浅,无从得知后台操作时为何导致程序卡死,个人猜测是刷新过程中堆栈溢出,
所以调整了堆栈大小后进行尝试,烧录后问题解决
仅作记录,若有错误欢迎指出