笔记-lvgl移植到stm32f407
移植lvgl到stm32f407平台freeRTOS中时遇到一些关于接口适配性问题,屏幕为ili9806g,原有接口函数为裸机使用,当前要在freeRTOS使用需要修改优化。包括显示函数和触摸函数。此处记录问题和解决过程。
- lvgl显示功能需要1个打点函数接口,lvgl接口方案优化后改用画实心矩形的函数接口,当前屏幕ili9806g驱动中的画矩形函数接口,需要传参选择画实心矩形还是空心矩形,并且lvgl下发的参数是起始坐标和结束坐标,但当前接口定义的参数是起始坐标和宽度高度,接口声明如下:
ILI9806G_DrawRectangle ( uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight, uint8_t ucFilled ) //画矩形
lvgl所需接口如下(函数名任意):
*
void ILI9806G_MyDrawRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t *color_p) //画实心矩形
解决: 考虑到运行效率决定重写画实心矩形函数,拷贝原有画矩形函数内容修改为所需接口。
- lvgl触屏需要2个函数接口,一个函数返回当前是否在触屏,另一个函数返回当前触屏坐标x和y,但屏幕现有驱动中缺少这2个函数接口。只有一个按下时调用的函数可用,此函数声明如下 :
static void GTP_Touch_Down(int32_t id,int32_t x,int32_t y,int32_t w)
所需的函数接口如下(名称自定):
*
uint8_t GetTouchStatus() //查询是否有触摸值
void getTouchXYValue(uint16_t *touchX, uint16_t *touchY) //获取触摸点坐标
解决: 定义一个结构体,成员分别是x和y,用结构体定义消息队列,驱动层把读取到的x和y值发送到消息队列。
函数GetTouchStatus() 中读取消息队列单元数,非0时返回1,0时返回0。
函数getTouchXYValue()中接收消息队列数据,赋值给本函数的指针参数。
- 移植完成后编译链接报错:Error: L6406E: No space in execution regions with .ANY selector matching xx.o(.bss).

原因: 内存不足。
解决: 点开keil魔术棒,勾选IRAM2即可解决。如下:

- 程序运行后屏幕未点亮,调试发现任务调度器运行起来就会进入stm32的HardFault_Handler(void)函数。
原因: freeRTOS运行要求中断优先级分组是4,如下:
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
添加的代码文件中有2个文件包含中断配置,分别是触屏外中断和定时器中断用于产生lvgl心跳。本来main.c文件中配置了正确的中断优先级分组,但这2个文件在配置中断时自行配置了不同的优先级分组把原有配置覆盖了,导致rtos无法运行。
解决: 直接删掉多余的优先级配置代码。
- 程序运行起来后lvgl界面和触摸可以正常使用。不过由于是裸机代码修改而来,当前所有外设初始化都是在main.c文件的while(1)之前完成,这导致初始化文件中无法使用rtos的vTaskDelay()函数延时,只能使用原有的while()循环延时,大大加长了初始化时间,并且因执行时间太长而不适合在任务函数中调用。
解决: 将外设初始化代码根据功能分散移动到各个任务中的while(1)之前,再将其中的whie()死循环延时替换为rtos的延时函数。但其中iic的us级延时函数用于gpio软件模拟iic通信,需要精确延时,rtos的延时分辨率为1ms,故而继续使用while()延时。
iic延时函数:

普通延时函数:
