在前面的文章《lvgl 笔记(3)-中文字库的制作和使用(windows模拟和esp32)》提到,esp32使用大字库会引起刷新速度变慢(文件浏览界面上下滑动时)的问题。今天尝试把712k大小的字库先读取到SPIRAM,使用时,直接读取SPIRAM,果然速度大为提升,效果还可以接受。
我用的模块是ESP32-S3-WROOM-1(N8R8),内部有8M byte SPIRAM。
本文对应的工程源码:《LVGL_HX8369_HZK》。
参考《lvgl 笔记(3)-中文字库的制作和使用(windows模拟和esp32)》。
我测试的开发板模块是esp32-S3-WROOM-1(N8R8),模块内部集成了8MB的spi flash。
首先要知道自己开发板的flash大概空间,字库放置的地址和用户程序不要冲突。以我的工程为例,flash空间的规划《partitions_singleapp_large.csv》是:
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x6000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 2000K,
storage,0x01,0x40,0x300000,800k
这里给用户程序安排了2M的空间,我的程序实际不超过 600k bytes;所以我就把字库放在3M开始的地方,也就是偏移量为0x30 0000.
具体操作很简单,把汉字库文件《 myFont_16_2.bin 》往0x300000地址烧录就行了。字库的大小是712k bytes,这里分配800k。
工程配置选择《partitions_singleapp_large.csv》文件:
在我的工程中,我也是拿别人的工程,基本没有改动SPIRAM的配置:
一开始,我想用一个全局数组:
EXT_RAM_ATTR unsigned char __g_hzk_buf[712*1024];
编译失败,提升下面的 error:
esp32 section `.dram0.bss' will not fit in region `dram0_0_seg'
于是改用动态分配就可以正常运行。先定义一个全局指针,再给这个指针动态分配空间:
uint8_t * __g_p_hz_data;
__g_p_hz_data=(uint8_t *) heap_caps_malloc(712*1024, MALLOC_CAP_SPIRAM);
下面是《myFont_16_2.c》的关键代码:
// 配置是否copy to SPIRAM
#define CONFIG_HZK_IN_SPIRAM 1
// 1. 将字库从 flash copy to SPIRAM
#if CONFIG_HZK_IN_SPIRAM
#define HZK_LEN (712*1024)
uint8_t * __g_p_hz_data;
// 上电时,在进入lvgl初始化之前,调用本函数
// 函数名: copyHZK_from_flash_to_SPIRAM()
// 功 能:把字库全部读取到外部SPI RAM
void copyHZK_from_flash_to_SPIRAM(void)
{
__g_p_hz_data=(uint8_t *) heap_caps_malloc(HZK_LEN, MALLOC_CAP_SPIRAM);
spi_flash_read(0x300000,__g_p_hz_data,HZK_LEN);
}
static uint8_t *__user_font_getdata(int offset, int size){
return __g_p_hz_data + offset;
}
#else
// 2.直接在flash 读取
static uint8_t __g_font_buf[256];//如bin文件存在SPI FLASH可使用此buff
static uint8_t *__user_font_getdata(int offset, int size){
//如字模保存在SPI FLASH, SPIFLASH_Read(__g_font_buf,offset,size);
spi_flash_read(0x300000+offset,__g_font_buf,size);
return __g_font_buf;
}
#endif
测试时,可以通过配置 宏 CONFIG_HZK_IN_SPIRAM 为0(没有把字库放在SPIRAM)或为1(把字库放在SPIRAM),对比两者的速度。
源码参考《lvgl_gui.c》。
void copyHZK_from_flash_to_SPIRAM(void);
void guiTask(void *pvParameter)
{
// 先copy 汉字库到 spiram
copyHZK_from_flash_to_SPIRAM();
xGuiSemaphore = xSemaphoreCreateMutex();
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
......
}
函数 guiTask是lvgl的主函数,在对lvgl初始化之前调用 copyHZK_from_flash_to_SPIRAM。