一、lvgl测试环境
对拿到的M1S_DOCK开发板进行开发板测试,博流的官方SDK是支持M0和D0两个内核都进行测试的;但是目前只实现了M0的LVGLBenchmark,测试D0内核中发现很多莫名其妙的问题。一会详细记录。
使用的是开发板自带的SPI显示屏,280*240分辨率。
二、M0内核lvgl测试
使用官方默认的SDK进行编译会报错缓存不够,按照下列方式修改SDK中的.ld内存分布文件
/bouffalo_sdk/bsp/board/bl808dk/bl808_flash_m0.ld文件。主要目的就是修改ram_memory的大小,把ram_wifi的大小暂时调整为0,因为目前官方SDK无法启用无线功能。如果测试过程中卡住,就是ram_memory太小了,缓存不够使用了,调大即可。
/****************************************************************************************
* @file flash.ld
*
* @brief This file is the link script file (gnuarm or armgcc).
*
* Copyright (C) BouffaloLab 2021
*
****************************************************************************************
*/
/* configure the CPU type */
OUTPUT_ARCH( "riscv" )
/* configure the entry point */
ENTRY(__start)
StackSize = 0x0400; /* 1KB */
HeapMinSize = 0x1000; /* 4KB */
psram_min_size = 0x1000;
__EM_SIZE = DEFINED(btble_controller_init) ? 32K : 0K;
MEMORY
{
fw_header_memory (rx) : ORIGIN = 0x58000000 - 0x1000, LENGTH = 4K
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
ram_psram (wxa) : ORIGIN = 0x50000000, LENGTH = 64M
itcm_memory (rx) : ORIGIN = 0x62020000, LENGTH = 32K
dtcm_memory (rx) : ORIGIN = 0x62028000, LENGTH = 16K
nocache_ram_memory (!rx) : ORIGIN = 0x2202C000, LENGTH = 16K
ram_memory (!rx) : ORIGIN = 0x62038000, LENGTH = 128K
ram_wifi (wxa) : ORIGIN = 0x22058000, LENGTH = 0K
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
}
SECTIONS
{
.fw_header :
{
KEEP(*(.fw_header))
} > fw_header_memory
.init :
{
KEEP (*(SORT_NONE(.init)))
KEEP (*(SORT_NONE(.vector)))
} > xip_memory
.text :
{
. = ALIGN(4);
__text_code_start__ = .;
*(.text)
*(.text.*)
/* section information for shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
/* section information for usb usbh_class_info */
. = ALIGN(4);
__usbh_class_info_start__ = .;
KEEP(*(.usbh_class_info))
. = ALIGN(4);
__usbh_class_info_end__ = .;
/*put .rodata**/
*(EXCLUDE_FILE( *bl808_glb*.o*
*bl808_glb_gpio*.o*
*bl808_pds*.o*
*bl808_aon*.o*
*bl808_hbn*.o*
*bl808_l1c*.o*
*bl808_common*.o*
*bl808_clock*.o*
*bl808_ef_ctrl*.o*
*bl808_sf_cfg*.o*
*bl808_sf_ctrl*.o*
*bl808_sflash*.o*
*bl808_xip_sflash*.o*
*bl808_romapi_patch*.o* ) .rodata*)
*(.srodata)
*(.srodata.*)
. = ALIGN(4);
__text_code_end__ = .;
} > xip_memory
. = ALIGN(4);
__itcm_load_addr = .;
.itcm_region : AT (__itcm_load_addr)
{
. = ALIGN(4);
__tcm_code_start__ = .;
*(.tcm_code.*)
*(.tcm_const.*)
*(.sclock_rlt_code.*)
*(.sclock_rlt_const.*)
*bl808_glb*.o*(.rodata*)
*bl808_glb_gpio*.o*(.rodata*)
*bl808_pds*.o*(.rodata*)
*bl808_aon*.o*(.rodata*)
*bl808_hbn*.o*(.rodata*)
*bl808_l1c*.o*(.rodat服务器托管网a*)
*bl808_common*.o*(.rodata*)
*bl808_clock*.o*(.rodata*)
*bl808_ef_ctrl*.o*(.rodata*)
*bl808_sf_cfg*.o*(.rodata*)
*bl808_sf_ctrl*.o*(.rodata*)
*bl808_sflash*.o*(.rodata*)
*bl808_xip_sflash*.o*(.rodata*)
*bl808_romapi_patch*.o*(.rodata*)
. = ALIGN(4);
__tcm_code_end__ = .;
} > itcm_memory
__dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
.dtcm_region : AT (__dtcm_load_addr)
{
. = ALIGN(4);
__tcm_data_start__ = .;
*(.tcm_data)
/* *finger_print.o(.data*) */
. = ALIGN(4);
__tcm_data_end__ = .;
} > dtcm_memory
/*************************************************************************/
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (NOLOAD):
{
. = ALIGN(0x4);
. = . + StackSize;
. = ALIGN(0x4);
} > dtcm_memory
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
PROVIDE( __freertos_irq_stack_top = __StackTop);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
/*************************************************************************/
__nocache_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region);
.nocache_ram_region : AT (__nocache_ram_load_addr)
{
. = ALIGN(4);
__nocache_ram_data_start__ = .;
*(.nocache_ram)
. = ALIGN(4);
__nocache_ram_data_end__ = .;
} > nocache_ram_memory
__ram_load_addr = __nocache_ram_load_addr + SIZEOF(.nocache_ram_region);
/* Data section */
RAM_DATA : AT (__ram_load_addr)
{
. = ALIGN(4);
__ram_data_start__ = .;
PROVIDE( __global_pointer$ = . + 0x800 );
*(.data)
*(.data.*)
*(.sdata)
*(.sdata.*)
*(.sdata2)
*(.sdata2.*)
. = ALIGN(4);
__bflog_tags_start__ = .;
*(.bflog_tags_array)
. = ALIGN(4);
__bflog_tags_end__ = .;
__ram_data_end__ = .;
} > ram_memory
__psram_load_addr = (__ram_load_addr + SIZEOF (RAM_DATA));
.psram_data_region : AT (__psram_load_addr)
{
. = ALIGN(4);
__psram_data_start__ = .;
KEEP(*(.psram_data*))
. = ALIGN(4);
__psram_data_end__ = .;
} > ram_psram
__etext_final = (__psram_load_addr + SIZEOF (.psram_data_region));
ASSERT(__etext_final ram_memory
.noinit_data (NOLOAD) :
{
. = ALIGN(4);
__noinit_data_start__ = .;
*(.noinit_data*)
. = ALIGN(4);
__noinit_data_end__ = .;
} > ram_memory
.nocache_noinit_ram_region (NOLOAD) :
{
. = ALIGN(4);
__nocache_noinit_ram_data_start__ = .;
*(.nocache_noinit_ram)
*(.noncacheable)
. = ALIGN(4);
__nocache_noinit_ram_data_end__ = .;
} > nocache_ram_memory
.heap (NOLOAD):
{
. = ALIGN(4);
__HeapBase = .;
/*__end__ = .;*/
/*end = __end__;*/
KEEP(*(.heap*))
. = ALIGN(4);
__HeapLimit = .;
} > ram_memory
__HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory);
ASSERT(__HeapLimit - __HeapBase >= HeapMinSize, "heap region overflow")
.psram_noinit_data (NOLOAD):
{
. = ALIGN(4);
__psram_noinit_data_start__ = .;
KEEP(*(.psram_noinit*))
. = ALIGN(4);
__psram_noinit_data_end__ = .;
} > ram_psram
.psram_heap (NOLOAD):
{
. = ALIGN(4);
__psram_heap_base = .;
KEEP(*(.psram_heap*))
. = ALIGN(4);
__psram_heap_end = .;
} > ram_psram
__psram_limit = ORIGIN(ram_psram) + LENGTH(ram_psram);
ASSERT(__psram_limit - __psram_heap_base >= psram_min_size, "psram heap region 服务器托管网overflow")
.wifibss (NOLOAD) :
{
PROVIDE( __wifi_bss_start = ADDR(.wifibss) );
PROVIDE( __wifi_bss_end = ADDR(.wifibss) + SIZEOF(.wifibss) );
*ipc_shared.o(COMMON)
*sdu_shared.o(COMMON)
*hal_desc.o(COMMON)
*txl_buffer_shared.o(COMMON)
*txl_frame_shared.o(COMMON)
*scan_shared.o(COMMON)
*scanu_shared.o(COMMON)
*mfp_bip.o(COMMON)
*me_mic.o(COMMON)
*bl_sta_mgmt_others.o(COMMON)
*bl_pmk_mgmt.o(COMMON)
*bl_pmk_mgmt_internal.o(COMMON)
*libwifi_drv.a:bl_utils.o(COMMON)
*libwifi_drv.a:bl_utils.o(.bss*)
*(.wifi_ram*)
. = ALIGN(16);
} > ram_wifi
PROVIDE(__LD_CONFIG_EM_SEL = __EM_SIZE);
}
修改完成后最好把LP内核的内存分布文件也修改一下。这里引申出一个问题,就是内存的分布肯定是LP和M0内核共享OCRAM+WRAM,但是不知道两个内核的itcm_memory 和dtcm_memory的大小是不是要按照规格书改成32K+16K,官方默认的大小是20K+4K,搞不懂是什么用意。而且两个内核的部分区域在官方SDK中竟然重叠了,好奇怪。对于初学者来说,实在是头大,官方也没有任何说明。
这里直接贴图一个成绩。
____ __ __ _ _ _
| _ / _|/ _| | | | | | |
| |_) | ___ _ _| |_| |_ __ _| | ___ | | __ _| |__
| _
三、D0内核调试挖坑!!!
测试D0内核花费了3天时间也没搞定,总是进入初始化以后,直接就卡屏卡死了。因为在假期,没带DEBUG工具,只能随便打点测试了一下;
1.SPI1无法启用
按照官方SDK进行测试,发现根本没有使用SPI1,而且在lcd_spi_hard_4_init(lcd_spi_hard_4_init_t *dbi_parra)初始化过程中,spi_hd = bflb_device_get_by_name(LCD_SPI_HARD_4_NAME);得到的是spi0。。。
int lcd_spi_hard_4_init(lcd_spi_hard_4_init_t *dbi_parra)
{
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = dbi_parra->clock_freq,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* dma cfg */
struct bflb_dma_channel_config_s dma_spi_tx_cfg = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_SPI0_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR4,
.dst_burst_count = DMA_BURST_INCR4,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
pixel_format = dbi_parra->pixel_format;
#if (SPI_FIFO_WIDTH_VARIABLE_SUPPORT)
/* SPI support burst*4 */
spi_cfg.tx_fifo_threshold = (2 * 4 - 1);
spi_cfg.rx_fifo_threshold = (2 * 4 - 1);
spi_cfg.byte_order = SPI_BYTE_MSB;
#elif
spi_cfg.tx_fifo_threshold = 4 - 1;
spi_cfg.rx_fifo_threshold = 4 - 1;
#endif
spi_hd = bflb_device_get_by_name(LCD_SPI_HARD_4_NAME);
/* CS and DC pin init */
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CS, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DC, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
LCD_SPI_HARD_4_CS_HIGH;
LCD_SPI_HARD_4_DC_HIGH;
if (spi_hd->idx == 0) {
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CLK, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DAT, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
#if defined(GPIO_FUNC_SPI1)
else if (spi_hd->idx == 1) {
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_CLK, GPIO_FUNC_SPI1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
bflb_gpio_init(gpio, LCD_SPI_HARD_4_PIN_DAT, GPIO_FUNC_SPI1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
#endif
/* spi init */
bflb_spi_init(spi_hd, &spi_cfg);
/* spi enabled continuous mode */
// bflb_spi_feature_control(spi_hd, SPI_CMD_SET_CS_INTERVAL, true);
if (pixel_format == LCD_SPI_LCD_PIXEL_FORMAT_RGB565) {
dma_spi_tx_cfg.src_width = DMA_DATA_WIDTH_16BIT;
dma_spi_tx_cfg.dst_width = DMA_DATA_WIDTH_16BIT;
}
if (spi_hd->idx == 0) {
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI0_TX;
spi_tx_fifo_address = DMA_ADDR_SPI0_TDR;
}
#if defined(DMA_REQUEST_SPI1_TX)
else if (spi_hd->idx == 1) {
dma_spi_tx_cfg.dst_req = DMA_REQUEST_SPI1_TX;
spi_tx_fifo_address = DMA_ADDR_SPI1_TDR;
}
#endif
/* dma init */
spi_dma_hd = bflb_device_get_by_name(LCD_SPI_HARD_4_DMA_NAME);
bflb_dma_channel_init(spi_dma_hd, &dma_spi_tx_cfg);
/* dma int cfg */
bflb_dma_channel_irq_attach(spi_dma_hd, spi_dma_callback, NULL);
return 0;
}
按照device_table.c文件中,竟然没有规定spi1……….,也没有规定DMA2的对应0-7个通道,但是却规定了DMA0的0-7个通道,官方datasheet中DMA0和DMA1只有一个通道。8个通道的寄存器基地址都是DMA0_BASE( #define DMA0_BASE ((uint32_t)0x2000c000)),在else这个分支里面竟然中断号都是0XFF,真是被这SDK搞懵了。看这样子好像官方并不想让使用spi1来使用?????这个问题等待后续解决。
{ .name = "spi0",
.reg_base = SPI0_BASE,
#if defined(CPU_M0) || defined(CPU_LP)
.irq_num = BL808_IRQ_SPI0,
#else
.irq_num = 0xff,
#endif
.idx = 0,
.dev_type = BFLB_DEVICE_TYPE_SPI,
.user_data = NULL
},
{ .name = "dma0_ch0",
.reg_base = DMA0_BASE + 1 * DMA_CHANNEL_OFFSET,
#if defined(CPU_M0) || defined(CPU_LP)
.irq_num = BL808_IRQ_DMA0_ALL,
#else
.irq_num = 0xff,
#endif
.idx = 0,
.sub_idx = 0,
.dev_type = BFLB_DEVICE_TYPE_DMA,
.user_data = NULL
},
四、引申出来的RAM分配问题
下面贴一下官方的SDK中定义的分配方案,看的我脑袋大,有点看不懂能不能这样使用,或者是这样使用会不会出现冲突。(0x62020000的意思是使用chache访问,和直接访问0x2202000是一个意思,但是nocache_ram_memory区域必须使用0x22034000直接访问,不能使用cache访问)。
1.M0的ram_memory区域,ram_memory (!rx) : ORIGIN = 0x6202A000, LENGTH = 24K,也就是0x2202A000-0x2203000,但是LP内核的itcm_memory (rx) : ORIGIN = 0x2202C000, LENGTH = 16K,也就是0x2202C000-0x2203000;
2.LP内核区域的dtcm_memory (rx) : ORIGIN = 0x22030000, LENGTH = 16K和M0内核的ram_wifi (wxa) : ORIGIN = 0x22030000, LENGTH = 160K – __EM_SIZE冲突,虽然LP内核内部没有cache功能,但是也好奇怪为什么还会划分idata和ddata这两个区域。
3.我自己曾经尝试过按照不冲突的RAM地址升序顺序和严格按照手册所写的itcm和dtcm大小进行内存划分,没有发现明显区别,coremark和lvgl都没有任何提升。看看后续如何理解这个问题和解决问题。
LP-MEMORY
{
fw_header_memory (rx) : ORIGIN = 0x58020000 - 0x1000, LENGTH = 4K
xip_memory (rx) : ORIGIN = 0x58020000, LENGTH = 1M
itcm_memory (rx) : ORIGIN = 0x2202C000, LENGTH = 16K
dtcm_memory (rx) : ORIGIN = 0x22030000, LENGTH = 16K
nocache_ram_memory (!rx) : ORIGIN = 0x22030000, LENGTH = 0K
ram_memory (!rx) : ORIGIN = 0x22034000, LENGTH = 16K
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
}
M0-MEMORY
{
fw_header_memory (rx) : ORIGIN = 0x58000000 - 0x1000, LENGTH = 4K
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
ram_psram (wxa) : ORIGIN = 0x50000000, LENGTH = 64M
itcm_memory (rx) : ORIGIN = 0x62020000, LENGTH = 20K
dtcm_memory (rx) : ORIGIN = 0x62025000, LENGTH = 4K
nocache_ram_memory (!rx) : ORIGIN = 0x22026000, LENGTH = 16K
ram_memory (!rx) : ORIGIN = 0x6202A000, LENGTH = 24K
ram_wifi (wxa) : ORIGIN = 0x22030000, LENGTH = 160K - __EM_SIZE
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
}
D0-MEMORY
{
fw_header_memory (rx) : ORIGIN = 0x58000000 - 0x1000, LENGTH = 4K
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
itcm_memory (rx) : ORIGIN = 0x3eff0000, LENGTH = 28K
dtcm_memory (rx) : ORIGIN = 0x3eff7000, LENGTH = 4K
nocache_ram_memory (!rx) : ORIGIN = 0x3eff8000, LENGTH = 0K
ram_memory (!rx) : ORIGIN = 0x3eff8000, LENGTH = 32K + 32K
xram_memory (!rx) : ORIGIN = 0x40004000, LENGTH = 16K
}
还是希望官方能够多给点文档看啊,linux下的M1S_DOCK_SDK好像就有很多正常的功能寄存器,还有库文件,我看文件抬头都是博流写的,真的是无语了。
后续还是在Linux下使用M1S_DOCK_SDK开发吧,官方的库我实在是搞不懂。浪费精力。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
集合类不安全 List不安全 单线程情况下集合类和很多其他的类都是安全的,因为同一时间只有一个线程在对他们进行修改,但是如果是多线程情况下,那么集合类就不一定是安全的,可能会出现一条线程正在修改的同时另一条线程启动来对这个集合进行修改,这种情况下就会导致发生并…