From b0174552da8bb44f94e879441fe7c67512e23d0e Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Mon, 4 May 2026 22:44:00 +0800 Subject: [PATCH 1/9] [bsp][k230] Add SoC variant selection with per-SoC memory layout Introduce a Kconfig choice between SOC_K230 and SOC_K230D to support different chip variants. SOC_K230D targets the ATK-DNK230D board with 128MB DDR, while SOC_K230 serves as the default for other K230 boards. Key changes: - Replace single BOARD_C908 config with a choice menu for SoC variant - Move common selects (ARCH_RISCV64, RT_USING_CACHE, ARCH_MM_MMU, etc.) into each SoC config entry - Add ARCH_RISCV_XUANTIE select for Xuantie processor support - mem_layout.h: define per-SoC default memory sizes with #if defined() blocks, add #error guard when no SoC is selected - Fix typo: Kerenl -> Kernel in memory layout ASCII diagram Co-Authored-By: Claude Opus 4.7 --- bsp/k230/Kconfig | 26 +++++++++++++-- bsp/k230/board/mem_layout.h | 66 +++++++++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/bsp/k230/Kconfig b/bsp/k230/Kconfig index 3ddee1c468c..e6791a7b6b1 100644 --- a/bsp/k230/Kconfig +++ b/bsp/k230/Kconfig @@ -10,15 +10,35 @@ source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" rsource "board/Kconfig" -config BOARD_C908 - bool +choice + prompt "SoC variant" + default SOC_K230 + +config SOC_K230 + bool "K230" + select ARCH_RISCV64 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + select RT_USING_CACHE + select ARCH_MM_MMU + select ARCH_RISCV_FPU + select ARCH_RISCV_XUANTIE + select ARCH_REMAP_KERNEL if RT_USING_SMART + +config SOC_K230D + bool "K230D (128MB DDR)" select ARCH_RISCV64 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select RT_USING_CACHE - select ARCH_MM_MMU + select ARCH_MM_MMU select ARCH_RISCV_FPU + select ARCH_RISCV_XUANTIE select ARCH_REMAP_KERNEL if RT_USING_SMART +endchoice + +config BOARD_C908 + bool default y config __STACKSIZE__ diff --git a/bsp/k230/board/mem_layout.h b/bsp/k230/board/mem_layout.h index cca1e0f7d99..19ba60ed0b0 100644 --- a/bsp/k230/board/mem_layout.h +++ b/bsp/k230/board/mem_layout.h @@ -26,7 +26,7 @@ * | ...... | maybe zero * +---------+ <- CONFIG_MEM_RTSMART_SIZE * | guard | MEM_GUARD_SIZE - * +---------+ <- End of Kerenl + * +---------+ <- End of Kernel * | | * | | * +---------+ @@ -47,30 +47,76 @@ * the SDK configuration. * * If CONFIG_XXX is defined, it means that the value comes from the SDK - * configuration, otherwise the default configuration of bsp/k230 in RT-Thead - * is used. The default configuration of bsp/k230 is for the 01Studio CanMV - * development board that supports 512MB of memory. + * configuration, otherwise the default configuration defined in this file + * is used. + */ + +#if defined(SOC_K230D) +/* + * ATK-DNK230D: 128MB DDR + * + * +---------+ <- 0x8000000 (128MB) + * | MMZ | CONFIG_MEM_MMZ_SIZE = 0x4600000 (70MB) + * +---------+ <- CONFIG_MEM_MMZ_BASE = 0x3A00000 (58MB) + * | heap | CONFIG_MEM_RTSMART_HEAP_SIZE = 0x800000 (8MB) + * +---------+ + * | kernel | CONFIG_MEM_RTSMART_SIZE - MEM_OPENSBI_SIZE - MEM_GUARD_SIZE - heap + * +---------+ <- CONFIG_MEM_RTSMART_BASE + MEM_OPENSBI_SIZE (128KB) + * | opensbi | MEM_OPENSBI_SIZE = 0x20000 (128KB) + * +---------+ <- 0x0 */ #ifndef CONFIG_MEM_TOTAL_SIZE -#define CONFIG_MEM_TOTAL_SIZE 0x20000000 // 512M +#define CONFIG_MEM_TOTAL_SIZE 0x8000000 // 128M #endif #ifndef CONFIG_MEM_RTSMART_SIZE -#define CONFIG_MEM_RTSMART_SIZE 0x10000000 // 256M +#define CONFIG_MEM_RTSMART_SIZE 0x3A00000 // 58M #endif #ifndef CONFIG_MEM_RTSMART_HEAP_SIZE -#define CONFIG_MEM_RTSMART_HEAP_SIZE 0x2000000 // 32M +#define CONFIG_MEM_RTSMART_HEAP_SIZE 0x800000 // 8M #endif #ifndef CONFIG_MEM_MMZ_BASE -#define CONFIG_MEM_MMZ_BASE 0x10000000 // 512M +#define CONFIG_MEM_MMZ_BASE 0x3A00000 // 58M #endif #ifndef CONFIG_MEM_MMZ_SIZE -#define CONFIG_MEM_MMZ_SIZE 0x10000000 // 256M +#define CONFIG_MEM_MMZ_SIZE 0x4600000 // 70M +#endif + +#elif defined(SOC_K230) +/* + * K230: default memory configuration + * + * The K230 chip supports different DDR sizes (256MB, 512MB, 1GB, 2GB). + * Override the CONFIG_MEM_XXX values in rtconfig.h or SDK configuration + * to match your board's actual DDR size. + */ +#ifndef CONFIG_MEM_TOTAL_SIZE +#define CONFIG_MEM_TOTAL_SIZE 0x8000000 // 128M +#endif + +#ifndef CONFIG_MEM_RTSMART_SIZE +#define CONFIG_MEM_RTSMART_SIZE 0x3A00000 // 58M +#endif + +#ifndef CONFIG_MEM_RTSMART_HEAP_SIZE +#define CONFIG_MEM_RTSMART_HEAP_SIZE 0x800000 // 8M +#endif + +#ifndef CONFIG_MEM_MMZ_BASE +#define CONFIG_MEM_MMZ_BASE 0x3A00000 // 58M +#endif + +#ifndef CONFIG_MEM_MMZ_SIZE +#define CONFIG_MEM_MMZ_SIZE 0x4600000 // 70M +#endif + +#else +#error "Either SOC_K230 or SOC_K230D must be defined" #endif #define MEM_KERNEL_SIZE (CONFIG_MEM_RTSMART_SIZE - MEM_OPENSBI_SIZE - MEM_GUARD_SIZE) -#endif // MEMORY_LAYOUT_H__ \ No newline at end of file +#endif // MEMORY_LAYOUT_H__ From d2496a4514cca6f93b22343eee48a8b77f7f96b3 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Mon, 4 May 2026 22:44:10 +0800 Subject: [PATCH 2/9] [bsp][k230] Clean up board definitions and add debug logging board.h: Remove unused peripheral base address defines for blocks that are not currently supported (SRAM, GSDMA, DECOMP, ISP, VPU, GPU, VO, DSI, Audio, USB2, SDHC, BootROM, Security, DDRC, XIP Flash, etc.). This reduces clutter and keeps only actively used hardware definitions. board.c: Add DBG_TAG/DBG_LVL configuration to enable debug logging via the ulog framework. Replace Chinese comments with English descriptions for better upstream readability. Add LOG_I/LOG_D trace points in primary_cpu_entry() and rt_hw_board_init() to aid bring-up debugging. Co-Authored-By: Claude Opus 4.7 --- bsp/k230/board/board.c | 33 ++++++++++++------- bsp/k230/board/board.h | 74 ------------------------------------------ 2 files changed, 21 insertions(+), 86 deletions(-) diff --git a/bsp/k230/board/board.c b/bsp/k230/board/board.c index 8e4eb675d58..26259a305e0 100644 --- a/bsp/k230/board/board.c +++ b/bsp/k230/board/board.c @@ -12,6 +12,10 @@ #include #include +#define DBG_TAG "board" +#define DBG_LVL DBG_INFO +#include + #include "board.h" #include "tick.h" @@ -39,7 +43,6 @@ extern unsigned int __bss_end; #define RT_HW_PAGE_END ((void *)(RAM_END)) #ifdef RT_USING_SMART - rt_region_t init_page_region = {(rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END}; extern size_t MMUTable[]; @@ -47,9 +50,7 @@ extern size_t MMUTable[]; struct mem_desc platform_mem_desc[] = { {KERNEL_VADDR_START, (rt_size_t)(KERNEL_VADDR_START + CONFIG_MEM_MMZ_BASE + CONFIG_MEM_MMZ_SIZE - 1), (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM}, }; - #define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0])) - #endif /* RT_USING_SMART */ #ifndef ARCH_REMAP_KERNEL @@ -76,34 +77,42 @@ static void __rt_assert_handler(const char *ex_string, const char *func, rt_size asm volatile("ebreak":::"memory"); } -//BSP的C入口 +/* C entry point, this gets called on primary CPU after stack setup. */ void primary_cpu_entry(void) { - //关中断 + LOG_I("primary_cpu_entry"); + rt_hw_interrupt_disable(); + +#ifdef RT_DEBUGING_ASSERT rt_assert_set_hook(__rt_assert_handler); - //启动RT-Thread Smart内核 +#endif + entry(); } #define IOREMAP_SIZE (1ul << 30) -//这个初始化程序由内核主动调用,此时调度器还未启动,因此在此不能使用依赖线程上下文的函数 +/* + * This function is called by the kernel during initialization. At this point, + * the scheduler has not started, so functions that depend on thread context + * cannot be used. + */ void rt_hw_board_init(void) { + LOG_D("board init: heap %p-%p, page %p-%p", + RT_HW_HEAP_BEGIN, RT_HW_HEAP_END, + RT_HW_PAGE_START, RT_HW_PAGE_END); + #ifdef RT_USING_SMART - /* init data structure */ rt_hw_mmu_map_init(&rt_kernel_space, (void *)(IOREMAP_VEND - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, PV_OFFSET); - - /* init page allocator */ rt_page_init(init_page_region); - /* setup region, and enable MMU */ + LOG_D("mmu setup: %d regions", NUM_MEM_DESC); rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, NUM_MEM_DESC); #endif #ifdef RT_USING_HEAP - /* initialize memory system */ rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); #endif /* initalize interrupt */ diff --git a/bsp/k230/board/board.h b/bsp/k230/board/board.h index 5b06bda30fb..c0d3a3d365d 100644 --- a/bsp/k230/board/board.h +++ b/bsp/k230/board/board.h @@ -20,9 +20,6 @@ * * See K230 Technical Reference Manual, chapter 1.5 Address Space mapping */ -#define SRAM_BASE_ADDR (0x80200000UL) -#define SRAM_IO_SIZE (0x00200000UL) - #define KPU_BASE_ADDR (0x80400000UL) #define KPU_IO_SIZE (0x00000800UL) @@ -32,43 +29,9 @@ #define AI2D_BASE_ADDR (0x80400C00UL) #define AI2D_IO_SIZE (0x00000400UL) -#define GSDMA_BASE_ADDR (0x80800000UL) -#define GSDMA_IO_SIZE (0x00004000UL) - #define DMA_BASE_ADDR (0x80804000UL) #define DMA_IO_SIZE (0x00004000UL) -#define DECOMP_BASE_ADDR (0x80808000UL) -#define DECOMP_IO_SIZE (0x00004000UL) - -#define NON_AI2D_BASE_ADDR (0x8080C000UL) -#define NON_AI2D_IO_SIZE (0x00004000UL) - -#define ISP_BASE_ADDR (0x90000000UL) -#define ISP_IO_SIZE (0x00008000UL) - -#define DEWARP_BASE_ADDR (0x90008000UL) -#define DEWARP_IO_SIZE (0x00001000UL) - -#define CSI_BASE_ADDR (0x90009000UL) -#define CSI_IO_SIZE (0x00002000UL) - -#define VPU_BASE_ADDR (0x90400000UL) -#define VPU_IO_SIZE (0x00010000UL) - -/*2.5D*/ -#define TAAH_GPU_BASE_ADDR (0x90800000UL) -#define TAAH_GPU_IO_SIZE (0x00040000UL) - -#define VO_BASE_ADDR (0x90840000UL) -#define VO_IO_SIZE (0x00010000UL) - -#define DSI_BASE_ADDR (0x90850000UL) -#define DSI_IO_SIZE (0x00001000UL) - -#define GPU_ENGINE_BASE_ADDR (0x90A00000UL) -#define GPU_ENGINE_IO_SIZE (0x00000800UL) - #define PMU_BASE_ADDR (0x91000000UL) #define PMU_IO_SIZE (0x00000C00UL) @@ -105,18 +68,6 @@ #define TS_BASE_ADDR (0x91107000UL) #define TS_IO_SIZE (0x00000800UL) -#define HDI_BASE_ADDR (0x91107800UL) -#define HDI_IO_SIZE (0x00000800UL) - -#define STC_BASE_ADDR (0x91108000UL) -#define STC_IO_SIZE (0x00001000UL) - -#define BOOTROM_BASE_ADDR (0x91200000UL) -#define BOOTROM_IO_SIZE (0x00010000UL) - -#define SECURITY_BASE_ADDR (0x91210000UL) -#define SECURITY_IO_SIZE (0x00008000UL) - #define UART0_BASE_ADDR (0x91400000UL) #define UART0_IO_SIZE (0x00001000UL) @@ -159,35 +110,10 @@ #define ADC_BASE_ADDR (0x9140D000UL) #define ADC_IO_SIZE (0x00001000UL) -#define CODEC_BASE_ADDR (0x9140E000UL) -#define CODEC_IO_SIZE (0x00001000UL) - -#define AUDIO_BASE_ADDR (0x9140F000UL) -#define AUDIO_IO_SIZE (0x00001000UL) - -#define USB2_BASE_ADDR (0x91500000UL) -#define USB2_IO_SIZE (0x00080000UL) - -#define SD_HC_BASE_ADDR (0x91580000UL) -#define SD_HC_IO_SIZE (0x00002000UL) - #define SPI_QOPI_BASE_ADDR (0x91582000UL) #define SPI_QOPI_IO_SIZE (0x00002000UL) #define SPI_OPI_BASE_ADDR (0x91584000UL) #define SPI_OPI_IO_SIZE (0x00001000UL) -#define HI_SYS_CONFIG_BASE_ADDR (0x91585000UL) -#define HI_SYS_CONFIG_IO_SIZE (0x00000400UL) - -#define DDRC_CONF_BASE_ADDR (0x98000000UL) -#define DDRC_CONF_IO_SIZE (0x02000000UL) - -#define SPI_XIP_FLASH_BASE_ADDR (0xC0000000UL) -#define SPI_XIP_FLASH_IO_SIZE (0x08000000UL) - -#define IO_SPACE_BASE_ADDR (KPU_BASE_ADDR) - -#define TIMER_CLK_FREQ (27000000) - #endif // BOARD_H__ From 8b1d4c61819bdae3f21078795240a95769abd158 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Mon, 4 May 2026 22:44:18 +0800 Subject: [PATCH 3/9] [bsp][k230] Downgrade RTC driver register log from INFO to DEBUG Change LOG_I to LOG_D for the "rtc driver register OK" message to reduce console noise during normal boot. Also remove the unnecessary trailing newline character from the log message. Co-Authored-By: Claude Opus 4.7 --- bsp/k230/drivers/interdrv/rtc/drv_rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp/k230/drivers/interdrv/rtc/drv_rtc.c b/bsp/k230/drivers/interdrv/rtc/drv_rtc.c index b4820dc79a1..17a941b4229 100644 --- a/bsp/k230/drivers/interdrv/rtc/drv_rtc.c +++ b/bsp/k230/drivers/interdrv/rtc/drv_rtc.c @@ -477,7 +477,7 @@ static int rt_hw_rtc_init(void) ret = rt_device_register(&rtc_dev.device, "rtc", RT_DEVICE_FLAG_RDWR); RT_ASSERT(ret == RT_EOK); - LOG_I("rtc driver register OK\n"); + LOG_D("rtc driver register OK"); rtc_alarm_stop(&rtc_dev); rtc_tick_stop(&rtc_dev); From 5dc289ba6ad9fc69fe52d63af4791546c8e7676d Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Mon, 4 May 2026 22:44:33 +0800 Subject: [PATCH 4/9] [libcpu][riscv] Add Xuantie processor support and MMU enhancements Kconfig: Introduce ARCH_RISCV_XUANTIE option for Xuantie-based SoCs and CONFIG_XUANTIE_SVPBMT under RT_USING_SMART to enable Svpbmt extension support used by the Xuantie C908 core. mmu.c: Several improvements for MMU management: - Add dcache flush after populating early page table entries to ensure they are visible to the MMU hardware before enabling address translation - Handle the case where v2p translation fails during aspace switch for low physical addresses below KERNEL_VADDR_START, falling back to direct physical address (needed during early K230 bring-up) - When ARCH_REMAP_KERNEL is enabled, set up an identity map guard for low physical memory during aspace switch to validate boot context liveness during the transition away from the early page table - Fix pointer arithmetic in _init_region() with explicit rt_ubase_t casts to avoid potential type promotion issues Co-Authored-By: Claude Opus 4.7 --- libcpu/Kconfig | 12 ++++++++++++ libcpu/risc-v/common64/mmu.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 1185c495214..d1046f1ac19 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -288,6 +288,10 @@ config ARCH_RISCV64 select ARCH_CPU_64BIT bool +config ARCH_RISCV_XUANTIE + select ARCH_RISCV + bool + if ARCH_RISCV64 config ARCH_USING_NEW_CTX_SWITCH bool @@ -300,6 +304,14 @@ if ARCH_RISCV64 select ARCH_USING_NEW_CTX_SWITCH help Using the common64 implementation under ./libcpu/risc-v + +if RT_USING_SMART + config CONFIG_XUANTIE_SVPBMT + int + depends on ARCH_RISCV_XUANTIE + default 1 +endif + endif config ARCH_REMAP_KERNEL diff --git a/libcpu/risc-v/common64/mmu.c b/libcpu/risc-v/common64/mmu.c index d88982d5136..fc1a348efb9 100644 --- a/libcpu/risc-v/common64/mmu.c +++ b/libcpu/risc-v/common64/mmu.c @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -84,12 +85,35 @@ void rt_hw_aspace_switch(rt_aspace_t aspace) uint32_t hartid = rt_cpu_get_id(); uintptr_t ptr = (uintptr_t)aspace->page_table + (uintptr_t)(hartid * ARCH_PAGE_SIZE); uintptr_t page_table = (uintptr_t)rt_kmem_v2p((void *)ptr); + + if (page_table == (uintptr_t)ARCH_MAP_FAILED) + { + /* + * During early K230 bring-up the kernel still runs with low physical + * pointers after relocation, including MMUTable. The formal kernel + * aspace does not translate that low pointer yet, but SATP needs the + * physical page-table address, so use the low address directly. + */ + if (ptr < KERNEL_VADDR_START) + { + page_table = ptr; + } + } #ifndef RT_USING_SMP current_mmu_table = aspace->page_table; #else current_mmu_table[rt_hw_cpu_id()] = (void *)ptr; #endif +#ifdef ARCH_REMAP_KERNEL + /* + * Bring-up guard: keep low physical memory identity-mapped while switching + * away from the early page table. This validates whether any low-address + * boot context is still live during the transition. + */ + ((rt_ubase_t *)ptr)[0] = COMBINEPTE(0, MMU_MAP_EARLY); + rt_hw_cpu_dcache_clean((void *)ptr, sizeof(rt_ubase_t)); +#endif write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | ((rt_ubase_t)page_table >> PAGE_OFFSET_BIT)); rt_hw_tlb_invalidate_all_local(); @@ -561,14 +585,14 @@ static inline void _init_region(void *vaddr, size_t size) { rt_ioremap_start = vaddr; rt_ioremap_size = size; - rt_mpr_start = rt_ioremap_start - rt_mpr_size; + rt_mpr_start = (void *)((rt_ubase_t)rt_ioremap_start - rt_mpr_size); LOG_D("rt_ioremap_start: %p, rt_mpr_start: %p", rt_ioremap_start, rt_mpr_start); } #else static inline void _init_region(void *vaddr, size_t size) { - rt_mpr_start = vaddr - rt_mpr_size; + rt_mpr_start = (void *)((rt_ubase_t)vaddr - rt_mpr_size); } #endif @@ -955,6 +979,9 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid) vs += L2_PAGE_SIZE; } #endif + /* flush page table entries from data cache before enabling MMU */ + rt_hw_cpu_dcache_clean(early_pgtbl, ARCH_PAGE_SIZE); + /* apply new mapping */ asm volatile("sfence.vma x0, x0"); write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT)); From 693af34292d59b8d9b2f8b1e6496df7d8a7e13fd Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Fri, 8 May 2026 11:51:04 +0800 Subject: [PATCH 5/9] bsp: qemu-virt64-riscv: switch to lp64d ABI and add libc stubs Change -march from rv64imafdcv to rv64imafdc, -mabi from lp64 to lp64d to match the K230 lp64d toolchain used by smart-build. Add -fno-builtin -nostdlib to avoid pulling in vector-optimized libc routines (csrr vlenb) that crash on QEMU 6.2. Provide non-vector memcpy/memset/memcmp stubs. Co-Authored-By: Claude Opus 4.7 --- bsp/qemu-virt64-riscv/driver/drv_libc_stubs.c | 33 +++++++++++++++++++ bsp/qemu-virt64-riscv/rtconfig.py | 8 ++--- 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 bsp/qemu-virt64-riscv/driver/drv_libc_stubs.c diff --git a/bsp/qemu-virt64-riscv/driver/drv_libc_stubs.c b/bsp/qemu-virt64-riscv/driver/drv_libc_stubs.c new file mode 100644 index 00000000000..973d67ec1f1 --- /dev/null +++ b/bsp/qemu-virt64-riscv/driver/drv_libc_stubs.c @@ -0,0 +1,33 @@ +/* libc stubs for qemu-virt64-riscv — override toolchain libc with non-vector implementations */ + +#include + +void *memcpy(void *dest, const void *src, size_t n) +{ + const char *s = (const char *)src; + char *d = (char *)dest; + size_t i; + for (i = 0; i < n; i++) + d[i] = s[i]; + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + char *p = (char *)s; + size_t i; + for (i = 0; i < n; i++) + p[i] = (char)c; + return s; +} + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *a = (const unsigned char *)s1; + const unsigned char *b = (const unsigned char *)s2; + size_t i; + for (i = 0; i < n; i++) + if (a[i] != b[i]) + return (int)a[i] - (int)b[i]; + return 0; +} diff --git a/bsp/qemu-virt64-riscv/rtconfig.py b/bsp/qemu-virt64-riscv/rtconfig.py index 09d530af4a1..ab43271b222 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.py +++ b/bsp/qemu-virt64-riscv/rtconfig.py @@ -21,7 +21,7 @@ if PLATFORM == 'gcc': # toolchains - PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-elf-' + PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-linux-musleabi-' CC = PREFIX + 'gcc' CXX = PREFIX + 'g++' AS = PREFIX + 'gcc' @@ -32,10 +32,10 @@ OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64 ' - CFLAGS = DEVICE + '-ffreestanding -flax-vector-conversions -Wno-cpp -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -fdiagnostics-color=always' + DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64d ' + CFLAGS = DEVICE + '-ffreestanding -fno-builtin -flax-vector-conversions -Wno-cpp -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -fdiagnostics-color=always' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ ' - LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static' + LFLAGS = DEVICE + ' -nostartfiles -nostdlib -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static' CPATH = '' LPATH = '' From 9c58485a602136770623b89fefd01683c07f9376 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Fri, 8 May 2026 12:30:02 +0800 Subject: [PATCH 6/9] bsp: qemu-virt64-riscv: add LVGL kernel-mode demo with virtio-gpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix osource variable expansion in Kconfig ($PKGS_DIR → $(PKGS_DIR)) - Add PKG_USING_LVGL Kconfig option - Add LVGL port files (lv_port_disp.c, lv_port_indev.c) for virtio-gpu - Add lv_conf.h with 32-bit color depth - Add lvgl_demo.c with button, slider, label widgets - LVGL source: clone to packages/lvgl-latest (v8.4.0) Co-Authored-By: Claude Opus 4.7 --- bsp/qemu-virt64-riscv/Kconfig | 2 +- .../applications/lvgl/SConscript | 16 ++++ .../applications/lvgl/lv_conf.h | 19 +++++ .../applications/lvgl/lv_port_disp.c | 81 +++++++++++++++++++ .../applications/lvgl/lv_port_indev.c | 7 ++ .../applications/lvgl/lvgl_demo.c | 49 +++++++++++ bsp/qemu-virt64-riscv/packages/Kconfig | 21 +++++ 7 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 bsp/qemu-virt64-riscv/applications/lvgl/SConscript create mode 100644 bsp/qemu-virt64-riscv/applications/lvgl/lv_conf.h create mode 100644 bsp/qemu-virt64-riscv/applications/lvgl/lv_port_disp.c create mode 100644 bsp/qemu-virt64-riscv/applications/lvgl/lv_port_indev.c create mode 100644 bsp/qemu-virt64-riscv/applications/lvgl/lvgl_demo.c create mode 100644 bsp/qemu-virt64-riscv/packages/Kconfig diff --git a/bsp/qemu-virt64-riscv/Kconfig b/bsp/qemu-virt64-riscv/Kconfig index 544753502b2..5347d59be6c 100644 --- a/bsp/qemu-virt64-riscv/Kconfig +++ b/bsp/qemu-virt64-riscv/Kconfig @@ -7,7 +7,7 @@ RTT_DIR := ../../ PKGS_DIR := packages source "$(RTT_DIR)/Kconfig" -osource "$PKGS_DIR/Kconfig" +osource "$(PKGS_DIR)/Kconfig" rsource "driver/Kconfig" config BOARD_QEMU_VIRT_RV64 diff --git a/bsp/qemu-virt64-riscv/applications/lvgl/SConscript b/bsp/qemu-virt64-riscv/applications/lvgl/SConscript new file mode 100644 index 00000000000..1b7f21a5377 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/lvgl/SConscript @@ -0,0 +1,16 @@ +from building import * +import os + +cwd = GetCurrentDir() + +src = Glob('*.c') +inc = [cwd] + +lvgl_root = cwd + '/../../packages/lvgl-latest' +inc += [lvgl_root] +inc += [lvgl_root + '/src'] +inc += [lvgl_root + '/env_support/rt-thread'] + +group = DefineGroup('LVGL-app', src, depend = ['PKG_USING_LVGL'], CPPPATH = inc) + +Return('group') diff --git a/bsp/qemu-virt64-riscv/applications/lvgl/lv_conf.h b/bsp/qemu-virt64-riscv/applications/lvgl/lv_conf.h new file mode 100644 index 00000000000..c425b0b76e8 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/lvgl/lv_conf.h @@ -0,0 +1,19 @@ +#ifndef LV_CONF_H +#define LV_CONF_H + +#ifdef __RTTHREAD__ +#include +#endif + +#define LV_COLOR_DEPTH 32 + +#define LV_HOR_RES_MAX 800 +#define LV_VER_RES_MAX 600 + +#define LV_USE_PERF_MONITOR 1 + +#define LV_FONT_MONTSERRAT_14 1 +#define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_24 1 + +#endif diff --git a/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_disp.c b/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_disp.c new file mode 100644 index 00000000000..634fcc9534d --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_disp.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#define DBG_TAG "lv_port_disp" +#define DBG_LVL DBG_INFO +#include + +static lv_disp_draw_buf_t disp_buf; +static lv_disp_drv_t disp_drv; +static rt_device_t gpu_device = 0; +static struct rt_device_graphic_info info; + +static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) +{ + lv_color32_t *fbp32 = (lv_color32_t *)info.framebuffer; + int32_t x, y; + + for (y = area->y1; y <= area->y2; y++) + { + for (x = area->x1; x <= area->x2; x++) + { + fbp32[y * info.width + x].full = color_p->full; + color_p++; + } + } + + lv_disp_flush_ready(disp_drv); +} + +void lv_port_disp_init(void) +{ + rt_err_t result; + + gpu_device = rt_device_find("virtio-gpu0"); + if (gpu_device == RT_NULL) + { + LOG_E("virtio-gpu0 device not found"); + return; + } + + result = rt_device_open(gpu_device, RT_DEVICE_OFLAG_RDWR); + if (result != RT_EOK) + { + LOG_E("failed to open virtio-gpu0: %d", result); + return; + } + + result = rt_device_control(gpu_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) + { + LOG_E("failed to get graphic info: %d", result); + return; + } + + LOG_I("framebuffer: %p, %dx%d, bpp=%d, format=%d", + info.framebuffer, info.width, info.height, + info.bits_per_pixel, info.pixel_format); + + lv_color_t *fbuf1 = rt_malloc(info.width * info.height * sizeof(lv_color_t)); + lv_color_t *fbuf2 = rt_malloc(info.width * info.height * sizeof(lv_color_t)); + if (fbuf1 == RT_NULL || fbuf2 == RT_NULL) + { + LOG_E("failed to allocate LVGL draw buffers"); + if (fbuf1) rt_free(fbuf1); + if (fbuf2) rt_free(fbuf2); + return; + } + + lv_disp_draw_buf_init(&disp_buf, fbuf1, fbuf2, info.width * info.height); + + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = info.width; + disp_drv.ver_res = info.height; + disp_drv.draw_buf = &disp_buf; + disp_drv.flush_cb = disp_flush; + + lv_disp_drv_register(&disp_drv); + + LOG_I("LVGL display port initialized"); +} diff --git a/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_indev.c b/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_indev.c new file mode 100644 index 00000000000..d5e40e69118 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/lvgl/lv_port_indev.c @@ -0,0 +1,7 @@ +#include +#include + +void lv_port_indev_init(void) +{ + /* no input devices yet */ +} diff --git a/bsp/qemu-virt64-riscv/applications/lvgl/lvgl_demo.c b/bsp/qemu-virt64-riscv/applications/lvgl/lvgl_demo.c new file mode 100644 index 00000000000..d6a979eb105 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/lvgl/lvgl_demo.c @@ -0,0 +1,49 @@ +#include +#include + +static void btn_event_cb(lv_event_t *e) +{ + lv_event_code_t code = lv_event_get_code(e); + if (code == LV_EVENT_CLICKED) + { + rt_kprintf("LVGL button clicked!\n"); + } +} + +static lv_obj_t *label; + +static void slider_event_cb(lv_event_t *e) +{ + lv_obj_t *slider = lv_event_get_target(e); + lv_label_set_text_fmt(label, "%d%%", (int)lv_slider_get_value(slider)); + lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -10); +} + +void lv_user_gui_init(void) +{ + lv_obj_t *scr = lv_scr_act(); + + lv_obj_t *title = lv_label_create(scr); + lv_label_set_text(title, "Hello RT-Thread + LVGL!"); + lv_obj_set_style_text_color(title, lv_color_white(), 0); + lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20); + + lv_obj_t *btn = lv_btn_create(scr); + lv_obj_set_size(btn, 120, 50); + lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0); + lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); + + lv_obj_t *btn_label = lv_label_create(btn); + lv_label_set_text(btn_label, "Click Me!"); + + lv_obj_t *slider = lv_slider_create(scr); + lv_obj_set_width(slider, 200); + lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, -40); + lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + + label = lv_label_create(scr); + lv_label_set_text(label, "0%"); + lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -10); + + rt_kprintf("LVGL user GUI initialized\n"); +} diff --git a/bsp/qemu-virt64-riscv/packages/Kconfig b/bsp/qemu-virt64-riscv/packages/Kconfig new file mode 100644 index 00000000000..bbb26eeef3c --- /dev/null +++ b/bsp/qemu-virt64-riscv/packages/Kconfig @@ -0,0 +1,21 @@ +config PKG_USING_LVGL + bool "LVGL: powerful and easy-to-use embedded GUI library" + default n + help + LVGL is a free and open-source embedded graphic library. + +if PKG_USING_LVGL + +config PKG_LVGL_THREAD_STACK_SIZE + int "LVGL thread stack size" + default 8192 + +config PKG_LVGL_THREAD_PRIO + int "LVGL thread priority" + default 10 + +config PKG_LVGL_DISP_REFR_PERIOD + int "LVGL display refresh period (ms)" + default 33 + +endif From 333d1f5c6c6b54bf8ffcd14b52a3eecd2f27264e Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Sun, 10 May 2026 18:24:24 +0800 Subject: [PATCH 7/9] bsp: k230: add soft-fpu display driver --- bsp/k230/applications/SConscript | 5 + bsp/k230/applications/display_demo/SConscript | 9 + .../applications/display_demo/display_demo.c | 74 ++ bsp/k230/board/Kconfig | 11 + bsp/k230/drivers/display/README.md | 103 +++ bsp/k230/drivers/display/SConscript | 20 + bsp/k230/drivers/display/bus_dsi.c | 346 +++++++++ bsp/k230/drivers/display/connector_bus.h | 36 + bsp/k230/drivers/display/connector_bus_dsi.h | 48 ++ bsp/k230/drivers/display/connector_panel.h | 78 ++ bsp/k230/drivers/display/drv_display.c | 474 +++++++++++++ bsp/k230/drivers/display/drv_display.h | 18 + .../display/include/k_connector_comm.h | 117 +++ bsp/k230/drivers/display/include/k_type.h | 36 + bsp/k230/drivers/display/include/k_vo_comm.h | 98 +++ bsp/k230/drivers/display/lib/vo_stubs.c | 19 + bsp/k230/drivers/display/panel_common.c | 252 +++++++ bsp/k230/drivers/display/panels/SConscript | 9 + bsp/k230/drivers/display/panels/mipi_st7701.c | 125 ++++ bsp/k230/drivers/display/vo/kd_dsi_reg.c | 669 ++++++++++++++++++ bsp/k230/drivers/display/vo/kd_dsi_reg.h | 32 + bsp/k230/drivers/display/vo/kd_vo_reg.c | 361 ++++++++++ bsp/k230/drivers/display/vo/kd_vo_reg.h | 26 + .../drivers/display/vo/vo_display_remap.h | 26 + bsp/k230/drivers/display/vo/vo_remap.c | 85 +++ 25 files changed, 3077 insertions(+) create mode 100644 bsp/k230/applications/display_demo/SConscript create mode 100644 bsp/k230/applications/display_demo/display_demo.c create mode 100644 bsp/k230/drivers/display/README.md create mode 100644 bsp/k230/drivers/display/SConscript create mode 100644 bsp/k230/drivers/display/bus_dsi.c create mode 100644 bsp/k230/drivers/display/connector_bus.h create mode 100644 bsp/k230/drivers/display/connector_bus_dsi.h create mode 100644 bsp/k230/drivers/display/connector_panel.h create mode 100644 bsp/k230/drivers/display/drv_display.c create mode 100644 bsp/k230/drivers/display/drv_display.h create mode 100644 bsp/k230/drivers/display/include/k_connector_comm.h create mode 100644 bsp/k230/drivers/display/include/k_type.h create mode 100644 bsp/k230/drivers/display/include/k_vo_comm.h create mode 100644 bsp/k230/drivers/display/lib/vo_stubs.c create mode 100644 bsp/k230/drivers/display/panel_common.c create mode 100644 bsp/k230/drivers/display/panels/SConscript create mode 100644 bsp/k230/drivers/display/panels/mipi_st7701.c create mode 100644 bsp/k230/drivers/display/vo/kd_dsi_reg.c create mode 100644 bsp/k230/drivers/display/vo/kd_dsi_reg.h create mode 100644 bsp/k230/drivers/display/vo/kd_vo_reg.c create mode 100644 bsp/k230/drivers/display/vo/kd_vo_reg.h create mode 100644 bsp/k230/drivers/display/vo/vo_display_remap.h create mode 100644 bsp/k230/drivers/display/vo/vo_remap.c diff --git a/bsp/k230/applications/SConscript b/bsp/k230/applications/SConscript index 9ffdfd6d3ac..86c67462cab 100644 --- a/bsp/k230/applications/SConscript +++ b/bsp/k230/applications/SConscript @@ -6,4 +6,9 @@ CPPPATH = [cwd] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + Return('group') diff --git a/bsp/k230/applications/display_demo/SConscript b/bsp/k230/applications/display_demo/SConscript new file mode 100644 index 00000000000..f639133b473 --- /dev/null +++ b/bsp/k230/applications/display_demo/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('DisplayDemo', src, depend=['BSP_USING_DISPLAY'], CPPPATH=CPPPATH) + +Return('group') diff --git a/bsp/k230/applications/display_demo/display_demo.c b/bsp/k230/applications/display_demo/display_demo.c new file mode 100644 index 00000000000..7ca46aa6020 --- /dev/null +++ b/bsp/k230/applications/display_demo/display_demo.c @@ -0,0 +1,74 @@ +/* Display demo: draw an RGB565 test pattern through the fb0 device. */ + +#include +#include +#include + +static rt_uint16_t rgb565(rt_uint8_t r, rt_uint8_t g, rt_uint8_t b) +{ + return (rt_uint16_t)(((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3)); +} + +static void display_demo(int argc, char** argv) +{ + rt_device_t fb; + struct rt_device_graphic_info info; + rt_uint16_t *line; + rt_uint16_t colors[] = { + rgb565(255, 0, 0), + rgb565(0, 255, 0), + rgb565(0, 0, 255), + rgb565(255, 255, 255), + rgb565(0, 0, 0), + }; + rt_size_t color_count = sizeof(colors) / sizeof(colors[0]); + + (void)argc; + (void)argv; + + fb = rt_device_find("fb0"); + if (!fb) { + rt_kprintf("display_demo: fb0 device not found\n"); + return; + } + + if (rt_device_open(fb, RT_DEVICE_FLAG_RDWR) != RT_EOK) { + rt_kprintf("display_demo: open fb0 failed\n"); + return; + } + + rt_memset(&info, 0, sizeof(info)); + if (rt_device_control(fb, RTGRAPHIC_CTRL_GET_INFO, &info) != RT_EOK || + info.pixel_format != RTGRAPHIC_PIXEL_FORMAT_RGB565) { + rt_kprintf("display_demo: unsupported framebuffer\n"); + rt_device_close(fb); + return; + } + + line = rt_malloc(info.pitch); + if (!line) { + rt_kprintf("display_demo: no memory\n"); + rt_device_close(fb); + return; + } + + for (rt_uint16_t y = 0; y < info.height; y++) { + for (rt_uint16_t x = 0; x < info.width; x++) { + rt_uint16_t band = (x * color_count) / info.width; + rt_uint16_t shade = (y * 31) / info.height; + + line[x] = colors[band]; + if (band == color_count - 1) + line[x] = (shade << 11) | (shade << 6) | shade; + } + rt_device_write(fb, y * info.pitch, line, info.pitch); + } + + rt_device_control(fb, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL); + rt_free(line); + rt_device_close(fb); + + rt_kprintf("display_demo: wrote %ux%u RGB565 test pattern\n", info.width, info.height); +} + +MSH_CMD_EXPORT(display_demo, draw RGB565 test pattern to fb0); diff --git a/bsp/k230/board/Kconfig b/bsp/k230/board/Kconfig index 11d7e6aae0b..35fbd31a782 100644 --- a/bsp/k230/board/Kconfig +++ b/bsp/k230/board/Kconfig @@ -4,6 +4,17 @@ menu "Drivers Configuration" bool "Enable KPU and AI2D" default n + menuconfig BSP_USING_DISPLAY + bool "Enable MIPI DSI Display (ST7701)" + select RT_USING_DEVICE + select RT_USING_DEVICE_OPS + select RT_USING_PIN + default n + help + Enable MIPI DSI display support for the atk_k230d board. + This registers lcd and fb0 graphic devices for the + 480x640 ST7701 panel over 2-lane MIPI DSI. + menuconfig BSP_USING_SPI bool "Enable SPI" select RT_USING_SPI diff --git a/bsp/k230/drivers/display/README.md b/bsp/k230/drivers/display/README.md new file mode 100644 index 00000000000..1e9028bcd09 --- /dev/null +++ b/bsp/k230/drivers/display/README.md @@ -0,0 +1,103 @@ +# K230 Display Driver + +This driver enables the ATK K230D ST7701 MIPI-DSI panel without linking the +hard-float `libvo.a`. The implementation is intentionally small: + +- `drv_display.c` registers RT-Thread graphic devices `lcd` and `fb0`. +- `panel_common.c`, `bus_dsi.c`, and `panels/` describe the panel, GPIO reset, + backlight, MIPI-DSI bus, and timing. +- `vo/` contains the lightweight VO/DSI register code that replaces the old + `libvo.a` dependency. + +## Configuration + +Enable: + +```text +BSP_USING_DISPLAY=y +``` + +The Kconfig option selects the RT-Thread device, device-ops, and pin APIs used +by this driver. The build is handled by `drivers/display/SConscript`; it builds +the local VO/DSI source files and does not link `libvo.a`. + +## Device Interface + +The driver registers: + +- `lcd`: compatible RT-Thread graphic device name. +- `fb0`: framebuffer-style graphic device intended for device-file access. + +Both devices share one RGB565 framebuffer. `RTGRAPHIC_CTRL_GET_INFO` returns +`struct rt_device_graphic_info`: + +- `pixel_format`: `RTGRAPHIC_PIXEL_FORMAT_RGB565` +- `bits_per_pixel`: `16` +- `pitch`: bytes per line +- `width`, `height`: panel active size +- `framebuffer`, `smem_len`: kernel framebuffer address and size + +Supported controls: + +- `RTGRAPHIC_CTRL_GET_INFO` +- `RTGRAPHIC_CTRL_RECT_UPDATE` +- `RTGRAPHIC_CTRL_POWERON` +- `RTGRAPHIC_CTRL_POWEROFF` +- `RTGRAPHIC_CTRL_SET_BRIGHTNESS` +- `RTGRAPHIC_CTRL_GET_BRIGHTNESS` +- `RTGRAPHIC_CTRL_WAIT_VSYNC` + +`read()` and `write()` operate on byte offsets in the RGB565 framebuffer. Writes +flush the CPU data cache for the updated range. + +## Kernel Shell Example + +```text +list_device +list_display +display_demo +``` + +`display_demo` opens `fb0`, queries `RTGRAPHIC_CTRL_GET_INFO`, writes an RGB565 +test pattern, then calls `RTGRAPHIC_CTRL_RECT_UPDATE`. + +## User-Space Example + +```c +#include +#include +#include + +int main(void) +{ + int fd = open("/dev/fb0", O_RDWR); + uint16_t line[480]; + + if (fd < 0) + return -1; + + for (int x = 0; x < 480; x++) + line[x] = 0xf800; /* red in RGB565 */ + + for (int y = 0; y < 640; y++) + write(fd, line, sizeof(line)); + + close(fd); + return 0; +} +``` + +Use RGB565 pixels. For partial updates, seek to `y * pitch + x * 2` before +writing if the user-space C library exposes `lseek()` for device files. + +## Notes + +This driver does not implement hardware acceleration. It only provides a CPU +framebuffer and the minimum panel/DSI/VO setup needed for display bring-up. + +The current local VO source covers reset, timing, mixer, background, DSI, and +register remap. The original hard-float `libvo.a` also contains lower-level +video/OSD layer address, stride, and format functions. Those functions must be +implemented from verified register definitions before claiming full framebuffer +scanout on hardware. Until then, `fb0` device-file drawing is present and cache +coherent, while actual panel scanout requires board validation. diff --git a/bsp/k230/drivers/display/SConscript b/bsp/k230/drivers/display/SConscript new file mode 100644 index 00000000000..2b8b1d523b4 --- /dev/null +++ b/bsp/k230/drivers/display/SConscript @@ -0,0 +1,20 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('lib/*.c') +src += [ + 'vo/vo_remap.c', + 'vo/kd_vo_reg.c', + 'vo/kd_dsi_reg.c', +] +CPPPATH = [cwd, cwd + '/include', cwd + '/vo'] + +group = DefineGroup('Display', src, depend=['BSP_USING_DISPLAY'], + CPPPATH=CPPPATH) + +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + +Return('group') diff --git a/bsp/k230/drivers/display/bus_dsi.c b/bsp/k230/drivers/display/bus_dsi.c new file mode 100644 index 00000000000..cb7a65a3080 --- /dev/null +++ b/bsp/k230/drivers/display/bus_dsi.c @@ -0,0 +1,346 @@ +/* Adapted from atk_k230d connector_bus_dsi.c for RT-Thread BSP */ + +#include +#include + +#include "connector_panel.h" +#include "connector_bus_dsi.h" + +#define DSI_PHY_REF_CLK 24000000 + +typedef struct { + k_u64 min_freq; + k_u64 max_freq; + k_u8 hsfreqrange; +} dsi_phy_hsfreq_range_t; + +static const dsi_phy_hsfreq_range_t hsfreq_ranges[] = { + { 2363125000ULL, 2500000000ULL, 0x49 }, { 2315625000ULL, 2500000000ULL, 0x48 }, { 2268125000ULL, 2500000000ULL, 0x47 }, + { 2220625000ULL, 2480625000ULL, 0x46 }, { 2173125000ULL, 2428125000ULL, 0x45 }, { 2125625000ULL, 2375625000ULL, 0x44 }, + { 2078125000ULL, 2323125000ULL, 0x43 }, { 2030625000ULL, 2270625000ULL, 0x42 }, { 1983125000ULL, 2218125000ULL, 0x41 }, + { 1935625000ULL, 2165625000ULL, 0x40 }, { 1888125000ULL, 2113125000ULL, 0x0F }, { 1840625000ULL, 2060625000ULL, 0x3F }, + { 1793125000ULL, 2008125000ULL, 0x2F }, { 1745625000ULL, 1955625000ULL, 0x1E }, { 1698125000ULL, 1903125000ULL, 0x0E }, + { 1650625000ULL, 1850625000ULL, 0x3E }, { 1603125000ULL, 1798125000ULL, 0x2E }, { 1555625000ULL, 1745625000ULL, 0x1D }, + { 1508125000ULL, 1693125000ULL, 0x0D }, { 1460625000ULL, 1640625000ULL, 0x3D }, { 1413125000ULL, 1588125000ULL, 0x2C }, + { 1365625000ULL, 1535625000ULL, 0x1C }, { 1318125000ULL, 1483125000ULL, 0x0C }, { 1270625000ULL, 1430625000ULL, 0x3C }, + { 1223125000ULL, 1378125000ULL, 0x2B }, { 1175625000ULL, 1325625000ULL, 0x1B }, { 1128125000ULL, 1273125000ULL, 0x0B }, + { 1080625000ULL, 1220625000ULL, 0x3B }, { 1033125000ULL, 1168125000ULL, 0x2A }, { 985625000ULL, 1115625000ULL, 0x1A }, + { 938125000ULL, 1063125000ULL, 0x0A }, { 890625000ULL, 1010625000ULL, 0x3A }, { 843125000ULL, 958125000ULL, 0x29 }, + { 795625000ULL, 905625000ULL, 0x19 }, { 748125000ULL, 853125000ULL, 0x09 }, { 700625000ULL, 800625000ULL, 0x39 }, + { 653125000ULL, 748125000ULL, 0x28 }, { 605625000ULL, 695625000ULL, 0x18 }, { 558125000ULL, 643125000ULL, 0x07 }, + { 510625000ULL, 590625000ULL, 0x37 }, { 463125000ULL, 538125000ULL, 0x26 }, { 415625000ULL, 485625000ULL, 0x16 }, + { 368125000ULL, 433125000ULL, 0x05 }, { 320625000ULL, 380625000ULL, 0x35 }, { 296875000ULL, 354375000ULL, 0x25 }, + { 273125000ULL, 328125000ULL, 0x14 }, { 249375000ULL, 301875000ULL, 0x04 }, { 225625000ULL, 275625000ULL, 0x33 }, + { 211375000ULL, 259875000ULL, 0x23 }, { 197125000ULL, 244125000ULL, 0x13 }, { 182875000ULL, 228375000ULL, 0x03 }, + { 168625000ULL, 212625000ULL, 0x32 }, { 159125000ULL, 202125000ULL, 0x22 }, { 149625000ULL, 191625000ULL, 0x12 }, + { 140125000ULL, 181125000ULL, 0x02 }, { 130625000ULL, 170625000ULL, 0x31 }, { 121125000ULL, 160125000ULL, 0x21 }, + { 111625000ULL, 149625000ULL, 0x11 }, { 102125000ULL, 139125000ULL, 0x01 }, { 92625000ULL, 128625000ULL, 0x30 }, + { 83125000ULL, 118125000ULL, 0x20 }, { 80000000ULL, 107625000ULL, 0x10 }, { 80000000ULL, 97125000ULL, 0x00 }, +}; + +static k_u32 dsi_lane_count(k_vo_dsi_lane_num lanes) +{ + switch (lanes) { + case K_DSI_1LAN: + return 1; + case K_DSI_2LAN: + return 2; + case K_DSI_4LAN: + return 4; + default: + return 0; + } +} + +static inline k_u32 dsi_bus_calc_lane_clk(const k_vo_timing* res, k_vo_dsi_lane_num lanes) +{ + k_u32 lane_count = dsi_lane_count(lanes); + + if (!res || res->pclk_khz == 0 || lane_count == 0) + return 0; + + return ((res->pclk_khz * 3 * 8 * 1000) / (lane_count * 2)); +} + +static k_u32 dsi_phy_calc_hsfreqrange(k_u64 bitrate_hz) +{ + int num_ranges = sizeof(hsfreq_ranges) / sizeof(hsfreq_ranges[0]); + + for (int i = 0; i < num_ranges; i++) { + if (bitrate_hz >= hsfreq_ranges[i].min_freq && bitrate_hz <= hsfreq_ranges[i].max_freq) { + return hsfreq_ranges[i].hsfreqrange; + } + } + + rt_kprintf("dsi_phy: unsupported bitrate %llu Hz\n", bitrate_hz); + return 0; +} + +static k_u32 dsi_phy_calc_vco(k_u32 fout_hz) +{ + if (fout_hz >= 1100000000 && fout_hz <= 1250000000) return 0x01; + if (fout_hz >= 630000000 && fout_hz <= 1149000000) return 0x03; + if (fout_hz >= 420000000 && fout_hz <= 660000000) return 0x07; + if (fout_hz >= 320000000 && fout_hz <= 440000000) return 0x0F; + if (fout_hz >= 210000000 && fout_hz <= 330000000) return 0x17; + if (fout_hz >= 160000000 && fout_hz <= 220000000) return 0x1F; + if (fout_hz >= 105000000 && fout_hz <= 165000000) return 0x27; + if (fout_hz >= 80000000 && fout_hz <= 110000000) return 0x2F; + if (fout_hz >= 52500000 && fout_hz <= 82500000) return 0x37; + if (fout_hz >= 40000000 && fout_hz <= 55000000) return 0x3F; + + rt_kprintf("dsi_phy: unsupported VCO frequency %u Hz\n", fout_hz); + return 0x17; +} + +static int dsi_phy_calc_m_and_n_impl(k_u32 fout, k_u32 mut, k_u32 clkin, k_u32* om, k_u32* on) +{ + for (int n = 1; n <= 16; n++) { + uint64_t numerator = (uint64_t)fout * mut * (n + 1); + if (numerator % clkin == 0) { + uint32_t mp2 = numerator / clkin; + if (mp2 >= 42 && mp2 <= 627) { + *om = mp2 - 2; + *on = n; + return 0; + } + } + } + + rt_kprintf("dsi_phy: can't generate phy attr with configuration\n"); + rt_kprintf("dsi_phy: try to increase or decrease pclk\n"); + return -1; +} + +static int dsi_phy_calc_m_and_n(k_u32 fout, k_u32* m, k_u32* n) +{ + k_u32 mut = 1; + + if (fout >= 320000000 && fout <= 1250000000) + mut = 1; + else if (fout >= 160000000 && fout <= 320000000) + mut = 2; + else if (fout >= 80000000 && fout <= 160000000) + mut = 4; + else if (fout >= 40000000 && fout <= 80000000) + mut = 8; + else + rt_kprintf("dsi_phy: unsupported MIPI Phy Clock: %u\n", fout); + + return dsi_phy_calc_m_and_n_impl(fout, mut, DSI_PHY_REF_CLK, m, n); +} + +static int dsi_bus_check_lane_clk(k_u32 lane_clk_hz) +{ + k_u32 mut = 1; + + if (lane_clk_hz == 0) + return -1; + + if (lane_clk_hz >= 320000000 && lane_clk_hz <= 1250000000) + mut = 1; + else if (lane_clk_hz >= 160000000 && lane_clk_hz <= 320000000) + mut = 2; + else if (lane_clk_hz >= 80000000 && lane_clk_hz <= 160000000) + mut = 4; + else if (lane_clk_hz >= 40000000 && lane_clk_hz <= 80000000) + mut = 8; + else + return -1; + + for (int n = 1; n <= 16; n++) { + uint64_t numerator = (uint64_t)lane_clk_hz * mut * (n + 1); + if (numerator % DSI_PHY_REF_CLK == 0) { + uint32_t mp2 = numerator / DSI_PHY_REF_CLK; + if (mp2 >= 42 && mp2 <= 627) + return 0; + } + } + + return -1; +} + +k_u32 dsi_correct_pclk(k_u32 pclk_hz, k_vo_dsi_lane_num lanes) +{ + k_u32 ratio, candidate_pclk, lane_clk, lane_count; + int delta; + + lane_count = dsi_lane_count(lanes); + if (pclk_hz == 0 || lane_count == 0) + return 0; + + ratio = (VO_PIXEL_CLOCK_HZ + pclk_hz / 2) / pclk_hz; + if (ratio == 0) + ratio = 1; + + for (delta = 0; delta <= 10; delta++) { + if (ratio + delta > 0) { + candidate_pclk = VO_PIXEL_CLOCK_HZ / (ratio + delta); + lane_clk = (candidate_pclk / 1000 * 3 * 8 * 1000) / (lane_count * 2); + if (dsi_bus_check_lane_clk(lane_clk) == 0) + return candidate_pclk; + } + if (delta > 0 && ratio > (k_u32)delta) { + candidate_pclk = VO_PIXEL_CLOCK_HZ / (ratio - delta); + lane_clk = (candidate_pclk / 1000 * 3 * 8 * 1000) / (lane_count * 2); + if (dsi_bus_check_lane_clk(lane_clk) == 0) + return candidate_pclk; + } + } + + return 0; +} + +static int dsi_bus_calculate_phy_attr(k_u32 lane_clk_hz, k_u32* n, k_u32* m, k_u32* voc, k_u32* hs_freq) +{ + k_u32 m_val, n_val; + + if (!n || !m || !voc || !hs_freq || lane_clk_hz == 0) + return -1; + + if (dsi_phy_calc_m_and_n(lane_clk_hz, &m_val, &n_val) != 0) + return -1; + + *m = m_val; + *n = n_val; + *voc = dsi_phy_calc_vco(lane_clk_hz); + *hs_freq = 0x80 | dsi_phy_calc_hsfreqrange(lane_clk_hz * 2); + + return 0; +} + +static int dsi_bus_init(const struct panel_desc* desc) +{ + k_u32 lane_clk; + k_u32 m, n, voc, hs_freq; + k_vo_dsi_config cfg; + + if (!desc) + return -1; + + lane_clk = dsi_bus_calc_lane_clk(&desc->timing, desc->bus.dsi.lanes); + if (lane_clk == 0) { + rt_kprintf("dsi_bus_init: failed to calculate lane_clk\n"); + return -2; + } + + if (dsi_bus_calculate_phy_attr(lane_clk, &n, &m, &voc, &hs_freq) != 0) { + rt_kprintf("dsi_bus_init: failed to calculate phy attr\n"); + return -3; + } + + cfg.phy.datarate = lane_clk * 2; + cfg.phy.m = m; + cfg.phy.n = n; + cfg.phy.voc = voc; + cfg.phy.hs_freq = hs_freq; + + cfg.timing = &desc->timing; + cfg.lanes = desc->bus.dsi.lanes; + cfg.cmd_mode = desc->bus.dsi.cmd_mode; + cfg.video_mode = desc->bus.dsi.video_mode; + cfg.vc_id = desc->bus.dsi.vc_id; + cfg.lp_speed_mhz = desc->bus.dsi.lp_cmd_speed_mhz; + + dwc_dsi_init(&cfg); + + if (desc->ops && desc->ops->read_chip_id) { + k_u32 chipid = desc->ops->read_chip_id(desc); + rt_kprintf("panel %s, chip id: 0x%08x\n", desc->name, chipid); + } + + return 0; +} + +static int dsi_bus_enable(const struct panel_desc* desc) +{ + if (!desc) + return -1; + + dwc_dsi_enable(); + return 0; +} + +k_s32 dsi_send_cmd_sequence(const struct panel_desc* desc, const k_u8* cmd_seq, size_t cmd_size, k_bool dump) +{ + uint32_t cmd_remain; + const uint8_t * pcmd, *pcmd_end; + k_connector_cmd_slice* cmd; + + if (!cmd_seq || !desc) { + rt_kprintf("no init sequence set.\n"); + return -1; + } + + pcmd = cmd_seq; + pcmd_end = pcmd + cmd_size; + + do { + cmd = (k_connector_cmd_slice*)pcmd; + cmd_remain = pcmd_end - pcmd; + + if (cmd->cmd_size > (cmd_remain - sizeof(k_connector_cmd_slice))) { + rt_kprintf("error cmd sequence. %d > %d\n", cmd->cmd_size, + cmd_remain - (int)sizeof(k_connector_cmd_slice)); + break; + } + + if (cmd->cmd_size) { + if ((DSI_DCS_SHORT_WRITE == cmd->cmd_type) || (DSI_DCS_SHORT_WRITE_PARAM == cmd->cmd_type) + || (DSI_DCS_LONG_WRITE == cmd->cmd_type)) { + + if (dwc_dsi_dcs_write(cmd->cmd_data, cmd->cmd_size, desc->bus.dsi.vc_id) != 0) { + rt_kprintf("dsi send cmd failed, but we treat it as non-fatal\n"); + return 0; + } + } else if ((DSI_GENERIC_SHORT_WRITE_0_PARAM == cmd->cmd_type) || (DSI_GENERIC_SHORT_WRITE_1_PARAM == cmd->cmd_type) + || (DSI_GENERIC_SHORT_WRITE_2_PARAM == cmd->cmd_type) || (DSI_GENERIC_LONG_WRITE == cmd->cmd_type)) { + + if (dwc_dsi_generic_write(cmd->cmd_data, cmd->cmd_size, desc->bus.dsi.vc_id) != 0) { + rt_kprintf("dsi send cmd failed, but we treat it as non-fatal\n"); + return 0; + } + } else { + rt_kprintf("unsupport cmd type 0x%02X\n", cmd->cmd_type); + return -2; + } + + if (dump) { + rt_kprintf("cmd[0x%02x] -> delay %u, data:", cmd->cmd_type, cmd->cmd_delay); + for (int i = 0; i < cmd->cmd_size; i++) + rt_kprintf("%02X ", cmd->cmd_data[i]); + rt_kprintf("\n"); + } + + if (cmd->cmd_delay) + rt_hw_us_delay((uint64_t)(cmd->cmd_delay) * 1000); + } + + pcmd += sizeof(k_connector_cmd_slice) + cmd->cmd_size; + } while (pcmd < pcmd_end); + + return 0; +} + +k_u32 dsi_read_chip_id(const struct panel_desc* desc) +{ + if (!desc) + return 0xDEADBEEF; + + k_u8 vc = desc->bus.dsi.vc_id; + k_u8 id[3] = { 0x03, 0x00, 0x00 }; + + if (dwc_dsi_send_packet(0x37, vc, id, 1, 1) != 0) + return 0xDEADBEEF; + + if (dwc_dsi_dcs_read(0x04, &id[0], 3, vc) != 3) + return 0xDEADBEEF; + + return (k_u32)((id[0] << 16) | (id[1] << 8) | id[2]); +} + +const struct panel_bus_ops dsi_bus_ops = { + .init = dsi_bus_init, + .enable = dsi_bus_enable, + .disable = NULL, +}; diff --git a/bsp/k230/drivers/display/connector_bus.h b/bsp/k230/drivers/display/connector_bus.h new file mode 100644 index 00000000000..0390e2cb813 --- /dev/null +++ b/bsp/k230/drivers/display/connector_bus.h @@ -0,0 +1,36 @@ +#ifndef _CONNECTOR_BUS_H_ +#define _CONNECTOR_BUS_H_ + +#include "connector_bus_dsi.h" +#include "k_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct panel_desc; + +enum panel_bus_type { + PANEL_BUS_DSI, + PANEL_BUS_SPI, + PANEL_BUS_I8080_SPI, + PANEL_BUS_QSPI, + PANEL_BUS_NONE, +}; + +struct panel_bus_ops { + int (*init)(const struct panel_desc* desc); + int (*enable)(const struct panel_desc* desc); + int (*disable)(const struct panel_desc* desc); + int (*send_cmd)(const struct panel_desc* desc, k_u8 cmd, + const k_u8* data, k_u32 len); + int (*send_frame)(const struct panel_desc* desc, void* data, k_u32 size); +}; + +extern const struct panel_bus_ops dsi_bus_ops; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONNECTOR_BUS_H_ */ diff --git a/bsp/k230/drivers/display/connector_bus_dsi.h b/bsp/k230/drivers/display/connector_bus_dsi.h new file mode 100644 index 00000000000..50427d08394 --- /dev/null +++ b/bsp/k230/drivers/display/connector_bus_dsi.h @@ -0,0 +1,48 @@ +#ifndef _CONNECTOR_BUS_DSI_H_ +#define _CONNECTOR_BUS_DSI_H_ + +#include +#include + +#include "k_vo_comm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct panel_desc; + +/* MIPI DSI DCS Command Types */ +#define DSI_DCS_SHORT_WRITE 0x05 +#define DSI_DCS_SHORT_WRITE_PARAM 0x15 +#define DSI_DCS_LONG_WRITE 0x39 + +/* MIPI DSI Generic Command Types */ +#define DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03 +#define DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13 +#define DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23 +#define DSI_GENERIC_LONG_WRITE 0x29 + +k_s32 dsi_send_cmd_sequence(const struct panel_desc* desc, const k_u8* cmd_seq, + size_t cmd_size, k_bool dump); +k_u32 dsi_read_chip_id(const struct panel_desc* desc); +k_u32 dsi_correct_pclk(k_u32 pclk_hz, k_vo_dsi_lane_num lanes); + +/* DWC DSI controller HAL implemented by display/vo. */ +void dwc_dsi_init(k_vo_dsi_config* cfg); +int dwc_dsi_enable(void); +int dwc_dsi_disable(void); +int dwc_dsi_send_packet(uint8_t type, uint8_t vc, const void* data, + uint32_t len, bool req_ack); +int dwc_dsi_dcs_write(const void* data, uint32_t len, uint8_t vc); +int dwc_dsi_dcs_read(uint8_t addr, void* buf, uint32_t len, uint8_t vc); +int dwc_dsi_generic_write(const void* data, uint32_t len, uint8_t vc); +int dwc_dsi_generic_read(const void* cmd, uint32_t cmd_len, + void* buf, uint32_t len, uint8_t vc); +void dwc_dsi_dump_reg_val(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _CONNECTOR_BUS_DSI_H_ */ diff --git a/bsp/k230/drivers/display/connector_panel.h b/bsp/k230/drivers/display/connector_panel.h new file mode 100644 index 00000000000..3763bb75479 --- /dev/null +++ b/bsp/k230/drivers/display/connector_panel.h @@ -0,0 +1,78 @@ +#ifndef _CONNECTOR_PANEL_H_ +#define _CONNECTOR_PANEL_H_ + +#include "k_connector_comm.h" +#include "k_vo_comm.h" + +#include "connector_bus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define VO_PIXEL_CLOCK_HZ 594000000UL +#define PANEL_BG_COLOR_BLACK 0x00000000 +#define PANEL_BG_COLOR_WHITE 0x00FFFFFF + +struct panel_desc; + +struct panel_drv { + const char* connector_name; + const struct panel_desc** panel_variants; + const struct panel_desc* active_panel; +}; + +struct panel_gpio_config { + k_s32 reset_pin; + k_u32 reset_delay_ms; + k_u32 backlight_delay_ms; + k_s32 backlight_pin; + k_bool reset_active_low; + k_bool backlight_active_low; +}; + +struct panel_dsi_config { + k_vo_dsi_lane_num lanes; + k_u32 cmd_mode; + k_vo_dsi_video_mode video_mode; + k_u8 vc_id; + k_u8 lp_cmd_speed_mhz; +}; + +struct panel_ops { + int (*reset)(const struct panel_desc* desc); + int (*init)(const struct panel_desc* desc); + int (*power_off)(const struct panel_desc* desc); + k_u32 (*read_chip_id)(const struct panel_desc* desc); +}; + +struct panel_desc { + const char* name; + k_u32 connector_type; + enum panel_bus_type bus_type; + + k_vo_timing timing; + k_u32 bg_color; + + struct panel_gpio_config gpio; + + union { + struct panel_dsi_config dsi; + } bus; + + const struct panel_bus_ops* bus_ops; + const struct panel_ops* ops; +}; + +k_u32 panel_correct_pclk(k_u32 pclk); +int panel_calculate_fps(const k_vo_timing* timing); +int panel_generic_reset(const struct panel_desc* desc); +int panel_generic_backlight(const struct panel_desc* desc, k_u32 mode, k_u32 duty); +k_s32 panel_generic_power_on(struct panel_desc* desc); +k_s32 panel_generic_power_off(const struct panel_desc* desc); + +#ifdef __cplusplus +} +#endif + +#endif /* _CONNECTOR_PANEL_H_ */ diff --git a/bsp/k230/drivers/display/drv_display.c b/bsp/k230/drivers/display/drv_display.c new file mode 100644 index 00000000000..23eea2c99d6 --- /dev/null +++ b/bsp/k230/drivers/display/drv_display.c @@ -0,0 +1,474 @@ +/* RT-Thread display driver for K230D */ + +#include +#include +#include +#include + +#ifdef RT_USING_SMART +#include +#include +#ifdef RT_USING_DFS +#include +#endif +#endif + +#include "connector_panel.h" +#include "drv_display.h" +#include "vo_display_remap.h" + +extern void kd_vo_set_background(k_u32 rgb888); + +extern struct panel_drv mipi_st7701_drv; + +static struct { + struct rt_device lcd; + struct rt_device fb; + struct rt_device_graphic_info info; + struct panel_desc* panel; + struct rt_mutex lock; + rt_uint8_t* framebuffer; + void* framebuffer_pa; + rt_size_t framebuffer_size; + rt_uint8_t brightness; + rt_bool_t initialized; +} g_display; + +static struct panel_drv* display_drv_list[] = { + &mipi_st7701_drv, + RT_NULL, +}; + +static const struct panel_desc* find_panel_by_name(const char* name) +{ + for (int i = 0; display_drv_list[i] != RT_NULL; i++) { + struct panel_drv* drv = display_drv_list[i]; + + if (drv->panel_variants) { + for (int j = 0; drv->panel_variants[j] != RT_NULL; j++) { + if (rt_strcmp(drv->panel_variants[j]->name, name) == 0) + return drv->panel_variants[j]; + } + } + if (drv->active_panel && rt_strcmp(drv->active_panel->name, name) == 0) + return drv->active_panel; + } + return RT_NULL; +} + +static void display_flush_range(rt_uint8_t *addr, rt_size_t size) +{ + if (addr && size) + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size); +} + +static void display_flush_rect(const struct rt_device_rect_info *rect) +{ + rt_uint16_t x; + rt_uint16_t y; + rt_uint16_t width; + rt_uint16_t height; + rt_uint8_t bytes_per_pixel = g_display.info.bits_per_pixel / 8; + rt_size_t line_bytes; + + if (!g_display.framebuffer) + return; + + if (!rect) { + display_flush_range(g_display.framebuffer, g_display.framebuffer_size); + return; + } + + if (rect->x >= g_display.info.width || rect->y >= g_display.info.height) + return; + + x = rect->x; + y = rect->y; + width = rect->width; + height = rect->height; + + if (x + width > g_display.info.width) + width = g_display.info.width - x; + if (y + height > g_display.info.height) + height = g_display.info.height - y; + if (width == 0 || height == 0) + return; + + line_bytes = width * bytes_per_pixel; + if (x == 0 && width == g_display.info.width) { + display_flush_range(g_display.framebuffer + y * g_display.info.pitch, + height * g_display.info.pitch); + return; + } + + for (rt_uint16_t row = 0; row < height; row++) { + display_flush_range(g_display.framebuffer + (y + row) * g_display.info.pitch + + x * bytes_per_pixel, + line_bytes); + } +} + +static rt_err_t display_init(rt_device_t dev) +{ + rt_size_t fb_size; + + (void)dev; + + if (g_display.initialized) + return RT_EOK; + + if (!g_display.panel) { + rt_kprintf("display: no panel selected\n"); + return -RT_ERROR; + } + + if (vo_display_remap_init() != 0) { + rt_kprintf("display: register remap failed\n"); + return -RT_ERROR; + } + + fb_size = g_display.panel->timing.hactive * g_display.panel->timing.vactive * 2; + g_display.framebuffer = rt_malloc_align(fb_size, K230_DISPLAY_FB_ALIGN); + if (!g_display.framebuffer) { + rt_kprintf("display: framebuffer allocation failed\n"); + return -RT_ENOMEM; + } + + rt_memset(g_display.framebuffer, 0, fb_size); + g_display.framebuffer_pa = rt_kmem_v2p(g_display.framebuffer); + if (!g_display.framebuffer_pa || g_display.framebuffer_pa == ARCH_MAP_FAILED) { + rt_kprintf("display: framebuffer physical address failed\n"); + rt_free_align(g_display.framebuffer); + g_display.framebuffer = RT_NULL; + return -RT_ERROR; + } + + g_display.framebuffer_size = fb_size; + g_display.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; + g_display.info.bits_per_pixel = 16; + g_display.info.pitch = g_display.panel->timing.hactive * 2; + g_display.info.width = g_display.panel->timing.hactive; + g_display.info.height = g_display.panel->timing.vactive; + g_display.info.framebuffer = g_display.framebuffer; + g_display.info.smem_len = fb_size; + display_flush_range(g_display.framebuffer, fb_size); + + if (panel_generic_power_on(g_display.panel) != 0) { + rt_kprintf("display: power_on failed\n"); + rt_free_align(g_display.framebuffer); + g_display.framebuffer = RT_NULL; + g_display.framebuffer_pa = RT_NULL; + g_display.framebuffer_size = 0; + rt_memset(&g_display.info, 0, sizeof(g_display.info)); + return -RT_ERROR; + } + + g_display.initialized = RT_TRUE; + g_display.brightness = 255; + + panel_generic_backlight(g_display.panel, 1, g_display.brightness); + + return RT_EOK; +} + +static rt_err_t display_open(rt_device_t dev, rt_uint16_t oflag) +{ + (void)oflag; + return display_init(dev); +} + +static rt_err_t display_close(rt_device_t dev) +{ + (void)dev; + return RT_EOK; +} + +static rt_ssize_t display_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_size_t count; + + (void)dev; + + if (!buffer || !g_display.framebuffer || pos < 0) + return 0; + if ((rt_size_t)pos >= g_display.framebuffer_size) + return 0; + + count = g_display.framebuffer_size - (rt_size_t)pos; + if (count > size) + count = size; + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + rt_memcpy(buffer, g_display.framebuffer + pos, count); + rt_mutex_release(&g_display.lock); + + return count; +} + +static rt_ssize_t display_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_size_t count; + + (void)dev; + + if (!buffer || !g_display.framebuffer || pos < 0) + return 0; + if ((rt_size_t)pos >= g_display.framebuffer_size) + return 0; + + count = g_display.framebuffer_size - (rt_size_t)pos; + if (count > size) + count = size; + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + rt_memcpy(g_display.framebuffer + pos, buffer, count); + display_flush_range(g_display.framebuffer + pos, count); + rt_mutex_release(&g_display.lock); + + return count; +} + +static rt_err_t display_control(rt_device_t dev, int cmd, void* args) +{ + (void)dev; + + switch (cmd) { + case RTGRAPHIC_CTRL_GET_INFO: + if (!args) + return -RT_EINVAL; + rt_memcpy(args, &g_display.info, sizeof(g_display.info)); + break; + case RTGRAPHIC_CTRL_RECT_UPDATE: + display_flush_rect((const struct rt_device_rect_info *)args); + break; + case RTGRAPHIC_CTRL_POWERON: + case LCD_CTRL_BACKLIGHT_ON: + panel_generic_backlight(g_display.panel, 1, g_display.brightness); + break; + case RTGRAPHIC_CTRL_POWEROFF: + case LCD_CTRL_BACKLIGHT_OFF: + panel_generic_backlight(g_display.panel, 0, 0); + break; + case RTGRAPHIC_CTRL_SET_BRIGHTNESS: + g_display.brightness = args ? *(rt_uint8_t *)args : 0; + panel_generic_backlight(g_display.panel, g_display.brightness ? 1 : 0, + g_display.brightness); + break; + case RTGRAPHIC_CTRL_GET_BRIGHTNESS: + if (!args) + return -RT_EINVAL; + *(rt_uint8_t *)args = g_display.brightness; + break; + case RTGRAPHIC_CTRL_WAIT_VSYNC: + rt_thread_mdelay(1000 / 60); + break; + case LCD_CTRL_SET_BG_COLOR: + if (args) + kd_vo_set_background(*(k_u32*)args); + break; +#ifdef RT_FIOMMAP2 + case RT_FIOMMAP2: + { + struct dfs_mmap2_args *mmap2 = (struct dfs_mmap2_args *)args; + + if (!mmap2 || !g_display.framebuffer_pa) + return -RT_EINVAL; + if (mmap2->length > g_display.framebuffer_size) + return -RT_ENOMEM; + + mmap2->ret = lwp_map_user_phy(lwp_self(), RT_NULL, g_display.framebuffer_pa, + mmap2->length, 1); + break; + } +#endif + default: + return -RT_ERROR; + } + return RT_EOK; +} + +static void display_set_pixel(const char *pixel, int x, int y) +{ + rt_uint8_t *dst; + rt_uint8_t bytes_per_pixel = g_display.info.bits_per_pixel / 8; + + if (!pixel || !g_display.framebuffer || x < 0 || y < 0 || + x >= g_display.info.width || y >= g_display.info.height) + return; + + dst = g_display.framebuffer + y * g_display.info.pitch + x * bytes_per_pixel; + rt_memcpy(dst, pixel, bytes_per_pixel); + display_flush_range(dst, bytes_per_pixel); +} + +static void display_get_pixel(char *pixel, int x, int y) +{ + rt_uint8_t *src; + rt_uint8_t bytes_per_pixel = g_display.info.bits_per_pixel / 8; + + if (!pixel || !g_display.framebuffer || x < 0 || y < 0 || + x >= g_display.info.width || y >= g_display.info.height) + return; + + src = g_display.framebuffer + y * g_display.info.pitch + x * bytes_per_pixel; + rt_memcpy(pixel, src, bytes_per_pixel); +} + +static void display_draw_hline(const char *pixel, int x1, int x2, int y) +{ + rt_uint8_t bytes_per_pixel = g_display.info.bits_per_pixel / 8; + rt_uint8_t *dst; + + if (!pixel || !g_display.framebuffer || y < 0 || y >= g_display.info.height) + return; + + if (x1 > x2) { + int tmp = x1; + x1 = x2; + x2 = tmp; + } + + if (x2 < 0 || x1 >= g_display.info.width) + return; + if (x1 < 0) + x1 = 0; + if (x2 >= g_display.info.width) + x2 = g_display.info.width - 1; + + dst = g_display.framebuffer + y * g_display.info.pitch + x1 * bytes_per_pixel; + for (int x = x1; x <= x2; x++) { + rt_memcpy(dst, pixel, bytes_per_pixel); + dst += bytes_per_pixel; + } + display_flush_range(g_display.framebuffer + y * g_display.info.pitch + x1 * bytes_per_pixel, + (x2 - x1 + 1) * bytes_per_pixel); +} + +static void display_draw_vline(const char *pixel, int x, int y1, int y2) +{ + if (!pixel || !g_display.framebuffer || x < 0 || x >= g_display.info.width) + return; + + if (y1 > y2) { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + + if (y2 < 0 || y1 >= g_display.info.height) + return; + if (y1 < 0) + y1 = 0; + if (y2 >= g_display.info.height) + y2 = g_display.info.height - 1; + + for (int y = y1; y <= y2; y++) + display_set_pixel(pixel, x, y); +} + +static void display_blit_line(const char *pixel, int x, int y, rt_size_t size) +{ + rt_uint8_t bytes_per_pixel = g_display.info.bits_per_pixel / 8; + rt_uint8_t *dst; + rt_size_t max_size; + + if (!pixel || !g_display.framebuffer || x < 0 || y < 0 || + x >= g_display.info.width || y >= g_display.info.height) + return; + + max_size = (g_display.info.width - x) * bytes_per_pixel; + if (size > max_size) + size = max_size; + + dst = g_display.framebuffer + y * g_display.info.pitch + x * bytes_per_pixel; + rt_memcpy(dst, pixel, size); + display_flush_range(dst, size); +} + +static struct rt_device_graphic_ops display_graphic_ops = { + .set_pixel = display_set_pixel, + .get_pixel = display_get_pixel, + .draw_hline = display_draw_hline, + .draw_vline = display_draw_vline, + .blit_line = display_blit_line, +}; + +static void list_display(int argc, char** argv) +{ + (void)argc; + (void)argv; + + rt_kprintf("Display Panels:\n"); + rt_kprintf("%-24s %-12s %-7s\n", "NAME", "RESOLUTION", "FPS"); + rt_kprintf("%-24s %-12s %-7s\n", "------------------------", "------------", "-------"); + + int shown = 0; + for (int i = 0; display_drv_list[i] != RT_NULL; i++) { + struct panel_drv* drv = display_drv_list[i]; + + if (drv->panel_variants) { + for (int j = 0; drv->panel_variants[j] != RT_NULL; j++) { + const struct panel_desc* panel = drv->panel_variants[j]; + int fps = panel_calculate_fps(&panel->timing); + rt_kprintf("%-24s %4ux%-4u %3d fps\n", + panel->name, panel->timing.hactive, + panel->timing.vactive, fps); + shown++; + } + } else if (drv->active_panel) { + const struct panel_desc* panel = drv->active_panel; + int fps = panel_calculate_fps(&panel->timing); + rt_kprintf("%-24s %4ux%-4u %3d fps\n", + panel->name, panel->timing.hactive, panel->timing.vactive, fps); + shown++; + } + } + + if (shown == 0) + rt_kprintf("No panels registered.\n"); +} + +MSH_CMD_EXPORT(list_display, list display panels); + +static const struct rt_device_ops display_ops = { + .init = display_init, + .open = display_open, + .close = display_close, + .read = display_read, + .write = display_write, + .control = display_control, +}; + +int k230_display_init(void) +{ + rt_memset(&g_display, 0, sizeof(g_display)); + + g_display.panel = (struct panel_desc*)find_panel_by_name("st7701_480x640_atk"); + if (!g_display.panel) { + rt_kprintf("display: st7701_480x640_atk panel not found\n"); + return -1; + } + + rt_mutex_init(&g_display.lock, "display", RT_IPC_FLAG_PRIO); + + g_display.lcd.type = RT_Device_Class_Graphic; + g_display.lcd.ops = &display_ops; + g_display.lcd.user_data = &display_graphic_ops; + + g_display.fb.type = RT_Device_Class_Graphic; + g_display.fb.ops = &display_ops; + g_display.fb.user_data = &display_graphic_ops; + + rt_device_register(&g_display.lcd, "lcd", RT_DEVICE_FLAG_RDWR); + rt_device_register(&g_display.fb, "fb0", RT_DEVICE_FLAG_RDWR); + + if (display_init(&g_display.lcd) != RT_EOK) { + rt_kprintf("display: auto-init failed\n"); + return -1; + } + + rt_kprintf("display: lcd/fb0 device ready, %ux%u RGB565\n", + g_display.info.width, g_display.info.height); + return 0; +} +INIT_DEVICE_EXPORT(k230_display_init); diff --git a/bsp/k230/drivers/display/drv_display.h b/bsp/k230/drivers/display/drv_display.h new file mode 100644 index 00000000000..3de9fd2cf2f --- /dev/null +++ b/bsp/k230/drivers/display/drv_display.h @@ -0,0 +1,18 @@ +#ifndef _DRV_DISPLAY_H_ +#define _DRV_DISPLAY_H_ + +#include + +/* K230D board pins */ +#define K230D_LCD_RESET_PIN 3 +#define K230D_LCD_BACKLIGHT_PIN 5 + +#define K230_DISPLAY_FB_ALIGN 64 + +#define LCD_CTRL_BACKLIGHT_OFF 0 +#define LCD_CTRL_BACKLIGHT_ON 1 +#define LCD_CTRL_SET_BG_COLOR 2 + +int k230_display_init(void); + +#endif /* _DRV_DISPLAY_H_ */ diff --git a/bsp/k230/drivers/display/include/k_connector_comm.h b/bsp/k230/drivers/display/include/k_connector_comm.h new file mode 100644 index 00000000000..02191bff1f5 --- /dev/null +++ b/bsp/k230/drivers/display/include/k_connector_comm.h @@ -0,0 +1,117 @@ +#ifndef __K_CONNECTOR_COMM_H__ +#define __K_CONNECTOR_COMM_H__ + +#include "k_type.h" +#include "k_vo_comm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Connector chip identifier */ +typedef enum { + K_CHIP_VIRTUAL = 0, + K_CHIP_HX8399 = 1, + K_CHIP_ILI9806 = 2, + K_CHIP_ILI9881 = 3, + K_CHIP_NT35516 = 4, + K_CHIP_NT35532 = 5, + K_CHIP_GC9503 = 6, + K_CHIP_ST7102 = 7, + K_CHIP_AML020T = 8, + K_CHIP_ST7701 = 9, + K_CHIP_JD9852 = 10, + K_CHIP_LT9611 = 11, + K_CHIP_ST7789 = 12, + K_CHIP_NV3030B = 13, +} k_connector_chip; + +/** Connector bus type */ +typedef enum { + K_BUS_DSI = 0, + K_BUS_HDMI = 1, + K_BUS_SPI = 2, +} k_connector_bus; + +/* + * k_connector_type encoding (32-bit): + * [31:26] chip (6 bits) + * [25:24] bus (2 bits) + * [23:20] version (4 bits) + * [19:10] width (10 bits) — h >> 1 + * [9:0] height (10 bits) — v >> 1 + */ +#define _CONN_CHIP_BITS 6 +#define _CONN_BUS_BITS 2 +#define _CONN_VER_BITS 4 +#define _CONN_W_BITS 10 +#define _CONN_H_BITS 10 + +#define _CONN_H_SHIFT 0 +#define _CONN_W_SHIFT 10 +#define _CONN_VER_SHIFT 20 +#define _CONN_BUS_SHIFT 24 +#define _CONN_CHIP_SHIFT 26 + +#define _CONN_MASK(bits) ((1U << (bits)) - 1) + +#define K_CONN_TYPE(chip, bus, w, h, ver) \ + ((k_u32) \ + ((((k_u32)(chip) & _CONN_MASK(_CONN_CHIP_BITS)) << _CONN_CHIP_SHIFT) | \ + (((k_u32)(bus) & _CONN_MASK(_CONN_BUS_BITS)) << _CONN_BUS_SHIFT) | \ + (((k_u32)(ver) & _CONN_MASK(_CONN_VER_BITS)) << _CONN_VER_SHIFT) | \ + (((k_u32)((w) >> 1) & _CONN_MASK(_CONN_W_BITS)) << _CONN_W_SHIFT) | \ + (((k_u32)((h) >> 1) & _CONN_MASK(_CONN_H_BITS)) << _CONN_H_SHIFT))) + +#define K_CONN_CHIP(type) ((k_connector_chip)(((type) >> _CONN_CHIP_SHIFT) & _CONN_MASK(_CONN_CHIP_BITS))) +#define K_CONN_BUS(type) ((k_connector_bus)(((type) >> _CONN_BUS_SHIFT) & _CONN_MASK(_CONN_BUS_BITS))) +#define K_CONN_VER(type) (((type) >> _CONN_VER_SHIFT) & _CONN_MASK(_CONN_VER_BITS)) +#define K_CONN_WIDTH(type) ((((type) >> _CONN_W_SHIFT) & _CONN_MASK(_CONN_W_BITS)) << 1) +#define K_CONN_HEIGHT(type) ((((type) >> _CONN_H_SHIFT) & _CONN_MASK(_CONN_H_BITS)) << 1) + +typedef k_u32 k_connector_type; + +/* ST7701 variants */ +#define ST7701_480_800_DSI_V1 K_CONN_TYPE(K_CHIP_ST7701, K_BUS_DSI, 480, 800, 1) +#define ST7701_480_854_DSI_V1 K_CONN_TYPE(K_CHIP_ST7701, K_BUS_DSI, 480, 854, 1) +#define ST7701_480_640_DSI_V1 K_CONN_TYPE(K_CHIP_ST7701, K_BUS_DSI, 480, 640, 1) +#define ST7701_368_544_DSI_V1 K_CONN_TYPE(K_CHIP_ST7701, K_BUS_DSI, 368, 544, 1) + +#define CONNECTOR_BUTT ((k_u32)0xFFFFFFFF) + +typedef enum { + K_CONNECTOR_BL_MODE_OFF = 0, + K_CONNECTOR_BL_MODE_ON = 1, + K_CONNECTOR_BL_MODE_PWM = 2, +} k_connector_backlight_mode; + +typedef struct { + k_connector_backlight_mode mode; + k_u32 duty; +} k_connector_backlight_attr; + +typedef struct { + char connector_name[32]; + k_connector_type type; + union { + k_vo_timing timing; + k_vo_timing resolution; + }; + k_u32 bg_color; +} k_connector_info; + +typedef struct { + k_u8 cmd_type; + k_u8 cmd_delay; + k_u8 cmd_size; + k_u8 cmd_data[0]; +} k_connector_cmd_slice; + +#define CONNECTOR_CMD_SEQUENCE(type, delay, ...) \ + (type), (delay), sizeof((k_u8[]) { __VA_ARGS__ }) / sizeof(k_u8), __VA_ARGS__ + +#ifdef __cplusplus +} +#endif + +#endif /* __K_CONNECTOR_COMM_H__ */ diff --git a/bsp/k230/drivers/display/include/k_type.h b/bsp/k230/drivers/display/include/k_type.h new file mode 100644 index 00000000000..8e7e7a4726d --- /dev/null +++ b/bsp/k230/drivers/display/include/k_type.h @@ -0,0 +1,36 @@ +#ifndef __K_TYPE_H__ +#define __K_TYPE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char k_u8; +typedef unsigned short k_u16; +typedef unsigned int k_u32; + +typedef signed char k_s8; +typedef short k_s16; +typedef int k_s32; + +typedef unsigned long k_u64; +typedef signed long k_s64; + +typedef char k_char; + +typedef enum +{ + K_FALSE = 0, + K_TRUE = 1, +} k_bool; + +typedef k_u32 k_handle; + +#define K_SUCCESS (0) +#define K_FAILED (-1) + +#ifdef __cplusplus +} +#endif + +#endif /* __K_TYPE_H__ */ diff --git a/bsp/k230/drivers/display/include/k_vo_comm.h b/bsp/k230/drivers/display/include/k_vo_comm.h new file mode 100644 index 00000000000..4852a37e119 --- /dev/null +++ b/bsp/k230/drivers/display/include/k_vo_comm.h @@ -0,0 +1,98 @@ +#ifndef __K_VO_COMM_H__ +#define __K_VO_COMM_H__ + +#include "k_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Display device / channel constants */ +#define K_VO_MAX_DEV_NUMS (1) +#define K_VO_MAX_CHN_NUMS (8) +#define K_VO_DISPLAY_DEV_ID (0) + +#define K_VO_DEFAULT_MIX_ORDER (0x0000000076543210) + +typedef struct { + k_u32 x; + k_u32 y; +} k_vo_position; + +typedef struct { + k_u32 width; + k_u32 height; +} k_vo_size; + +struct vo_disp_layer_mix_priority_t { + union { + struct { + k_u64 layer0_sel : 4; + k_u64 layer1_sel : 4; + k_u64 layer2_sel : 4; + k_u64 layer3_sel : 4; + k_u64 layer4_sel : 4; + k_u64 layer5_sel : 4; + k_u64 layer6_sel : 4; + k_u64 layer7_sel : 4; + k_u64 layer8_sel : 4; + k_u64 layer9_sel : 4; + k_u64 layer10_sel : 4; + k_u64 layer11_sel : 4; + k_u64 recv : 16; + } bits; + k_u64 reg; + }; +}; + +/* Display timing parameters */ +typedef struct { + k_u32 pclk_khz; + k_u32 hactive; + k_u32 hsync_len; + k_u32 hback_porch; + k_u32 hfront_porch; + k_u32 vactive; + k_u32 vsync_len; + k_u32 vback_porch; + k_u32 vfront_porch; +} k_vo_timing; + +/* DSI lane config */ +typedef enum { + K_DSI_1LAN = 0, + K_DSI_2LAN = 1, + K_DSI_4LAN = 3, +} k_vo_dsi_lane_num; + +typedef enum { + K_VO_LP_MODE = 0, + K_VO_HS_MODE, +} k_vo_dsi_cmd_mode; + +typedef enum { + K_BURST_MODE = 0, + K_NON_BURST_MODE_WITH_SYNC_EVENT = 1, + K_NON_BURST_MODE_WITH_PULSES = 2, +} k_vo_dsi_video_mode; + +typedef struct { + struct { + k_u32 datarate; + k_u32 m, n, voc, hs_freq; + } phy; + + const k_vo_timing* timing; + + k_vo_dsi_lane_num lanes; + k_vo_dsi_cmd_mode cmd_mode; + k_vo_dsi_video_mode video_mode; + k_u8 vc_id; + k_u8 lp_speed_mhz; +} k_vo_dsi_config; + +#ifdef __cplusplus +} +#endif + +#endif /* __K_VO_COMM_H__ */ diff --git a/bsp/k230/drivers/display/lib/vo_stubs.c b/bsp/k230/drivers/display/lib/vo_stubs.c new file mode 100644 index 00000000000..73c6d7370d1 --- /dev/null +++ b/bsp/k230/drivers/display/lib/vo_stubs.c @@ -0,0 +1,19 @@ +/* Small compatibility helpers used by the source VO/DSI implementation. */ + +#include +#include + +void cpu_ticks_delay_us(uint64_t us) +{ + rt_hw_us_delay(us); +} + +void K_LOG(int level, int module, const char* fmt, ...) +{ + char buf[256]; + va_list args; + va_start(args, fmt); + rt_vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + rt_kprintf("[vo:%d:%d] %s", module, level, buf); +} diff --git a/bsp/k230/drivers/display/panel_common.c b/bsp/k230/drivers/display/panel_common.c new file mode 100644 index 00000000000..5bc60436536 --- /dev/null +++ b/bsp/k230/drivers/display/panel_common.c @@ -0,0 +1,252 @@ +/* Adapted from atk_k230d connector_panel_common.c for RT-Thread BSP */ + +#include +#include + +#include "connector_bus_dsi.h" +#include "connector_panel.h" + +extern void kd_vo_reset(void); +extern void kd_vo_wrap_init(void); +extern void kd_vo_set_config_mix(void); +extern void kd_vo_set_frame_intr(k_bool status); +extern void kd_vo_set_timing(const k_vo_timing* timing); +extern void kd_vo_set_pixclk(k_u32 div); +extern void kd_vo_set_background(k_u32 rgb888); +extern void kd_vo_enable(void); + +static inline k_u32 panel_calc_pixclk_div(k_u32 pclk_khz) +{ + return (pclk_khz == 0) ? 0 : (VO_PIXEL_CLOCK_HZ / (pclk_khz * 1000)) - 1; +} + +static k_s32 panel_vo_init(const struct panel_desc* desc) +{ + kd_vo_wrap_init(); + kd_vo_set_config_mix(); + kd_vo_set_frame_intr(K_TRUE); + kd_vo_set_timing(&desc->timing); + kd_vo_set_background(desc->bg_color); + kd_vo_enable(); + return 0; +} + +k_u32 panel_correct_pclk(k_u32 pclk_hz) +{ + k_u32 ratio; + + if (pclk_hz == 0) + return 0; + + ratio = (VO_PIXEL_CLOCK_HZ + pclk_hz / 2) / pclk_hz; + if (ratio == 0) + ratio = 1; + + return VO_PIXEL_CLOCK_HZ / ratio; +} + +int panel_calculate_fps(const k_vo_timing* timing) +{ + k_u32 htotal, vtotal; + + if (!timing) + return 0; + + htotal = timing->hactive + timing->hsync_len + timing->hback_porch + timing->hfront_porch; + vtotal = timing->vactive + timing->vsync_len + timing->vback_porch + timing->vfront_porch; + + if (htotal == 0 || vtotal == 0) + return 0; + + return (timing->pclk_khz * 1000) / htotal / vtotal; +} + +int panel_generic_reset(const struct panel_desc* desc) +{ + k_s32 reset_pin; + k_u32 reset_delay_ms; + k_bool reset_active_low; + int inactive_level, active_level; + + if (!desc) + return -1; + + reset_pin = desc->gpio.reset_pin; + if (reset_pin < 0) + return 0; + + reset_delay_ms = desc->gpio.reset_delay_ms; + reset_active_low = desc->gpio.reset_active_low; + + if (reset_active_low) { + active_level = PIN_LOW; + inactive_level = PIN_HIGH; + } else { + active_level = PIN_HIGH; + inactive_level = PIN_LOW; + } + + rt_pin_mode(reset_pin, PIN_MODE_OUTPUT); + + rt_pin_write(reset_pin, inactive_level); + rt_thread_mdelay(3); + + rt_pin_write(reset_pin, active_level); + rt_thread_mdelay(7); + + rt_pin_write(reset_pin, inactive_level); + rt_thread_mdelay(reset_delay_ms); + + return 0; +} + +static int panel_generic_backlight_over_gpio(const struct panel_desc* desc, k_u32 mode, k_u32 duty) +{ + k_s32 backlight_pin; + k_u32 backlight_delay_ms; + k_bool backlight_active_low; + int target_level; + int on; + + if (!desc) + return -1; + + backlight_pin = desc->gpio.backlight_pin; + if (backlight_pin < 0) + return -1; + + if (mode == 0) + on = 0; + else if (mode == 1) + on = 1; + else + on = duty / 128; + + backlight_delay_ms = desc->gpio.backlight_delay_ms; + backlight_active_low = desc->gpio.backlight_active_low; + + if (backlight_active_low) + target_level = on ? PIN_LOW : PIN_HIGH; + else + target_level = on ? PIN_HIGH : PIN_LOW; + + rt_pin_mode(backlight_pin, PIN_MODE_OUTPUT); + rt_pin_write(backlight_pin, target_level); + + if (backlight_delay_ms > 0) + rt_thread_mdelay(backlight_delay_ms); + + return 0; +} + +int panel_generic_backlight(const struct panel_desc* desc, k_u32 mode, k_u32 duty) +{ + if (!desc) + return -1; + + return panel_generic_backlight_over_gpio(desc, mode, duty); +} + +k_s32 panel_generic_power_on(struct panel_desc* desc) +{ + k_s32 ret; + k_u32 pixclk_div; + int fps; + + if (!desc) + return -1; + + kd_vo_reset(); + + if (!desc->bus_ops) { + rt_kprintf("panel_generic_power_on: missing bus_ops\n"); + return -1; + } + + if (desc->ops && desc->ops->reset) { + ret = desc->ops->reset(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_on: ops->reset failed: %d\n", ret); + return ret; + } + } + + if (desc->bus_type == PANEL_BUS_DSI) { + desc->timing.pclk_khz = dsi_correct_pclk(desc->timing.pclk_khz * 1000, desc->bus.dsi.lanes) / 1000; + } else { + desc->timing.pclk_khz = panel_correct_pclk(desc->timing.pclk_khz * 1000) / 1000; + } + + fps = panel_calculate_fps(&desc->timing); + rt_kprintf("panel %s, pixelclock %u khz, resolution %dx%d@%d\n", + desc->name, desc->timing.pclk_khz, desc->timing.hactive, desc->timing.vactive, fps); + + pixclk_div = panel_calc_pixclk_div(desc->timing.pclk_khz); + if (pixclk_div != 0) + kd_vo_set_pixclk(pixclk_div); + + if (desc->bus_ops->init) { + ret = desc->bus_ops->init(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_on: bus_ops->init failed: %d\n", ret); + return ret; + } + } + + if (!desc->ops || !desc->ops->init) { + rt_kprintf("panel_generic_power_on: panel missing mandatory ops->init\n"); + return -1; + } + + ret = desc->ops->init(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_on: ops->init failed: %d\n", ret); + return ret; + } + + if (desc->bus_ops->enable) { + ret = desc->bus_ops->enable(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_on: bus_ops->enable failed: %d\n", ret); + return ret; + } + } + + ret = panel_vo_init(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_on: panel_vo_init failed: %d\n", ret); + return ret; + } + + return 0; +} + +k_s32 panel_generic_power_off(const struct panel_desc* desc) +{ + k_s32 first_err = 0; + k_s32 ret; + + if (!desc) + return -1; + + panel_generic_backlight(desc, 0, 0); + + if (desc->ops && desc->ops->power_off) { + ret = desc->ops->power_off(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_off: ops->power_off failed: %d\n", ret); + first_err = ret; + } + } + + if (desc->bus_ops && desc->bus_ops->disable) { + ret = desc->bus_ops->disable(desc); + if (ret != 0) { + rt_kprintf("panel_generic_power_off: bus_ops->disable failed: %d\n", ret); + if (!first_err) + first_err = ret; + } + } + + return first_err; +} diff --git a/bsp/k230/drivers/display/panels/SConscript b/bsp/k230/drivers/display/panels/SConscript new file mode 100644 index 00000000000..17399e96708 --- /dev/null +++ b/bsp/k230/drivers/display/panels/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('DisplayPanels', src, depend=['BSP_USING_DISPLAY'], CPPPATH=CPPPATH) + +Return('group') diff --git a/bsp/k230/drivers/display/panels/mipi_st7701.c b/bsp/k230/drivers/display/panels/mipi_st7701.c new file mode 100644 index 00000000000..8cbd6737b54 --- /dev/null +++ b/bsp/k230/drivers/display/panels/mipi_st7701.c @@ -0,0 +1,125 @@ +/* Adapted from atk_k230d mipi_st7701.c — K230D ATK variant only */ + +#include + +#include "connector_panel.h" +#include "connector_bus_dsi.h" + +#include "drv_display.h" + +static int st7701_480x640_atk_init(const struct panel_desc* desc) +{ + /* clang-format off */ + const k_u8 init_sequence[] = { + // cmd type, delay, data length, data0 ... dataN + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13, + 0x15, 0, 2, 0xEF, 0x08, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x10, + 0x39, 0, 3, 0xC0, 0x4F, 0x00, + 0x39, 0, 3, 0xC1, 0x10, 0x0C, + 0x39, 0, 3, 0xC2, 0x01, 0x14, + 0x15, 0, 2, 0xCC, 0x10, + 0x39, 0,17, 0xB0, 0x00, 0x0B, 0x13, 0x0D, 0x10, 0x07, 0x02, 0x08, 0x07, 0x1F, 0x04, 0x11, 0x0F, 0x28, 0x2F, 0x1F, + 0x39, 0,17, 0xB1, 0x00, 0x0C, 0x13, 0x0C, 0x10, 0x05, 0x02, 0x08, 0x08, 0x1E, 0x05, 0x13, 0x11, 0x27, 0x30, 0x1F, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x11, + 0x15, 0, 2, 0xB0, 0x4D, + 0x15, 0, 2, 0xB1, 0x4D, + 0x15, 0, 2, 0xB2, 0x87, + 0x15, 0, 2, 0xB3, 0x80, + 0x15, 0, 2, 0xB5, 0x45, + 0x15, 0, 2, 0xB7, 0x85, + 0x15, 0, 2, 0xB8, 0x20, + 0x15, 0, 2, 0xC0, 0x09, + 0x15, 0, 2, 0xC1, 0x78, + 0x15, 0, 2, 0xC2, 0x78, + 0x15,10, 2, 0xD0, 0x88, + 0x39, 0, 4, 0xE0, 0x00, 0x00, 0x02, + 0x39, 0,12, 0xE1, 0x04, 0xB0, 0x06, 0xB0, 0x05, 0xB0, 0x07, 0xB0, 0x00, 0x44, 0x44, + 0x39, 0,13, 0xE2, 0x20, 0x20, 0x44, 0x44, 0x96, 0xA0, 0x00, 0x00, 0x96, 0xA0, 0x00, 0x00, + 0x39, 0, 5, 0xE3, 0x00, 0x00, 0x22, 0x22, + 0x39, 0, 3, 0xE4, 0x44, 0x44, + 0x39, 0,17, 0xE5, 0x0C, 0x90, 0xB0, 0xA0, 0x0E, 0x92, 0xB0, 0xA0, 0x08, 0x8C, 0xB0, 0xA0, 0x0A, 0x8E, 0xB0, 0xA0, + 0x39, 0, 5, 0xE6, 0x00, 0x00, 0x22, 0x22, + 0x39, 0, 3, 0xE7, 0x44, 0x44, + 0x39, 0,17, 0xE8, 0x0D, 0x91, 0xB0, 0xA0, 0x0F, 0x93, 0xB0, 0xA0, 0x09, 0x8D, 0xB0, 0xA0, 0x0B, 0x8F, 0xB0, 0xA0, + 0x39, 0, 3, 0xE9, 0x36, 0x00, + 0x39, 0, 8, 0xEB, 0x00, 0x00, 0xE4, 0xE4, 0x44, 0x88, 0x40, + 0x39, 0,17, 0xED, 0xC1, 0xA2, 0xBF, 0x0F, 0x67, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x76, 0xF0, 0xFB, 0x2A, 0x1C, + 0x39, 0, 7, 0xEF, 0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13, + 0x39, 0, 3, 0xE8, 0x00, 0x0E, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00, + 0x05,20, 1, 0x11, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13, + 0x39,10, 3, 0xE8, 0x00, 0x0C, + 0x39, 0, 3, 0xE8, 0x00, 0x00, + 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00, + 0x05,20, 1, 0x29, + }; + /* clang-format on */ + + return dsi_send_cmd_sequence(desc, init_sequence, sizeof(init_sequence), 0); +} + +static int st7701_power_off(const struct panel_desc* desc) +{ + (void)desc; + return 0; +} + +static const struct panel_ops st7701_480x640_atk_ops = { + .reset = panel_generic_reset, + .init = st7701_480x640_atk_init, + .power_off = st7701_power_off, + .read_chip_id = dsi_read_chip_id, +}; + +static struct panel_desc st7701_480x640_atk_panel_desc = { + .name = "st7701_480x640_atk", + .connector_type = ST7701_480_640_DSI_V1, + .bus_type = PANEL_BUS_DSI, + + .timing = { + .pclk_khz = 24864, + .hactive = 480, + .hsync_len = 20, + .hback_porch = 20, + .hfront_porch = 40, + .vactive = 640, + .vsync_len = 20, + .vback_porch = 20, + .vfront_porch = 40, + }, + + .bg_color = PANEL_BG_COLOR_BLACK, + + .gpio = { + .reset_pin = K230D_LCD_RESET_PIN, + .backlight_pin = K230D_LCD_BACKLIGHT_PIN, + .reset_delay_ms = 10, + .backlight_delay_ms = 0, + .reset_active_low = K_TRUE, + .backlight_active_low = K_FALSE, + }, + + .bus.dsi = { + .lanes = K_DSI_2LAN, + .cmd_mode = K_VO_LP_MODE, + .video_mode = K_BURST_MODE, + .vc_id = 0, + }, + + .bus_ops = &dsi_bus_ops, + .ops = &st7701_480x640_atk_ops, +}; + +static const struct panel_desc* st7701_panel_variants[] = { + &st7701_480x640_atk_panel_desc, + NULL, +}; + +struct panel_drv mipi_st7701_drv = { + .connector_name = "st7701", + .panel_variants = st7701_panel_variants, + .active_panel = &st7701_480x640_atk_panel_desc, +}; diff --git a/bsp/k230/drivers/display/vo/kd_dsi_reg.c b/bsp/k230/drivers/display/vo/kd_dsi_reg.c new file mode 100644 index 00000000000..4dfef64e9dc --- /dev/null +++ b/bsp/k230/drivers/display/vo/kd_dsi_reg.c @@ -0,0 +1,669 @@ +#include "kd_dsi_reg.h" +#include "vo_display_remap.h" + +#include + +#include +#include + +#define KD_DSI_MODULE_ID 11 + +#define DSI_REG_PWR_UP 0x004 +#define DSI_REG_CLKMGR_CFG 0x008 +#define DSI_REG_DPI_VCID 0x00c +#define DSI_REG_DPI_COLOR_CODING 0x010 +#define DSI_REG_DPI_CFG_POL 0x014 +#define DSI_REG_VID_MODE_CFG 0x038 +#define DSI_REG_VID_PKT_SIZE 0x03c +#define DSI_REG_VID_NUM_CHUNKS 0x040 +#define DSI_REG_VID_NULL_SIZE 0x044 +#define DSI_REG_VID_HSA_TIME 0x048 +#define DSI_REG_VID_HBP_TIME 0x04c +#define DSI_REG_VID_HLINE_TIME 0x050 +#define DSI_REG_VID_VSA_LINES 0x054 +#define DSI_REG_VID_VBP_LINES 0x058 +#define DSI_REG_VID_VFP_LINES 0x05c +#define DSI_REG_VID_VACTIVE_LINES 0x060 +#define DSI_REG_CMD_MODE_CFG 0x068 +#define DSI_REG_GEN_HDR 0x06c +#define DSI_REG_GEN_PLD_DATA 0x070 +#define DSI_REG_CMD_PKT_STATUS 0x074 +#define DSI_REG_TO_CNT_CFG 0x078 +#define DSI_REG_BTA_TO_CNT 0x08c +#define DSI_REG_PHY_TMR_CFG 0x098 +#define DSI_REG_PHY_TMR_LPCLK_CFG 0x09c +#define DSI_REG_PHY_IF_CFG 0x0a4 +#define DSI_REG_PHY_RSTZ 0x0a0 +#define DSI_REG_PHY_STATUS 0x0b0 +#define DSI_REG_PHY_TST_CTRL0 0x0b4 +#define DSI_REG_PHY_TST_CTRL1 0x0b8 +#define DSI_REG_INT_ST0 0x0bc +#define DSI_REG_INT_ST1 0x0c0 +#define DSI_REG_INT_MSK0 0x0c4 +#define DSI_REG_INT_MSK1 0x0c8 +#define DSI_REG_MODE_CFG 0x094 + +#define DSI_PACKET_DCS_SHORT_WRITE0 0x05 +#define DSI_PACKET_DCS_SHORT_WRITE1 0x15 +#define DSI_PACKET_DCS_LONG_WRITE 0x39 +#define DSI_PACKET_DCS_READ 0x06 +#define DSI_PACKET_GEN_SHORT_WRITE0 0x03 +#define DSI_PACKET_GEN_SHORT_WRITE1 0x13 +#define DSI_PACKET_GEN_SHORT_WRITE2 0x23 +#define DSI_PACKET_GEN_LONG_WRITE 0x29 +#define DSI_PACKET_GEN_READ0 0x04 +#define DSI_PACKET_GEN_READ1 0x14 +#define DSI_PACKET_GEN_READ2 0x24 + +#define DSI_WAIT_US 10 +#define DSI_WAIT_RETRY 20000U + +#if defined(__riscv) +#define DSI_FENCE_WO() __asm__ volatile("fence w,o" ::: "memory") +#define DSI_FENCE_IR() __asm__ volatile("fence i,r" ::: "memory") +#else +#define DSI_FENCE_WO() __asm__ volatile("" ::: "memory") +#define DSI_FENCE_IR() __asm__ volatile("" ::: "memory") +#endif + +struct kd_dsi_resolution { + k_u32 pclk; + k_u32 phyclk; + k_u32 htotal; + k_u32 hdisplay; + k_u32 hsync_len; + k_u32 hback_porch; + k_u32 hfront_porch; + k_u32 vtotal; + k_u32 vdisplay; + k_u32 vsync_len; + k_u32 vback_porch; + k_u32 vfront_porch; +}; + +struct kd_dsi_config { + k_u32 pclk; + k_u32 phyclk; + k_u32 n; + k_u32 m; + k_u32 voc; + k_u32 lane_num; + k_u32 hs_freq; + k_u32 cmd_mode; + k_u32 work_mode; + k_u32 video_mode; + struct kd_dsi_resolution *resolution; + uint8_t color_coding; + uint8_t lp_div; +}; + +extern void K_LOG(int level, int module, const char *fmt, ...); +extern void *memcpy(void *dst, const void *src, unsigned long count); + +static k_u32 curren_video_mode; + +static k_u32 dsi_lane_count(k_vo_dsi_lane_num lanes) +{ + switch (lanes) { + case K_DSI_1LAN: + return 1; + case K_DSI_2LAN: + return 2; + case K_DSI_4LAN: + return 4; + default: + return 0; + } +} + +static inline void raw_writel(k_u32 value, volatile void *addr) +{ + *(volatile k_u32 *)addr = value; +} + +static inline k_u32 raw_readl(const volatile void *addr) +{ + return *(const volatile k_u32 *)addr; +} + +static uintptr_t dsi_base_addr(void) +{ + if (display_remap == NULL || display_remap->dsi_base == NULL) { + (void)vo_display_remap_init(); + } + if (display_remap == NULL || display_remap->dsi_base == NULL) { + return 0; + } + return (uintptr_t)display_remap->dsi_base; +} + +static uintptr_t phy_base_addr(void) +{ + if (display_remap == NULL || display_remap->phy_base == NULL) { + (void)vo_display_remap_init(); + } + if (display_remap == NULL || display_remap->phy_base == NULL) { + return 0; + } + return (uintptr_t)display_remap->phy_base; +} + +static void dsi_write(k_u32 value, k_u32 offset) +{ + uintptr_t base = dsi_base_addr(); + + K_LOG(7, KD_DSI_MODULE_ID, + "[Func]:%s [Line]:%d [Info]:DSI write: offset 0x%x, val 0x%x\n", + __func__, 160, offset, value); + + if (base == 0U) { + return; + } + + DSI_FENCE_WO(); + raw_writel(value, (void *)(base + offset)); +} + +static k_u32 dsi_read(k_u32 offset) +{ + uintptr_t base = dsi_base_addr(); + k_u32 value = 0; + + if (base != 0U) { + value = raw_readl((void *)(base + offset)); + DSI_FENCE_IR(); + } + + K_LOG(7, KD_DSI_MODULE_ID, + "[Func]:%s [Line]:%d [Info]:DSI read: offset 0x%x, val 0x%x\n", + __func__, 179, offset, value); + return value; +} + +static void phy_update_bits(k_u32 offset, k_u32 mask, k_u32 value) +{ + uintptr_t base = phy_base_addr(); + k_u32 reg; + + if (base == 0U) { + return; + } + + reg = raw_readl((void *)(base + offset)); + DSI_FENCE_IR(); + reg &= ~mask; + reg |= value & mask; + DSI_FENCE_WO(); + raw_writel(reg, (void *)(base + offset)); +} + +static int packet_format_is_long(uint8_t type) +{ + return type == DSI_PACKET_DCS_LONG_WRITE || + type == DSI_PACKET_GEN_LONG_WRITE; +} + +static uint8_t dcs_packet_type(uint32_t len) +{ + if (len == 1U) { + return DSI_PACKET_DCS_SHORT_WRITE0; + } + if (len == 2U) { + return DSI_PACKET_DCS_SHORT_WRITE1; + } + return DSI_PACKET_DCS_LONG_WRITE; +} + +static int wait_status_clear(k_u32 mask) +{ + unsigned int retry; + + for (retry = 0; retry < DSI_WAIT_RETRY; ++retry) { + if ((dsi_read(DSI_REG_CMD_PKT_STATUS) & mask) == 0U) { + return 0; + } + rt_hw_us_delay(DSI_WAIT_US); + } + + return -1; +} + +static int wait_status_set(k_u32 mask) +{ + unsigned int retry; + + for (retry = 0; retry < DSI_WAIT_RETRY; ++retry) { + if ((dsi_read(DSI_REG_CMD_PKT_STATUS) & mask) == mask) { + return 0; + } + rt_hw_us_delay(DSI_WAIT_US); + } + + return -1; +} + +static int write_payload(const uint8_t *payload, uint32_t len) +{ + uint32_t offset = 0; + + while (offset < len) { + uint32_t word = 0; + uint32_t chunk = len - offset; + uint32_t i; + + if (wait_status_clear(0x8U) != 0) { + return -1; + } + + if (chunk > 4U) { + chunk = 4U; + } + + for (i = 0; i < chunk; ++i) { + word |= (k_u32)payload[offset + i] << (i * 8U); + } + + dsi_write(word, DSI_REG_GEN_PLD_DATA); + offset += chunk; + } + + return 0; +} + +static int read_payload(uint8_t *data, uint32_t len) +{ + uint32_t offset = 0; + + while (offset < len) { + k_u32 word; + uint32_t chunk = len - offset; + + if (wait_status_clear(0x10U) != 0) { + return offset == 0U ? -1 : (int)offset; + } + + if (chunk > 4U) { + chunk = 4U; + } + + word = dsi_read(DSI_REG_GEN_PLD_DATA); + memcpy(data + offset, &word, chunk); + offset += chunk; + + if ((dsi_read(DSI_REG_CMD_PKT_STATUS) & 0x10U) != 0U) { + break; + } + } + + return (int)offset; +} + +static void dsi_message_config(uint8_t channel, uint8_t ack, uint8_t lp) +{ + k_u32 value = 0; + + if (ack != 0U) { + value |= 0x1U; + } + if (lp != 0U) { + value |= 0x70fU; + } + value |= ((k_u32)channel & 0x3U) << 8; + + dsi_write(value, DSI_REG_CMD_MODE_CFG); +} + +static void dsi_video_mode_config(k_u32 mode) +{ + k_u32 value = 0xbf00U; + + if (mode == 1U) { + value |= 0x1U; + } else if (mode != 2U) { + value |= 0x2U; + } + + dsi_write(value, DSI_REG_VID_MODE_CFG); +} + +static void dsi_set_mode(uint8_t enable, k_u32 video_mode) +{ + dsi_write(0, DSI_REG_PWR_UP); + if (enable == 0U) { + dsi_write(1, DSI_REG_MODE_CFG); + dsi_write(0x010f7f00U, DSI_REG_CMD_MODE_CFG); + dsi_write(0, DSI_REG_VID_MODE_CFG); + } else { + dsi_write(0, DSI_REG_MODE_CFG); + dsi_video_mode_config(video_mode); + } + dsi_write(1, DSI_REG_MODE_CFG); + dsi_write(1, DSI_REG_PWR_UP); +} + +static void wait_for_two_frames(const struct kd_dsi_resolution *res) +{ + k_u32 htotal; + k_u32 vtotal; + k_u32 frame_ms; + + if (res == NULL || res->pclk == 0U) { + rt_thread_mdelay(34); + return; + } + + htotal = res->hdisplay + res->hsync_len + res->hback_porch + res->hfront_porch; + vtotal = res->vdisplay + res->vsync_len + res->vback_porch + res->vfront_porch; + frame_ms = (k_u32)(((uint64_t)htotal * (uint64_t)vtotal) / (uint64_t)res->pclk); + rt_thread_mdelay((int)((frame_ms + 1U) * 2U)); +} + +void k230_dsi_write_phy_reg(uint8_t addr, uint8_t value) +{ + dsi_write(0x10000U | addr, DSI_REG_PHY_TST_CTRL1); + dsi_write(2, DSI_REG_PHY_TST_CTRL0); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); + dsi_write(value, DSI_REG_PHY_TST_CTRL1); + dsi_write(2, DSI_REG_PHY_TST_CTRL0); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); +} + +void k230_dsi_phy_pll_config(uint32_t n, uint32_t m, uint8_t hs_freq) +{ + phy_update_bits(0x10, 0x00000200U, 0x00000200U); + phy_update_bits(0x10, 0x00000200U, 0); + phy_update_bits(0x10, 0x00000003U, 0x00000001U); + phy_update_bits(0x08, 0x07fe0000U, (n & 0x3ffU) << 17); + phy_update_bits(0x08, 0x78000000U, (m & 0x0fU) << 27); + phy_update_bits(0x10, 0x0001f800U, ((k_u32)hs_freq & 0x3fU) << 11); + + k230_dsi_write_phy_reg(0x14, 0x02); + k230_dsi_write_phy_reg(0x15, 0x60); + k230_dsi_write_phy_reg(0x16, 0x03); + k230_dsi_write_phy_reg(0x1d, 0x01); + + phy_update_bits(0x10, 0x00000400U, 0x00000400U); + rt_thread_mdelay(1); + phy_update_bits(0x10, 0x00000400U, 0); +} + +void k230_dsi_phy0_config(uint32_t n, uint32_t m, uint8_t hs_freq, uint8_t lane_num) +{ + uintptr_t base = phy_base_addr(); + + if (base != 0U) { + DSI_FENCE_WO(); + raw_writel(0, (void *)(base + 0x04)); + } + + dsi_write(0x0c, DSI_REG_PHY_RSTZ); + dsi_write(1, DSI_REG_PHY_TST_CTRL0); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); + + k230_dsi_write_phy_reg(0x0c, 0x03); + k230_dsi_write_phy_reg(0x44, lane_num); + k230_dsi_write_phy_reg(0xa0, 0x40); + k230_dsi_write_phy_reg(0xa4, 0x11); + k230_dsi_write_phy_reg(0xa4, 0x85); + k230_dsi_write_phy_reg(0xa3, 0x01); + k230_dsi_write_phy_reg(0x1f, 0x01); + k230_dsi_write_phy_reg(0x4a, 0x40); + + phy_update_bits(0x00, 0x00003f3cU, 0x000028a0U); + k230_dsi_phy_pll_config(n, m, hs_freq); + + if (base != 0U) { + DSI_FENCE_WO(); + raw_writel(0x28a0U, (void *)base); + } + + dsi_write(0x0c, DSI_REG_PHY_RSTZ); +} + +void k230_dsi_phy1_config(uint8_t lane_num) +{ + uintptr_t base = phy_base_addr(); + + if (base != 0U) { + DSI_FENCE_WO(); + raw_writel(0x00400000U, (void *)(base + 0x04)); + } + + dsi_write(1, DSI_REG_PHY_TST_CTRL0); + rt_thread_mdelay(1); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); + k230_dsi_write_phy_reg(0x0c, 0); + k230_dsi_write_phy_reg(0x44, lane_num); +} + +int dwc_dsi_send_packet(k_u8 type, k_u8 channel, const void *payload, + uint32_t payload_len, uint8_t read) +{ + const uint8_t *bytes = (const uint8_t *)payload; + k_u32 header; + + if (payload_len != 0U && bytes == NULL) { + return -1; + } + + dsi_message_config(channel, 1, read); + if (wait_status_clear(0x2U) != 0) { + return -1; + } + + if (packet_format_is_long(type)) { + if (write_payload(bytes, payload_len) != 0) { + return -1; + } + header = ((k_u32)type | (((k_u32)channel & 0x3U) << 6)) | + (payload_len << 8); + } else { + k_u32 data0 = payload_len > 0U ? bytes[0] : 0U; + k_u32 data1 = payload_len > 1U ? bytes[1] : 0U; + + header = ((k_u32)type | (((k_u32)channel & 0x3U) << 6)) | + (data0 << 8) | (data1 << 16); + } + + dsi_write(header, DSI_REG_GEN_HDR); + + if (wait_status_set(0x5U) != 0) { + K_LOG(3, KD_DSI_MODULE_ID, "%s: packet 0x%x timeout, status 0x%x\n", + __func__, type, dsi_read(DSI_REG_CMD_PKT_STATUS)); + return -1; + } + + return 0; +} + +int dwc_dsi_dcs_write(const void *data, uint32_t len, uint8_t channel) +{ + return dwc_dsi_send_packet(dcs_packet_type(len), channel, data, len, 0); +} + +int dwc_dsi_dcs_read(uint8_t cmd, void *data, uint32_t len, uint8_t channel) +{ + int ret; + + if (len != 0U && data == NULL) { + return -1; + } + + ret = dwc_dsi_send_packet(DSI_PACKET_DCS_READ, channel, &cmd, 1, 1); + if (ret != 0) { + return ret; + } + if (wait_status_clear(0x20U) != 0) { + return -1; + } + + return read_payload((uint8_t *)data, len); +} + +int dwc_dsi_generic_write(const void *data, uint32_t len, uint8_t channel) +{ + uint8_t type; + + if (len == 0U) { + type = DSI_PACKET_GEN_SHORT_WRITE0; + } else if (len == 1U) { + type = DSI_PACKET_GEN_SHORT_WRITE1; + } else if (len == 2U) { + type = DSI_PACKET_GEN_SHORT_WRITE2; + } else { + type = DSI_PACKET_GEN_LONG_WRITE; + } + + return dwc_dsi_send_packet(type, channel, data, len, 0); +} + +int dwc_dsi_generic_read(const void *params, uint32_t params_len, void *data, + uint32_t len, uint8_t channel) +{ + uint8_t type; + int ret; + + if ((params_len != 0U && params == NULL) || (len != 0U && data == NULL)) { + return -1; + } + + if (params_len == 0U) { + type = DSI_PACKET_GEN_READ0; + } else if (params_len == 1U) { + type = DSI_PACKET_GEN_READ1; + } else { + type = DSI_PACKET_GEN_READ2; + } + + ret = dwc_dsi_send_packet(type, channel, params, params_len, 1); + if (ret != 0) { + return ret; + } + if (wait_status_clear(0x20U) != 0) { + return -1; + } + + return read_payload((uint8_t *)data, len); +} + +void dwc_dsi_dump_config(const k_vo_dsi_config *config) +{ + if (config == NULL) { + rt_kprintf("dwc dsi config is null\n"); + return; + } + + rt_kprintf("dwc dsi config:\n"); + rt_kprintf(" lane_num %u\n", config->lanes); + rt_kprintf(" cmd_mode %u\n", config->cmd_mode); + rt_kprintf(" video_mode %u\n", config->video_mode); + rt_kprintf(" pclk %u phyclk %u n %u m %u voc %u hs_freq %u\n", + config->timing->pclk_khz * 1000, config->phy.datarate / 2, + config->phy.n, config->phy.m, config->phy.voc, + config->phy.hs_freq); +} + +void dwc_dsi_init(k_vo_dsi_config *config) +{ + struct kd_dsi_resolution res; + k_u32 lane_num; + k_u32 byte_clk; + k_u32 tx_escape_clk_division; + k_u32 hline; + + if (config == NULL || config->timing == NULL) { + K_LOG(3, KD_DSI_MODULE_ID, "%s: invalid dsi config\n", __func__); + return; + } + + rt_memset(&res, 0, sizeof(res)); + res.pclk = config->timing->pclk_khz * 1000; + res.phyclk = config->phy.datarate / 2; + res.hdisplay = config->timing->hactive; + res.hsync_len = config->timing->hsync_len; + res.hback_porch = config->timing->hback_porch; + res.hfront_porch = config->timing->hfront_porch; + res.htotal = res.hdisplay + res.hsync_len + res.hback_porch + res.hfront_porch; + res.vdisplay = config->timing->vactive; + res.vsync_len = config->timing->vsync_len; + res.vback_porch = config->timing->vback_porch; + res.vfront_porch = config->timing->vfront_porch; + res.vtotal = res.vdisplay + res.vsync_len + res.vback_porch + res.vfront_porch; + + lane_num = dsi_lane_count(config->lanes); + if (lane_num == 0U) { + K_LOG(3, KD_DSI_MODULE_ID, "%s: invalid lane config %u\n", + __func__, config->lanes); + return; + } + byte_clk = res.phyclk / 8000000U; + if (byte_clk == 0U) { + byte_clk = 1U; + } + tx_escape_clk_division = byte_clk / (config->lp_speed_mhz == 0U ? 20U : config->lp_speed_mhz); + if (tx_escape_clk_division == 0U) { + tx_escape_clk_division = 1U; + } + if (tx_escape_clk_division > 255U) { + tx_escape_clk_division = 255U; + } + + curren_video_mode = config->video_mode; + + dsi_write(0, DSI_REG_PWR_UP); + dsi_write(((tx_escape_clk_division & 0xffU) << 8) | (byte_clk & 0xffU), + DSI_REG_CLKMGR_CFG); + dsi_write(config->vc_id & 0x3U, DSI_REG_DPI_VCID); + dsi_write(0x5U, DSI_REG_DPI_COLOR_CODING); + dsi_write(0, DSI_REG_DPI_CFG_POL); + dsi_video_mode_config(config->video_mode); + + dsi_write(res.hdisplay & 0x3fffU, DSI_REG_VID_PKT_SIZE); + dsi_write(0, DSI_REG_VID_NUM_CHUNKS); + dsi_write(0, DSI_REG_VID_NULL_SIZE); + + hline = res.hdisplay + res.hsync_len + res.hback_porch + res.hfront_porch; + dsi_write(res.hsync_len, DSI_REG_VID_HSA_TIME); + dsi_write(res.hback_porch, DSI_REG_VID_HBP_TIME); + dsi_write(hline, DSI_REG_VID_HLINE_TIME); + dsi_write(res.vsync_len, DSI_REG_VID_VSA_LINES); + dsi_write(res.vback_porch, DSI_REG_VID_VBP_LINES); + dsi_write(res.vfront_porch, DSI_REG_VID_VFP_LINES); + dsi_write(res.vdisplay, DSI_REG_VID_VACTIVE_LINES); + + dsi_write(0x1388U, DSI_REG_TO_CNT_CFG); + dsi_write(0x0d00U, DSI_REG_BTA_TO_CNT); + dsi_write(0x2710U, DSI_REG_PHY_TMR_CFG); + dsi_write(0x0073003aU, DSI_REG_PHY_TMR_LPCLK_CFG); + dsi_write(0x2800U | ((lane_num - 1U) & 0x3U), DSI_REG_PHY_IF_CFG); + dsi_write(0xffffffffU, DSI_REG_INT_MSK0); + dsi_write(0xffffffffU, DSI_REG_INT_MSK1); + + k230_dsi_phy0_config(config->phy.n, config->phy.m, + (uint8_t)config->phy.hs_freq, (uint8_t)lane_num); + + dsi_write(0x0f, DSI_REG_PHY_RSTZ); + if ((dsi_read(DSI_REG_PHY_STATUS) & 0x1U) == 0U) { + K_LOG(3, KD_DSI_MODULE_ID, "%s: phy lock timeout\n", __func__); + } + if ((dsi_read(DSI_REG_PHY_STATUS) & 0x4U) == 0U) { + K_LOG(3, KD_DSI_MODULE_ID, "%s: phy stop-state timeout\n", __func__); + } + + wait_for_two_frames(&res); + dsi_set_mode(0, 0); +} + +int dwc_dsi_enable(void) +{ + dsi_set_mode(1, curren_video_mode); + return 0; +} + +int dwc_dsi_disable(void) +{ + dsi_set_mode(0, 0); + dsi_write(0, DSI_REG_PWR_UP); + dsi_write(0, DSI_REG_PHY_RSTZ); + return 0; +} diff --git a/bsp/k230/drivers/display/vo/kd_dsi_reg.h b/bsp/k230/drivers/display/vo/kd_dsi_reg.h new file mode 100644 index 00000000000..e57e02b85e2 --- /dev/null +++ b/bsp/k230/drivers/display/vo/kd_dsi_reg.h @@ -0,0 +1,32 @@ +#ifndef VO_KD_DSI_REG_H +#define VO_KD_DSI_REG_H + +#include "k_vo_comm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void k230_dsi_write_phy_reg(k_u8 addr, k_u8 value); +void k230_dsi_phy_pll_config(k_u32 n, k_u32 m, k_u8 hs_freq); +void k230_dsi_phy0_config(k_u32 n, k_u32 m, k_u8 hs_freq, k_u8 lane_num); +void k230_dsi_phy1_config(k_u8 lane_num); + +int dwc_dsi_send_packet(k_u8 type, k_u8 channel, const void *payload, + k_u32 payload_len, k_u8 read); +int dwc_dsi_dcs_write(const void *data, k_u32 len, k_u8 channel); +int dwc_dsi_dcs_read(k_u8 cmd, void *data, k_u32 len, k_u8 channel); +int dwc_dsi_generic_write(const void *data, k_u32 len, k_u8 channel); +int dwc_dsi_generic_read(const void *params, k_u32 params_len, void *data, + k_u32 len, k_u8 channel); + +void dwc_dsi_init(k_vo_dsi_config *config); +int dwc_dsi_enable(void); +int dwc_dsi_disable(void); +void dwc_dsi_dump_config(const k_vo_dsi_config *config); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/k230/drivers/display/vo/kd_vo_reg.c b/bsp/k230/drivers/display/vo/kd_vo_reg.c new file mode 100644 index 00000000000..f74652d6139 --- /dev/null +++ b/bsp/k230/drivers/display/vo/kd_vo_reg.c @@ -0,0 +1,361 @@ +#include "kd_vo_reg.h" +#include "vo_display_remap.h" + +#include + +#include +#include + +#define KD_VO_MODULE_ID 11 + +#define VO_REG_RESET 0x004 +#define VO_REG_ENABLE 0x004 +#define VO_REG_WRAP_CTRL0 0x008 +#define VO_REG_WRAP_CTRL1 0x00c +#define VO_REG_WRAP_CTRL2 0x010 +#define VO_REG_MIX_ORDER0 0x034 +#define VO_REG_MIX_ORDER1 0x038 +#define VO_REG_MIX_ORDER2 0x03c +#define VO_REG_MIX_ORDER3 0x040 +#define VO_REG_MIX_ORDER4 0x044 +#define VO_REG_MIX_ORDER5 0x048 +#define VO_REG_MIX_ORDER6 0x04c +#define VO_REG_MIX_ORDER7 0x050 +#define VO_REG_HSYNC 0x100 +#define VO_REG_HSYNC1 0x104 +#define VO_REG_VSYNC1 0x108 +#define VO_REG_HSYNC2 0x10c +#define VO_REG_VSYNC2 0x110 +#define VO_REG_LAYER_CFG_EXTRA 0x118 +#define VO_REG_ACTIVE_H 0x0c0 +#define VO_REG_ACTIVE_V 0x0c4 +#define VO_REG_TOTAL_SIZE 0x11c +#define VO_REG_BG_COLOR 0x3d0 +#define VO_REG_MIX_ENABLE 0x3c0 +#define VO_REG_MIX_ALPHA0 0x3c4 +#define VO_REG_MIX_ALPHA1 0x3c8 +#define VO_REG_MIX_PRIORITY0 0x3cc +#define VO_REG_MIX_PRIORITY1 0x950 +#define VO_REG_LAYER_ENABLE 0x380 +#define VO_REG_INTR_FRAME 0x3e0 +#define VO_REG_INTR_VTTH 0x3e4 +#define VO_REG_INTR_CLEAR0 0x3d4 +#define VO_REG_INTR_CLEAR1 0x3d8 +#define VO_REG_INTR_MASK0 0x3e8 +#define VO_REG_USER_SYNC 0x780 + +#define VO_SYS_RESET_OFFSET 0x090 +#define VO_PIXCLK_REG_OFFSET 0x078 +#define VO_TIMESTAMP_CTRL_OFFSET 0x000 +#define VO_TIMESTAMP_TIME_HI 0x070 +#define VO_TIMESTAMP_TIME_LO 0x074 +#define VO_TIMESTAMP_PTP_HI 0x078 +#define VO_TIMESTAMP_PTP_LO 0x07c + +#if defined(__riscv) +#define VO_FENCE_WO() __asm__ volatile("fence w,o" ::: "memory") +#define VO_FENCE_IR() __asm__ volatile("fence i,r" ::: "memory") +#else +#define VO_FENCE_WO() __asm__ volatile("" ::: "memory") +#define VO_FENCE_IR() __asm__ volatile("" ::: "memory") +#endif + +extern void K_LOG(int level, int module, const char *fmt, ...); +extern void dwc_dsi_disable(void); + +static inline void __raw_writel(k_u32 value, volatile void *addr) +{ + *(volatile k_u32 *)addr = value; +} + +static inline k_u32 __raw_readl(const volatile void *addr) +{ + return *(const volatile k_u32 *)addr; +} + +static inline uintptr_t vo_base_addr(void) +{ + if (display_remap == RT_NULL || display_remap->vo_base == RT_NULL) + { + (void)vo_display_remap_init(); + } + return (uintptr_t)display_remap->vo_base; +} + +static inline uintptr_t clock_base_addr(void) +{ + if (display_remap == RT_NULL || display_remap->clock_base == RT_NULL) + { + (void)vo_display_remap_init(); + } + return (uintptr_t)display_remap->clock_base; +} + +static inline uintptr_t sysctl_base_addr(void) +{ + if (display_remap == RT_NULL || display_remap->sysctl_base == RT_NULL) + { + (void)vo_display_remap_init(); + } + return (uintptr_t)display_remap->sysctl_base; +} + +static inline uintptr_t timestamp_base_addr(void) +{ + if (display_remap == RT_NULL || display_remap->timestamp_base == RT_NULL) + { + (void)vo_display_remap_init(); + } + return (uintptr_t)display_remap->timestamp_base; +} + +static void vo_write(k_u32 value, k_u32 offset) +{ + K_LOG(7, KD_VO_MODULE_ID, + "[Func]:%s [Line]:%d [Info]:VO write: offset 0x%x, val 0x%x\n", + __func__, 61, offset, value); + VO_FENCE_WO(); + __raw_writel(value, (void *)(vo_base_addr() + offset)); +} + +void kd_vo_set_pixclk(k_u32 div) +{ + uintptr_t addr = clock_base_addr() + VO_PIXCLK_REG_OFFSET; + k_u32 val; + + val = __raw_readl((void *)addr); + VO_FENCE_IR(); + val &= ~0x7f8U; + val |= div << 3; + val |= 0x80000000U; + VO_FENCE_WO(); + __raw_writel(val, (void *)addr); +} + +void kd_vo_wrap_init(void) +{ + unsigned int i; + + vo_write(0x00000011U, VO_REG_WRAP_CTRL0); + vo_write(0x00000088U, VO_REG_WRAP_CTRL1); + vo_write(0x00000000U, VO_REG_WRAP_CTRL2); + + for (i = 0; i <= 7; ++i) { + vo_write(0x01010101U, (i + 5U) * 4U); + } + + vo_write(0x76543210U, VO_REG_MIX_ORDER0); + vo_write(0x76543210U, VO_REG_MIX_ORDER2); + vo_write(0x76543210U, VO_REG_MIX_ORDER4); + vo_write(0x76543210U, VO_REG_MIX_ORDER6); + vo_write(0xfedcba98U, VO_REG_MIX_ORDER1); + vo_write(0xfedcba98U, VO_REG_MIX_ORDER3); + vo_write(0xfedcba98U, VO_REG_MIX_ORDER5); + vo_write(0xfedcba98U, VO_REG_MIX_ORDER7); + + for (i = 0; i <= 9; ++i) { + vo_write(0x00000701U, (i + 32U) * 4U); + } + + vo_write(0x00000701U, 0x800U); + vo_write(0x00000701U, 0x804U); + vo_write(0x00000701U, 0x808U); + vo_write(0x00000701U, 0x80cU); + vo_write(0x00000701U, 0x810U); + vo_write(0x00000000U, VO_REG_LAYER_CFG_EXTRA); +} + +static void kd_vo_software_reset(void) +{ + vo_write(0x0000000fU, VO_REG_RESET); + vo_write(0x00000000U, VO_REG_WRAP_CTRL0); + vo_write(0x00000000U, VO_REG_ENABLE); +} + +void kd_vo_reset(void) +{ + uintptr_t reset_addr; + + (void)vo_display_remap_init(); + reset_addr = sysctl_base_addr() + VO_SYS_RESET_OFFSET; + + VO_FENCE_WO(); + __raw_writel(0, (void *)reset_addr); + rt_thread_mdelay(1); + + VO_FENCE_WO(); + __raw_writel(0xffffffffU, (void *)reset_addr); + rt_thread_mdelay(1); + + dwc_dsi_disable(); + kd_vo_software_reset(); + rt_thread_mdelay(3); +} + +void kd_vo_timestamp_enable(void) +{ + uintptr_t addr = timestamp_base_addr() + VO_TIMESTAMP_CTRL_OFFSET; + k_u32 val; + + val = __raw_readl((void *)addr); + VO_FENCE_IR(); + + if ((val & 0x1U) == 0) { + val &= ~0x18U; + val |= 0x8U; + val |= 0x1U; + VO_FENCE_WO(); + __raw_writel(val, (void *)addr); + } +} + +void k230_get_timestamp(k_u32 *ptp_time, k_u32 *time) +{ + uintptr_t base = timestamp_base_addr(); + k_u32 val; + + val = __raw_readl((void *)(base + VO_TIMESTAMP_TIME_HI)); + VO_FENCE_IR(); + time[1] = val; + + val = __raw_readl((void *)(base + VO_TIMESTAMP_TIME_LO)); + VO_FENCE_IR(); + time[0] = val; + + val = __raw_readl((void *)(base + VO_TIMESTAMP_PTP_HI)); + VO_FENCE_IR(); + ptp_time[1] = val; + + val = __raw_readl((void *)(base + VO_TIMESTAMP_PTP_LO)); + VO_FENCE_IR(); + ptp_time[0] = val; +} + +void kd_vo_enable(void) +{ + vo_write(0x00000011U, VO_REG_ENABLE); + kd_vo_timestamp_enable(); +} + +void kd_vo_set_config_mix(void) +{ + vo_write(0x0000007fU, VO_REG_MIX_ENABLE); + vo_write(0xffffffffU, VO_REG_MIX_ALPHA0); + vo_write(0xffffffffU, VO_REG_MIX_ALPHA1); + vo_write(0xffffffffU, 0x940U); + vo_write(0x00003210U, VO_REG_MIX_PRIORITY0); + vo_write(0xba987654U, VO_REG_MIX_PRIORITY1); + vo_write(0x00000001U, VO_REG_LAYER_ENABLE); + vo_write(0x00000000U, VO_REG_INTR_CLEAR1); + vo_write(0x00000001U, VO_REG_INTR_CLEAR0); + vo_write(0x11111111U, 0x340U); + vo_write(0x000000ffU, VO_REG_MIX_ENABLE); + vo_write(0x00000000U, VO_REG_INTR_FRAME); + vo_write(0x00000000U, VO_REG_INTR_VTTH); + vo_write(0x00000000U, VO_REG_INTR_MASK0); +} + +static void kd_vo_set_sync_pair(k_u32 low, k_u32 high, k_u32 offset) +{ + k_u32 val = (low & 0xffffU) | (high << 16); + + vo_write(val, offset); +} + +static void kd_vo_set_hsync(k_u32 low, k_u32 high) +{ + kd_vo_set_sync_pair(low, high, VO_REG_HSYNC); +} + +static void kd_vo_set_hsync1(k_u32 low, k_u32 high) +{ + kd_vo_set_sync_pair(low, high, VO_REG_HSYNC1); +} + +static void kd_vo_set_hsync2(k_u32 low, k_u32 high) +{ + kd_vo_set_sync_pair(low, high, VO_REG_HSYNC2); +} + +static void kd_vo_set_vsync1(k_u32 low, k_u32 high) +{ + kd_vo_set_sync_pair(low, high, VO_REG_VSYNC1); +} + +static void kd_vo_set_vsync2(k_u32 low, k_u32 high) +{ + kd_vo_set_sync_pair(low, high, VO_REG_VSYNC2); +} + +void kd_vo_set_background(k_u32 rgb888) +{ + k_u32 r = (rgb888 >> 16) & 0xffU; + k_u32 g = (rgb888 >> 8) & 0xffU; + k_u32 b = rgb888 & 0xffU; + k_u32 y; + k_u32 cb; + k_u32 cr; + k_u32 yuv; + + y = (66U * r + 129U * g + 25U * b + 128U) >> 8; + y += 16U; + cb = ((-38 * (int)r - 74 * (int)g + 112 * (int)b + 128) >> 8) + 128; + cr = ((112 * (int)r - 94 * (int)g - 18 * (int)b + 128) >> 8) + 128; + + yuv = ((cr & 0xffU) << 16) | ((cb & 0xffU) << 8) | (y & 0xffU); + vo_write(yuv, VO_REG_BG_COLOR); +} + +void kd_vo_set_timing(const k_vo_timing *timing) +{ + k_u32 hactive; + k_u32 hback_porch; + k_u32 htotal; + k_u32 vactive; + k_u32 vback_porch; + k_u32 vtotal; + k_u32 val; + + hback_porch = timing->hback_porch; + hactive = timing->hactive; + htotal = hactive + hback_porch + timing->hsync_len + timing->hfront_porch; + + vback_porch = timing->vback_porch; + vactive = timing->vactive; + vtotal = vactive + vback_porch + timing->vsync_len + timing->vfront_porch; + + kd_vo_set_hsync(2, 5); + kd_vo_set_hsync1(2, 5); + kd_vo_set_hsync2(2, 5); + kd_vo_set_vsync1(0, 0); + kd_vo_set_vsync2(0, 0); + + val = ((hactive + hback_porch - 1U) << 16) | hback_porch; + vo_write(val, VO_REG_ACTIVE_H); + + val = ((vactive + vback_porch - 1U) << 16) | vback_porch; + vo_write(val, VO_REG_ACTIVE_V); + + val = (vtotal << 16) | htotal; + vo_write(val, VO_REG_TOTAL_SIZE); + + val = ((vactive - 1U) << 16) | hactive; + val += 0x7fffU; + vo_write(val, VO_REG_USER_SYNC); + +} + +void kd_vo_set_vtth_intr(k_u32 status, k_u32 line) +{ + (void)status; + (void)line; + vo_write(0x00000000U, VO_REG_INTR_VTTH); +} + +void kd_vo_set_frame_intr(k_bool status) +{ + k_u32 val = ((k_u32)status) << 20; + + vo_write(val, VO_REG_INTR_FRAME); + kd_vo_set_vtth_intr(0, 0); +} diff --git a/bsp/k230/drivers/display/vo/kd_vo_reg.h b/bsp/k230/drivers/display/vo/kd_vo_reg.h new file mode 100644 index 00000000000..2112a1eee0f --- /dev/null +++ b/bsp/k230/drivers/display/vo/kd_vo_reg.h @@ -0,0 +1,26 @@ +#ifndef VO_KD_VO_REG_H +#define VO_KD_VO_REG_H + +#include "k_vo_comm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void kd_vo_reset(void); +void kd_vo_wrap_init(void); +void kd_vo_set_config_mix(void); +void kd_vo_set_frame_intr(k_bool status); +void kd_vo_set_vtth_intr(k_u32 status, k_u32 line); +void kd_vo_set_pixclk(k_u32 div); +void kd_vo_set_timing(const k_vo_timing *timing); +void kd_vo_set_background(k_u32 rgb888); +void kd_vo_enable(void); +void kd_vo_timestamp_enable(void); +void k230_get_timestamp(k_u32 *ptp_time, k_u32 *time); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/k230/drivers/display/vo/vo_display_remap.h b/bsp/k230/drivers/display/vo/vo_display_remap.h new file mode 100644 index 00000000000..a3e06495e58 --- /dev/null +++ b/bsp/k230/drivers/display/vo/vo_display_remap.h @@ -0,0 +1,26 @@ +#ifndef VO_DISPLAY_REMAP_H +#define VO_DISPLAY_REMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct vo_display_remap { + void *vo_base; + void *dsi_base; + void *sysctl_base; + void *phy_base; + void *clock_base; + void *timestamp_base; +}; + +extern struct vo_display_remap *display_remap; + +int vo_display_remap_init(void); +void vo_display_remap_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/k230/drivers/display/vo/vo_remap.c b/bsp/k230/drivers/display/vo/vo_remap.c new file mode 100644 index 00000000000..3ac196ae4c1 --- /dev/null +++ b/bsp/k230/drivers/display/vo/vo_remap.c @@ -0,0 +1,85 @@ +#include "vo_display_remap.h" + +#include + +#include + +#define VO_REG_BASE_PHYS 0x09084000UL +#define VO_REG_SIZE 0x00010000UL +#define DSI_REG_BASE_PHYS 0x09085000UL +#define DSI_REG_SIZE 0x00001000UL +#define SYSCTL_REG_BASE_PHYS 0x91101000UL +#define DSI_PHY_REG_BASE_PHYS 0x09085400UL +#define CLOCK_REG_BASE_PHYS 0x91100000UL +#define TIMESTAMP_REG_BASE_PHYS 0x91108000UL +#define AUX_REG_SIZE 0x00001000UL + +struct vo_display_remap *display_remap; + +static struct vo_display_remap g_display_remap; +static int g_remap_ready; + +extern void *rt_ioremap(unsigned long phys_addr, unsigned long size); +extern void *rt_ioremap_nocache(unsigned long phys_addr, unsigned long size); +extern void rt_iounmap(void *addr); + +static void unmap_if_present(void **addr) +{ + if (addr != RT_NULL && *addr != RT_NULL) + { + rt_iounmap(*addr); + *addr = RT_NULL; + } +} + +void vo_display_remap_deinit(void) +{ + if (!g_remap_ready) + { + return; + } + + unmap_if_present(&g_display_remap.timestamp_base); + unmap_if_present(&g_display_remap.clock_base); + unmap_if_present(&g_display_remap.phy_base); + unmap_if_present(&g_display_remap.sysctl_base); + unmap_if_present(&g_display_remap.dsi_base); + unmap_if_present(&g_display_remap.vo_base); + + memset(&g_display_remap, 0, sizeof(g_display_remap)); + display_remap = RT_NULL; + g_remap_ready = 0; +} + +int vo_display_remap_init(void) +{ + if (g_remap_ready) + { + return 0; + } + + memset(&g_display_remap, 0, sizeof(g_display_remap)); + + g_display_remap.vo_base = rt_ioremap_nocache(VO_REG_BASE_PHYS, VO_REG_SIZE); + g_display_remap.dsi_base = rt_ioremap_nocache(DSI_REG_BASE_PHYS, DSI_REG_SIZE); + g_display_remap.sysctl_base = rt_ioremap(SYSCTL_REG_BASE_PHYS, AUX_REG_SIZE); + g_display_remap.phy_base = rt_ioremap(DSI_PHY_REG_BASE_PHYS, AUX_REG_SIZE); + g_display_remap.clock_base = rt_ioremap(CLOCK_REG_BASE_PHYS, AUX_REG_SIZE); + g_display_remap.timestamp_base = rt_ioremap(TIMESTAMP_REG_BASE_PHYS, AUX_REG_SIZE); + + if (g_display_remap.vo_base == RT_NULL || + g_display_remap.dsi_base == RT_NULL || + g_display_remap.sysctl_base == RT_NULL || + g_display_remap.phy_base == RT_NULL || + g_display_remap.clock_base == RT_NULL || + g_display_remap.timestamp_base == RT_NULL) + { + rt_kprintf("vo_remap: failed to map display registers\n"); + vo_display_remap_deinit(); + return -1; + } + + display_remap = &g_display_remap; + g_remap_ready = 1; + return 0; +} From 701175e0634e4a10a021b03f8d13673e5dcfd644 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Sun, 10 May 2026 18:33:07 +0800 Subject: [PATCH 8/9] bsp: k230: register gpio as pin device --- bsp/k230/board/Kconfig | 6 ++ bsp/k230/drivers/interdrv/gpio/drv_gpio.c | 77 +++++++++++++++++++++-- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/bsp/k230/board/Kconfig b/bsp/k230/board/Kconfig index 35fbd31a782..22f64302633 100644 --- a/bsp/k230/board/Kconfig +++ b/bsp/k230/board/Kconfig @@ -4,11 +4,17 @@ menu "Drivers Configuration" bool "Enable KPU and AI2D" default n + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default n + menuconfig BSP_USING_DISPLAY bool "Enable MIPI DSI Display (ST7701)" select RT_USING_DEVICE select RT_USING_DEVICE_OPS select RT_USING_PIN + select BSP_USING_GPIO default n help Enable MIPI DSI display support for the atk_k230d board. diff --git a/bsp/k230/drivers/interdrv/gpio/drv_gpio.c b/bsp/k230/drivers/interdrv/gpio/drv_gpio.c index 2185418aea0..9d0f0aeee77 100644 --- a/bsp/k230/drivers/interdrv/gpio/drv_gpio.c +++ b/bsp/k230/drivers/interdrv/gpio/drv_gpio.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include "ioremap.h" @@ -52,7 +53,6 @@ #define DBG_COLOR struct kd_gpio_device { - struct rt_device dev; void* base[2]; int hardlock; }; @@ -92,7 +92,7 @@ static rt_uint32_t kd_gpio_reg_readl(void* reg, rt_size_t offset) static int check_pin_valid(rt_base_t pin) { - if ((rt_uint16_t)pin < 0 || (rt_uint16_t)pin > GPIO_MAX_NUM) + if (pin < 0 || pin >= GPIO_MAX_NUM) { LOG_E("pin %d is not valid\n", pin); return -RT_EINVAL; @@ -379,6 +379,75 @@ rt_err_t kd_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) return RT_EOK; } +static void k230_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode) +{ + (void)device; + + switch (mode) + { + case PIN_MODE_OUTPUT: + case PIN_MODE_OUTPUT_OD: + (void)kd_pin_mode(pin, GPIO_DM_OUTPUT); + break; + case PIN_MODE_INPUT: + case PIN_MODE_INPUT_PULLUP: + case PIN_MODE_INPUT_PULLDOWN: + (void)kd_pin_mode(pin, GPIO_DM_INPUT); + break; + default: + LOG_E("pin mode %u is not supported", mode); + break; + } +} + +static void k230_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value) +{ + (void)device; + + (void)kd_pin_write(pin, value ? GPIO_PV_HIGH : GPIO_PV_LOW); +} + +static rt_ssize_t k230_pin_read(struct rt_device *device, rt_base_t pin) +{ + (void)device; + + return kd_pin_read(pin); +} + +static rt_err_t k230_pin_attach_irq(struct rt_device *device, rt_base_t pin, + rt_uint8_t mode, void (*hdr)(void *args), + void *args) +{ + (void)device; + + return kd_pin_attach_irq(pin, mode, hdr, args); +} + +static rt_err_t k230_pin_detach_irq(struct rt_device *device, rt_base_t pin) +{ + (void)device; + + return kd_pin_detach_irq(pin); +} + +static rt_err_t k230_pin_irq_enable(struct rt_device *device, rt_base_t pin, + rt_uint8_t enabled) +{ + (void)device; + + return kd_pin_irq_enable(pin, enabled); +} + +static const struct rt_pin_ops k230_pin_ops = +{ + .pin_mode = k230_pin_mode, + .pin_write = k230_pin_write, + .pin_read = k230_pin_read, + .pin_attach_irq = k230_pin_attach_irq, + .pin_detach_irq = k230_pin_detach_irq, + .pin_irq_enable = k230_pin_irq_enable, +}; + int rt_hw_gpio_init(void) { rt_err_t ret; @@ -393,8 +462,8 @@ int rt_hw_gpio_init(void) } gpio_dev.hardlock = HARDLOCK_GPIO; - ret = rt_device_register(&gpio_dev.dev, "gpio", RT_DEVICE_FLAG_RDWR); + ret = rt_device_pin_register("gpio", &k230_pin_ops, RT_NULL); return ret; } -INIT_BOARD_EXPORT(rt_hw_gpio_init); \ No newline at end of file +INIT_BOARD_EXPORT(rt_hw_gpio_init); From de91de53ef1be8a67f825f467902ff09a59d3fe7 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Thu, 28 May 2026 15:41:08 +0800 Subject: [PATCH 9/9] bsp: k230: enable K230D display driver with VO/DSI hardware init - bsp/k230: switch to SOC_K230D with soft-fpu, enable Xuantie C908 - bsp/k230: implement full VO+DSI display driver with power domain management, OSD framebuffer binding, and hardware layer commit - bsp/k230: add lwext4 support, switch rootfs from elmfat to ext4 - bsp/k230: fix DSI lane clock calculation with DSI_DPI_BITS_PER_PIXEL - bsp/qemu-virt64-riscv: slim down config by removing unused packages - bsp/qemu-virt64-riscv: save FDT address in boot_fdt_addr for later use - components: fix mutex init name in elmfat/tmpfs to use static strings - components: fix sdio block_size assignment after probe - components: derive ELF segment memory protection from p_flags (W^X) - libcpu/risc-v: clear user space page table entries for SMART - libcpu/risc-v: remove obsolete early identity mapping guard Co-Authored-By: Claude Opus 4.7 --- bsp/k230/.config | 94 +- .../applications/display_demo/display_demo.c | 12 +- bsp/k230/applications/mnt.c | 2 +- bsp/k230/board/board.h | 9 + bsp/k230/drivers/display/SConscript | 8 +- bsp/k230/drivers/display/bus_dsi.c | 15 +- bsp/k230/drivers/display/connector_bus_dsi.h | 2 +- bsp/k230/drivers/display/drv_display.c | 1082 +++++++++++++++- bsp/k230/drivers/display/drv_display.h | 2 +- bsp/k230/drivers/display/lib/vo_stubs.c | 8 + bsp/k230/drivers/display/panels/mipi_st7701.c | 5 +- bsp/k230/drivers/display/vo/kd_dsi_reg.c | 500 +++++++- bsp/k230/drivers/display/vo/kd_dsi_reg.h | 13 +- bsp/k230/drivers/display/vo/kd_vo_reg.c | 240 ++++ bsp/k230/drivers/display/vo/kd_vo_reg.h | 17 + bsp/k230/drivers/display/vo/vo_remap.c | 30 +- bsp/k230/rtconfig.h | 41 +- bsp/k230/rtconfig.py | 2 +- bsp/qemu-virt64-riscv/.config | 1138 ++--------------- bsp/qemu-virt64-riscv/driver/board.c | 106 +- bsp/qemu-virt64-riscv/link_cpus.lds | 2 +- bsp/qemu-virt64-riscv/rtconfig.h | 266 +--- .../dfs/dfs_v2/filesystems/elmfat/dfs_elm.c | 4 +- .../dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c | 2 +- components/drivers/sdio/dev_block.c | 2 +- components/lwp/lwp_elf.c | 14 +- components/mm/mm_fault.c | 7 + libcpu/risc-v/common64/mmu.c | 22 +- libcpu/risc-v/common64/startup_gcc.S | 8 +- 29 files changed, 2237 insertions(+), 1416 deletions(-) diff --git a/bsp/k230/.config b/bsp/k230/.config index 47d11534483..d6ef859ac50 100644 --- a/bsp/k230/.config +++ b/bsp/k230/.config @@ -116,7 +116,7 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 # end of rt_strnlen options # end of klibc options -CONFIG_RT_NAME_MAX=16 +CONFIG_RT_NAME_MAX=32 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_NANO is not set CONFIG_RT_USING_SMART=y @@ -141,6 +141,7 @@ CONFIG_RT_TIMER_THREAD_PRIO=4 CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192 # CONFIG_RT_USING_TIMER_ALL_SOFT is not set CONFIG_RT_USING_CPU_USAGE_TRACER=y +CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200 # # kservice options @@ -191,7 +192,8 @@ CONFIG_RT_USING_DEVICE_OPS=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x50201 +CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y +CONFIG_RT_VER_NUM=0x50300 CONFIG_RT_USING_STDC_ATOMIC=y CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 # end of RT-Thread Kernel @@ -202,12 +204,10 @@ CONFIG_ARCH_MM_MMU=y CONFIG_KERNEL_VADDR_START=0xffffffc000000000 CONFIG_ARCH_RISCV=y CONFIG_ARCH_RISCV_FPU=y -CONFIG_ARCH_RISCV_VECTOR=y -CONFIG_ARCH_VECTOR_VLEN_128=y -# CONFIG_ARCH_VECTOR_VLEN_256 is not set -CONFIG_ARCH_RISCV_FPU_D=y CONFIG_ARCH_RISCV64=y +CONFIG_ARCH_RISCV_XUANTIE=y CONFIG_ARCH_USING_NEW_CTX_SWITCH=y +CONFIG_CONFIG_XUANTIE_SVPBMT=1 CONFIG_ARCH_REMAP_KERNEL=y # @@ -275,7 +275,7 @@ CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set CONFIG_RT_USING_DFS_PTYFS=y # CONFIG_RT_USING_DFS_PROCFS is not set -CONFIG_RT_USING_DFS_CROMFS=y +# CONFIG_RT_USING_DFS_CROMFS is not set CONFIG_RT_USING_DFS_TMPFS=y # CONFIG_RT_USING_DFS_MQUEUE is not set CONFIG_RT_USING_PAGECACHE=y @@ -311,9 +311,8 @@ CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 CONFIG_RT_USING_SERIAL_BYPASS=y # CONFIG_RT_USING_CAN is not set -CONFIG_RT_USING_CPUTIME=y -CONFIG_RT_USING_CPUTIME_RISCV=y -CONFIG_CPUTIME_TIMER_FREQ=25000000 +CONFIG_RT_USING_CLOCK_TIME=y +CONFIG_CLOCK_TIMER_FREQ=250000 # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set # CONFIG_RT_USING_PHY_V2 is not set @@ -330,7 +329,7 @@ CONFIG_RT_USING_RANDOM=y # CONFIG_RT_USING_PM is not set CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set -# CONFIG_RT_USING_SOFT_RTC is not set +CONFIG_RT_USING_SOFT_RTC=y CONFIG_RT_USING_SDIO=y CONFIG_RT_SDIO_STACK_SIZE=8192 CONFIG_RT_SDIO_THREAD_PRIORITY=15 @@ -356,10 +355,10 @@ CONFIG_RT_BLK_PARTITION_DFS=y CONFIG_RT_BLK_PARTITION_EFI=y # end of Partition Types +# CONFIG_RT_USING_REGULATOR is not set +# CONFIG_RT_USING_POWER_SUPPLY is not set # CONFIG_RT_USING_VIRTIO is not set CONFIG_RT_USING_PIN=y -CONFIG_RT_USING_KTIME=y -# CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CHERRYUSB is not set # end of Device Drivers @@ -408,7 +407,8 @@ CONFIG_RT_USING_POSIX_TIMER=y # # Interprocess Communication (IPC) # -# CONFIG_RT_USING_POSIX_PIPE is not set +CONFIG_RT_USING_POSIX_PIPE=y +CONFIG_RT_USING_POSIX_PIPE_SIZE=2048 # CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set # CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set @@ -537,6 +537,7 @@ CONFIG_RT_USING_ADT_REF=y # # Memory management # +# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000 CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_RT_USING_MEMBLOCK is not set @@ -574,6 +575,7 @@ CONFIG_RT_USING_VDSO=y # end of Using USB legacy version # CONFIG_RT_USING_FDT is not set +# CONFIG_RT_USING_RUST is not set # end of RT-Thread Components # @@ -775,6 +777,7 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_U8G2 is not set # end of u8g2: a monochrome graphic library +# CONFIG_PKG_USING_NES_SIMULATOR is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -799,6 +802,9 @@ CONFIG_RT_USING_VDSO=y # # tools packages # +# CONFIG_PKG_USING_VECTOR is not set +# CONFIG_PKG_USING_SORCH is not set +# CONFIG_PKG_USING_DICT is not set # CONFIG_PKG_USING_CMBACKTRACE is not set # CONFIG_PKG_USING_MCOREDUMP is not set # CONFIG_PKG_USING_EASYFLASH is not set @@ -847,6 +853,9 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_RVBACKTRACE is not set # CONFIG_PKG_USING_HPATCHLITE is not set # CONFIG_PKG_USING_THREAD_METRIC is not set +# CONFIG_PKG_USING_UORB is not set +# CONFIG_PKG_USING_RT_TUNNEL is not set +# CONFIG_PKG_USING_VIRTUAL_TERMINAL is not set # end of tools packages # @@ -907,7 +916,13 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_DFS_JFFS2 is not set # CONFIG_PKG_USING_DFS_UFFS is not set -# CONFIG_PKG_USING_LWEXT4 is not set +CONFIG_PKG_USING_LWEXT4=y +CONFIG_PKG_LWEXT4_PATH="/packages/system/lwext4" +CONFIG_RT_USING_DFS_LWEXT4=y +# CONFIG_PKG_USING_LWEXT4_V200 is not set +CONFIG_PKG_USING_LWEXT4_LATEST_VERSION=y +# CONFIG_PKG_USING_LWEXT4_V110 is not set +CONFIG_PKG_LWEXT4_VER="latest" # CONFIG_PKG_USING_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set # CONFIG_PKG_USING_EV is not set @@ -941,6 +956,9 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_R_RHEALSTONE is not set # CONFIG_PKG_USING_HEARTBEAT is not set # CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set +# CONFIG_PKG_USING_CHERRYECAT is not set +# CONFIG_PKG_USING_EVENT_LOOP is not set +# CONFIG_PKG_USING_THREAD_MANAGER is not set # end of system packages # @@ -1097,7 +1115,24 @@ CONFIG_RT_USING_VDSO=y # # CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set # CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set +# CONFIG_PKG_USING_GD32_RISCV_SERIES_DRIVER is not set +# CONFIG_PKG_USING_GD32VW55X_WIFI is not set # end of GD32 Drivers + +# +# HPMicro SDK +# +# CONFIG_PKG_USING_HPM_SDK is not set +# end of HPMicro SDK + +# +# FT32 HAL & SDK Drivers +# +# CONFIG_PKG_USING_FT32F0_STD_DRIVER is not set +# CONFIG_PKG_USING_FT32F0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_FT32F4_STD_DRIVER is not set +# CONFIG_PKG_USING_FT32F4_CMSIS_DRIVER is not set +# end of FT32 HAL & SDK Drivers # end of HAL & SDK Drivers # @@ -1143,9 +1178,11 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_RT3020 is not set # CONFIG_PKG_USING_MLX90632 is not set # CONFIG_PKG_USING_MLX90382 is not set +# CONFIG_PKG_USING_MLX90384 is not set # CONFIG_PKG_USING_MLX90393 is not set # CONFIG_PKG_USING_MLX90392 is not set # CONFIG_PKG_USING_MLX90394 is not set +# CONFIG_PKG_USING_MLX90396 is not set # CONFIG_PKG_USING_MLX90397 is not set # CONFIG_PKG_USING_MS5611 is not set # CONFIG_PKG_USING_MAX31865 is not set @@ -1174,6 +1211,7 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_P3T1755 is not set # CONFIG_PKG_USING_QMI8658 is not set # CONFIG_PKG_USING_ICM20948 is not set +# CONFIG_PKG_USING_SCD4X is not set # end of sensors drivers # @@ -1191,6 +1229,7 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_CST812T is not set # end of touch drivers +# CONFIG_PKG_USING_LCD_SPI_DRIVER is not set # CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set @@ -1270,6 +1309,13 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_IC74HC165 is not set # CONFIG_PKG_USING_IST8310 is not set # CONFIG_PKG_USING_ST7789_SPI is not set +# CONFIG_PKG_USING_CAN_UDS is not set +# CONFIG_PKG_USING_ISOTP_C is not set +# CONFIG_PKG_USING_IKUNLED is not set +# CONFIG_PKG_USING_INS5T8025 is not set +# CONFIG_PKG_USING_IRUART is not set +# CONFIG_PKG_USING_ST7305 is not set +# CONFIG_PKG_USING_TM1668 is not set # CONFIG_PKG_USING_SPI_TOOLS is not set # end of peripheral libraries and drivers @@ -1344,13 +1390,7 @@ CONFIG_RT_USING_VDSO=y # CONFIG_PKG_USING_MULTIBUTTON is not set # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set -CONFIG_PKG_USING_ZLIB=y -CONFIG_PKG_ZLIB_PATH="/packages/misc/zlib" -# CONFIG_ZLIB_USING_SAMPLE is not set -# CONFIG_PKG_USING_ZLIB_V100 is not set -# CONFIG_PKG_USING_ZLIB_V123 is not set -CONFIG_PKG_USING_ZLIB_LATEST_VERSION=y -CONFIG_PKG_ZLIB_VER="latest" +# CONFIG_PKG_USING_ZLIB is not set # CONFIG_PKG_USING_MINIZIP is not set # CONFIG_PKG_USING_HEATSHRINK is not set # CONFIG_PKG_USING_DSTR is not set @@ -1618,6 +1658,8 @@ CONFIG_PKG_ZLIB_VER="latest" # Drivers Configuration # # CONFIG_BSP_USING_GNNE is not set +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_DISPLAY=y # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_RTC is not set @@ -1637,16 +1679,18 @@ CONFIG_BSP_USING_SDIO0=y # CONFIG_BSP_SDIO0_EMMC is not set # CONFIG_BSP_SDIO0_1V8 is not set # CONFIG_BSP_USING_SDIO1 is not set -CONFIG_BSP_SD_MNT_DEVNAME="sd0p1" +CONFIG_BSP_SD_MNT_DEVNAME="sd0p0" # CONFIG_BSP_USING_TIMERS is not set # CONFIG_BSP_USING_WDT is not set # CONFIG_BSP_USING_PDMA is not set # CONFIG_BSP_UTEST_DRIVERS is not set # end of Drivers Configuration +# CONFIG_SOC_K230 is not set +CONFIG_SOC_K230D=y CONFIG_BOARD_C908=y CONFIG___STACKSIZE__=65536 CONFIG_BSP_ROOTFS_TYPE_ELMFAT=y # CONFIG_BSP_ROOTFS_TYPE_CROMFS is not set -# CONFIG_BSP_RISCV_FPU_SOFT is not set -CONFIG_BSP_RISCV_FPU_D=y +CONFIG_BSP_RISCV_FPU_SOFT=y +# CONFIG_BSP_RISCV_FPU_D is not set diff --git a/bsp/k230/applications/display_demo/display_demo.c b/bsp/k230/applications/display_demo/display_demo.c index 7ca46aa6020..9a81a7c90ca 100644 --- a/bsp/k230/applications/display_demo/display_demo.c +++ b/bsp/k230/applications/display_demo/display_demo.c @@ -13,7 +13,7 @@ static void display_demo(int argc, char** argv) { rt_device_t fb; struct rt_device_graphic_info info; - rt_uint16_t *line; + rt_uint16_t *fbmem; rt_uint16_t colors[] = { rgb565(255, 0, 0), rgb565(0, 255, 0), @@ -45,14 +45,16 @@ static void display_demo(int argc, char** argv) return; } - line = rt_malloc(info.pitch); - if (!line) { - rt_kprintf("display_demo: no memory\n"); + fbmem = (rt_uint16_t *)info.framebuffer; + if (!fbmem || info.pitch < info.width * sizeof(rt_uint16_t)) { + rt_kprintf("display_demo: invalid framebuffer\n"); rt_device_close(fb); return; } for (rt_uint16_t y = 0; y < info.height; y++) { + rt_uint16_t *line = (rt_uint16_t *)((rt_uint8_t *)fbmem + y * info.pitch); + for (rt_uint16_t x = 0; x < info.width; x++) { rt_uint16_t band = (x * color_count) / info.width; rt_uint16_t shade = (y * 31) / info.height; @@ -61,11 +63,9 @@ static void display_demo(int argc, char** argv) if (band == color_count - 1) line[x] = (shade << 11) | (shade << 6) | shade; } - rt_device_write(fb, y * info.pitch, line, info.pitch); } rt_device_control(fb, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL); - rt_free(line); rt_device_close(fb); rt_kprintf("display_demo: wrote %ux%u RGB565 test pattern\n", info.width, info.height); diff --git a/bsp/k230/applications/mnt.c b/bsp/k230/applications/mnt.c index 3e86c2db035..9c2c97b52a1 100644 --- a/bsp/k230/applications/mnt.c +++ b/bsp/k230/applications/mnt.c @@ -38,7 +38,7 @@ int mnt_init(void) rt_thread_mdelay(100); // Yield to the scheduler } - if (dfs_mount(BSP_SD_MNT_DEVNAME, "/", "elm", 0, 0) != 0) + if (dfs_mount(BSP_SD_MNT_DEVNAME, "/", "ext", 0, 0) != 0) { rt_kprintf("%s mounted on / failed!\n", BSP_SD_MNT_DEVNAME); } diff --git a/bsp/k230/board/board.h b/bsp/k230/board/board.h index c0d3a3d365d..47eafaee370 100644 --- a/bsp/k230/board/board.h +++ b/bsp/k230/board/board.h @@ -32,6 +32,12 @@ #define DMA_BASE_ADDR (0x80804000UL) #define DMA_IO_SIZE (0x00004000UL) +#define VO_BASE_ADDR (0x90840000UL) +#define VO_IO_SIZE (0x00010000UL) + +#define DSI_BASE_ADDR (0x90850000UL) +#define DSI_IO_SIZE (0x00001000UL) + #define PMU_BASE_ADDR (0x91000000UL) #define PMU_IO_SIZE (0x00000C00UL) @@ -68,6 +74,9 @@ #define TS_BASE_ADDR (0x91107000UL) #define TS_IO_SIZE (0x00000800UL) +#define STC_BASE_ADDR (0x91108000UL) +#define STC_IO_SIZE (0x00001000UL) + #define UART0_BASE_ADDR (0x91400000UL) #define UART0_IO_SIZE (0x00001000UL) diff --git a/bsp/k230/drivers/display/SConscript b/bsp/k230/drivers/display/SConscript index 2b8b1d523b4..d0fb772fab1 100644 --- a/bsp/k230/drivers/display/SConscript +++ b/bsp/k230/drivers/display/SConscript @@ -7,7 +7,13 @@ src += [ 'vo/kd_vo_reg.c', 'vo/kd_dsi_reg.c', ] -CPPPATH = [cwd, cwd + '/include', cwd + '/vo'] +CPPPATH = [ + cwd, + cwd + '/include', + cwd + '/vo', + cwd + '/../interdrv/sysctl/sysctl_power', + cwd + '/../interdrv/sysctl/sysctl_reset', +] group = DefineGroup('Display', src, depend=['BSP_USING_DISPLAY'], CPPPATH=CPPPATH) diff --git a/bsp/k230/drivers/display/bus_dsi.c b/bsp/k230/drivers/display/bus_dsi.c index cb7a65a3080..e4599de7475 100644 --- a/bsp/k230/drivers/display/bus_dsi.c +++ b/bsp/k230/drivers/display/bus_dsi.c @@ -7,6 +7,7 @@ #include "connector_bus_dsi.h" #define DSI_PHY_REF_CLK 24000000 +#define DSI_DPI_BITS_PER_PIXEL 16U typedef struct { k_u64 min_freq; @@ -59,7 +60,8 @@ static inline k_u32 dsi_bus_calc_lane_clk(const k_vo_timing* res, k_vo_dsi_lane_ if (!res || res->pclk_khz == 0 || lane_count == 0) return 0; - return ((res->pclk_khz * 3 * 8 * 1000) / (lane_count * 2)); + return ((res->pclk_khz * DSI_DPI_BITS_PER_PIXEL * 1000) / + (lane_count * 2)); } static k_u32 dsi_phy_calc_hsfreqrange(k_u64 bitrate_hz) @@ -176,13 +178,15 @@ k_u32 dsi_correct_pclk(k_u32 pclk_hz, k_vo_dsi_lane_num lanes) for (delta = 0; delta <= 10; delta++) { if (ratio + delta > 0) { candidate_pclk = VO_PIXEL_CLOCK_HZ / (ratio + delta); - lane_clk = (candidate_pclk / 1000 * 3 * 8 * 1000) / (lane_count * 2); + lane_clk = (candidate_pclk / 1000 * DSI_DPI_BITS_PER_PIXEL * 1000) / + (lane_count * 2); if (dsi_bus_check_lane_clk(lane_clk) == 0) return candidate_pclk; } if (delta > 0 && ratio > (k_u32)delta) { candidate_pclk = VO_PIXEL_CLOCK_HZ / (ratio - delta); - lane_clk = (candidate_pclk / 1000 * 3 * 8 * 1000) / (lane_count * 2); + lane_clk = (candidate_pclk / 1000 * DSI_DPI_BITS_PER_PIXEL * 1000) / + (lane_count * 2); if (dsi_bus_check_lane_clk(lane_clk) == 0) return candidate_pclk; } @@ -244,11 +248,6 @@ static int dsi_bus_init(const struct panel_desc* desc) dwc_dsi_init(&cfg); - if (desc->ops && desc->ops->read_chip_id) { - k_u32 chipid = desc->ops->read_chip_id(desc); - rt_kprintf("panel %s, chip id: 0x%08x\n", desc->name, chipid); - } - return 0; } diff --git a/bsp/k230/drivers/display/connector_bus_dsi.h b/bsp/k230/drivers/display/connector_bus_dsi.h index 50427d08394..d5a5498d57d 100644 --- a/bsp/k230/drivers/display/connector_bus_dsi.h +++ b/bsp/k230/drivers/display/connector_bus_dsi.h @@ -33,7 +33,7 @@ void dwc_dsi_init(k_vo_dsi_config* cfg); int dwc_dsi_enable(void); int dwc_dsi_disable(void); int dwc_dsi_send_packet(uint8_t type, uint8_t vc, const void* data, - uint32_t len, bool req_ack); + uint32_t len, uint8_t req_ack); int dwc_dsi_dcs_write(const void* data, uint32_t len, uint8_t vc); int dwc_dsi_dcs_read(uint8_t addr, void* buf, uint32_t len, uint8_t vc); int dwc_dsi_generic_write(const void* data, uint32_t len, uint8_t vc); diff --git a/bsp/k230/drivers/display/drv_display.c b/bsp/k230/drivers/display/drv_display.c index 23eea2c99d6..c5fb6238844 100644 --- a/bsp/k230/drivers/display/drv_display.c +++ b/bsp/k230/drivers/display/drv_display.c @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef RT_USING_SMART #include @@ -16,10 +17,15 @@ #include "connector_panel.h" #include "drv_display.h" #include "vo_display_remap.h" - -extern void kd_vo_set_background(k_u32 rgb888); +#include "kd_vo_reg.h" +#include "kd_dsi_reg.h" +#include "sysctl_pwr.h" +#include "sysctl_rst.h" extern struct panel_drv mipi_st7701_drv; +extern void dwc_dsi_debug_dump(void); +extern volatile sysctl_pwr_s *sysctl_pwr; +extern volatile sysctl_rst_t *sysctl_rst; static struct { struct rt_device lcd; @@ -32,6 +38,8 @@ static struct { rt_size_t framebuffer_size; rt_uint8_t brightness; rt_bool_t initialized; + rt_err_t last_error; + const char* last_stage; } g_display; static struct panel_drv* display_drv_list[] = { @@ -39,6 +47,85 @@ static struct panel_drv* display_drv_list[] = { RT_NULL, }; +static void display_flush_range(rt_uint8_t *addr, rt_size_t size); + +static rt_bool_t display_power_domains_ready(void) +{ + if (!sysctl_pwr) + return RT_FALSE; + + return ((sysctl_pwr->disp_lpi_state & 0x2U) != 0) && + ((sysctl_pwr->dpu_pwr_lpi_state & 0x2U) != 0); +} + +static rt_bool_t display_wait_power_domains(void) +{ + for (int i = 0; i < 20; i++) { + if (display_power_domains_ready()) + return RT_TRUE; + rt_thread_mdelay(1); + } + + return RT_FALSE; +} + +static rt_err_t display_hw_enable(void) +{ + bool disp_ok; + bool dpu_ok; + + disp_ok = sysctl_pwr_up(SYSCTL_PD_DISP); + dpu_ok = sysctl_pwr_up(SYSCTL_PD_DPU); + if (!display_wait_power_domains()) { + rt_kprintf("display: power domain enable failed, ret disp=%d dpu=%d state disp=0x%08x dpu=0x%08x\n", + disp_ok, dpu_ok, + sysctl_pwr ? sysctl_pwr->disp_lpi_state : 0, + sysctl_pwr ? sysctl_pwr->dpu_pwr_lpi_state : 0); + return -RT_ERROR; + } + if (!disp_ok || !dpu_ok) + rt_kprintf("display: power domain enable warning, ret disp=%d dpu=%d state disp=0x%08x dpu=0x%08x\n", + disp_ok, dpu_ok, sysctl_pwr->disp_lpi_state, + sysctl_pwr->dpu_pwr_lpi_state); + + disp_ok = sysctl_pwr_set_lpi(SYSCTL_PD_DISP, true); + dpu_ok = sysctl_pwr_set_lpi(SYSCTL_PD_DPU, true); + if (!disp_ok || !dpu_ok) + rt_kprintf("display: lpi exit warning, disp=%d dpu=%d\n", disp_ok, dpu_ok); + + (void)sysctl_set_reset_time(SYSCTL_RESET_TIME_DISP_SYS, 0xf, 0xf, 0xf); + (void)sysctl_set_reset_time(SYSCTL_RESET_TIME_DPU, 0, 0xf, 0xf); + + disp_ok = sysctl_reset(SYSCTL_RESET_DISP); + dpu_ok = sysctl_reset(SYSCTL_RESET_DPU); + if (!disp_ok || !dpu_ok) + rt_kprintf("display: reset warning, ret disp=%d dpu=%d ctl disp=0x%08x dpu=0x%08x\n", + disp_ok, dpu_ok, + sysctl_rst ? sysctl_rst->disp_rst_ctl : 0, + sysctl_rst ? sysctl_rst->dpu_rst_ctl : 0); + rt_thread_mdelay(1); + + return RT_EOK; +} + +static rt_err_t display_fail(const char *stage, rt_err_t error) +{ + g_display.last_stage = stage; + g_display.last_error = error; + return error; +} + +static void display_fb_release(void) +{ + if (g_display.framebuffer) + rt_free_align(g_display.framebuffer); + + g_display.framebuffer = RT_NULL; + g_display.framebuffer_pa = RT_NULL; + g_display.framebuffer_size = 0; + rt_memset(&g_display.info, 0, sizeof(g_display.info)); +} + static const struct panel_desc* find_panel_by_name(const char* name) { for (int i = 0; display_drv_list[i] != RT_NULL; i++) { @@ -62,6 +149,102 @@ static void display_flush_range(rt_uint8_t *addr, rt_size_t size) rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size); } +static void display_commit_framebuffer(void) +{ + if (!g_display.framebuffer || !g_display.framebuffer_size) + return; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, g_display.framebuffer, + g_display.framebuffer_size); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, g_display.framebuffer, + g_display.framebuffer_size); + if (g_display.initialized) + kd_vo_commit(); +} + +static void display_bind_default_osd(void) +{ + if (!g_display.initialized || !g_display.framebuffer_pa) + return; + + kd_vo_set_osd_rgb565_framebuffer(2, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + g_display.info.width, + g_display.info.height, + g_display.info.pitch); + kd_vo_select_osd(2); +} + +static rt_uint32_t display_fb_crc32(void) +{ + const rt_uint8_t *data = g_display.framebuffer; + rt_uint32_t crc = 0xffffffffU; + + if (!data || !g_display.framebuffer_size) + return 0; + + for (rt_size_t i = 0; i < g_display.framebuffer_size; i++) { + crc ^= data[i]; + for (int bit = 0; bit < 8; bit++) { + if (crc & 1U) + crc = (crc >> 1) ^ 0xedb88320U; + else + crc >>= 1; + } + } + + return ~crc; +} + +static rt_uint16_t display_fb_pixel(rt_uint16_t x, rt_uint16_t y) +{ + rt_uint16_t *line; + + if (!g_display.framebuffer || x >= g_display.info.width || y >= g_display.info.height) + return 0; + + line = (rt_uint16_t *)(g_display.framebuffer + y * g_display.info.pitch); + return line[x]; +} + +static void display_fb_probe_print(const char *tag) +{ + rt_uint16_t x0; + rt_uint16_t x1; + rt_uint16_t x2; + rt_uint16_t y0; + rt_uint16_t y1; + rt_uint16_t y2; + + if (!g_display.framebuffer) { + rt_kprintf("FB_PROBE %s not-ready\n", tag); + return; + } + + x0 = 0; + y0 = 0; + x1 = g_display.info.width / 2U; + y1 = g_display.info.height / 2U; + x2 = g_display.info.width ? (g_display.info.width - 1U) : 0; + y2 = g_display.info.height ? (g_display.info.height - 1U) : 0; + + rt_kprintf("FB_PROBE %s va=%p pa=%p size=0x%lx pitch=%u align_pa=0x%lx crc=0x%08x\n", + tag, g_display.framebuffer, g_display.framebuffer_pa, + (unsigned long)g_display.framebuffer_size, g_display.info.pitch, + ((unsigned long)(rt_ubase_t)g_display.framebuffer_pa) & 0xfffUL, + display_fb_crc32()); + rt_kprintf("FB_PROBE %s p00=0x%04x p_mid=0x%04x p_last=0x%04x p120_80=0x%04x p240_80=0x%04x p360_80=0x%04x p120_240=0x%04x p360_480=0x%04x\n", + tag, + display_fb_pixel(x0, y0), + display_fb_pixel(x1, y1), + display_fb_pixel(x2, y2), + display_fb_pixel(120, 80), + display_fb_pixel(240, 80), + display_fb_pixel(360, 80), + display_fb_pixel(120, 240), + display_fb_pixel(360, 480)); +} + static void display_flush_rect(const struct rt_device_rect_info *rect) { rt_uint16_t x; @@ -75,7 +258,8 @@ static void display_flush_rect(const struct rt_device_rect_info *rect) return; if (!rect) { - display_flush_range(g_display.framebuffer, g_display.framebuffer_size); + display_bind_default_osd(); + display_commit_framebuffer(); return; } @@ -98,6 +282,9 @@ static void display_flush_rect(const struct rt_device_rect_info *rect) if (x == 0 && width == g_display.info.width) { display_flush_range(g_display.framebuffer + y * g_display.info.pitch, height * g_display.info.pitch); + display_bind_default_osd(); + if (g_display.initialized) + kd_vo_commit(); return; } @@ -106,6 +293,9 @@ static void display_flush_rect(const struct rt_device_rect_info *rect) x * bytes_per_pixel, line_bytes); } + display_bind_default_osd(); + if (g_display.initialized) + kd_vo_commit(); } static rt_err_t display_init(rt_device_t dev) @@ -119,28 +309,32 @@ static rt_err_t display_init(rt_device_t dev) if (!g_display.panel) { rt_kprintf("display: no panel selected\n"); - return -RT_ERROR; + return display_fail("select-panel", -RT_ERROR); } + rt_kprintf("display: init start, panel=%s\n", g_display.panel->name); + + if (display_hw_enable() != RT_EOK) + return display_fail("hw-enable", -RT_ERROR); + if (vo_display_remap_init() != 0) { rt_kprintf("display: register remap failed\n"); - return -RT_ERROR; + return display_fail("remap", -RT_ERROR); } fb_size = g_display.panel->timing.hactive * g_display.panel->timing.vactive * 2; g_display.framebuffer = rt_malloc_align(fb_size, K230_DISPLAY_FB_ALIGN); if (!g_display.framebuffer) { rt_kprintf("display: framebuffer allocation failed\n"); - return -RT_ENOMEM; + return display_fail("fb-alloc", -RT_ENOMEM); } rt_memset(g_display.framebuffer, 0, fb_size); g_display.framebuffer_pa = rt_kmem_v2p(g_display.framebuffer); if (!g_display.framebuffer_pa || g_display.framebuffer_pa == ARCH_MAP_FAILED) { rt_kprintf("display: framebuffer physical address failed\n"); - rt_free_align(g_display.framebuffer); - g_display.framebuffer = RT_NULL; - return -RT_ERROR; + display_fb_release(); + return display_fail("fb-phys", -RT_ERROR); } g_display.framebuffer_size = fb_size; @@ -155,19 +349,22 @@ static rt_err_t display_init(rt_device_t dev) if (panel_generic_power_on(g_display.panel) != 0) { rt_kprintf("display: power_on failed\n"); - rt_free_align(g_display.framebuffer); - g_display.framebuffer = RT_NULL; - g_display.framebuffer_pa = RT_NULL; - g_display.framebuffer_size = 0; - rt_memset(&g_display.info, 0, sizeof(g_display.info)); - return -RT_ERROR; + display_fb_release(); + return display_fail("panel-power-on", -RT_ERROR); } g_display.initialized = RT_TRUE; g_display.brightness = 255; + g_display.last_stage = "ready"; + g_display.last_error = RT_EOK; + + kd_vo_disable_osd_all(); panel_generic_backlight(g_display.panel, 1, g_display.brightness); + rt_kprintf("display: init done, fb va=%p pa=%p size=0x%lx\n", + g_display.framebuffer, g_display.framebuffer_pa, + (unsigned long)g_display.framebuffer_size); return RT_EOK; } @@ -222,7 +419,8 @@ static rt_ssize_t display_write(rt_device_t dev, rt_off_t pos, const void *buffe rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); rt_memcpy(g_display.framebuffer + pos, buffer, count); - display_flush_range(g_display.framebuffer + pos, count); + display_bind_default_osd(); + display_commit_framebuffer(); rt_mutex_release(&g_display.lock); return count; @@ -299,6 +497,9 @@ static void display_set_pixel(const char *pixel, int x, int y) dst = g_display.framebuffer + y * g_display.info.pitch + x * bytes_per_pixel; rt_memcpy(dst, pixel, bytes_per_pixel); display_flush_range(dst, bytes_per_pixel); + display_bind_default_osd(); + if (g_display.initialized) + kd_vo_commit(); } static void display_get_pixel(char *pixel, int x, int y) @@ -342,6 +543,9 @@ static void display_draw_hline(const char *pixel, int x1, int x2, int y) } display_flush_range(g_display.framebuffer + y * g_display.info.pitch + x1 * bytes_per_pixel, (x2 - x1 + 1) * bytes_per_pixel); + display_bind_default_osd(); + if (g_display.initialized) + kd_vo_commit(); } static void display_draw_vline(const char *pixel, int x, int y1, int y2) @@ -383,6 +587,9 @@ static void display_blit_line(const char *pixel, int x, int y, rt_size_t size) dst = g_display.framebuffer + y * g_display.info.pitch + x * bytes_per_pixel; rt_memcpy(dst, pixel, size); display_flush_range(dst, size); + display_bind_default_osd(); + if (g_display.initialized) + kd_vo_commit(); } static struct rt_device_graphic_ops display_graphic_ops = { @@ -430,6 +637,839 @@ static void list_display(int argc, char** argv) MSH_CMD_EXPORT(list_display, list display panels); +static void display_dump(int argc, char** argv) +{ + (void)argc; + (void)argv; + + rt_kprintf("display initialized=%d panel=%s\n", + g_display.initialized, + g_display.panel ? g_display.panel->name : ""); + rt_kprintf("display last_stage=%s last_error=%d\n", + g_display.last_stage ? g_display.last_stage : "", + g_display.last_error); + rt_kprintf("fb va=%p pa=%p size=0x%lx width=%u height=%u pitch=%u bpp=%u brightness=%u\n", + g_display.framebuffer, g_display.framebuffer_pa, + (unsigned long)g_display.framebuffer_size, + g_display.info.width, g_display.info.height, + g_display.info.pitch, g_display.info.bits_per_pixel, + g_display.brightness); + + if (g_display.panel) { + const k_vo_timing *t = &g_display.panel->timing; + + rt_kprintf("timing pclk=%u h=%u/%u/%u/%u v=%u/%u/%u/%u bg=0x%08x\n", + t->pclk_khz, + t->hactive, t->hsync_len, t->hback_porch, t->hfront_porch, + t->vactive, t->vsync_len, t->vback_porch, t->vfront_porch, + g_display.panel->bg_color); + } + + if (sysctl_pwr) { + rt_kprintf("PWR base=%p disp_ctl=0x%08x disp_state=0x%08x dpu_ctl=0x%08x dpu_state=0x%08x repair=0x%08x\n", + sysctl_pwr, + sysctl_pwr->disp_lpi_ctl, sysctl_pwr->disp_lpi_state, + sysctl_pwr->dpu_pwr_lpi_ctl, sysctl_pwr->dpu_pwr_lpi_state, + sysctl_pwr->repair_status); + } else { + rt_kprintf("PWR base=\n"); + } + + if (sysctl_rst) { + rt_kprintf("RMU base=%p dpu_rst_tim=0x%08x dpu_rst_ctl=0x%08x disp_rst_tim=0x%08x disp_rst_ctl=0x%08x\n", + sysctl_rst, + sysctl_rst->dpu_rst_tim, sysctl_rst->dpu_rst_ctl, + sysctl_rst->disp_sys_rst_tim, sysctl_rst->disp_rst_ctl); + } else { + rt_kprintf("RMU base=\n"); + } + + kd_vo_debug_dump(); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_dump, dump K230 display registers); + +static void display_bind_osd(int argc, char** argv) +{ + int osd; + + if (argc != 2) { + rt_kprintf("usage: display_bind_osd <0-3>\n"); + return; + } + + if (!g_display.framebuffer_pa) { + rt_kprintf("display: framebuffer is not ready\n"); + return; + } + + osd = atoi(argv[1]); + if (osd < 0 || osd > 3) { + rt_kprintf("display: invalid osd %d\n", osd); + return; + } + + kd_vo_set_osd_rgb565_framebuffer((k_u32)osd, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + g_display.info.width, g_display.info.height, + g_display.info.pitch); + kd_vo_select_osd((k_u32)osd); + display_commit_framebuffer(); + rt_kprintf("display: bound fb0 to OSD%d\n", osd); +} +MSH_CMD_EXPORT(display_bind_osd, bind fb0 to K230 VO OSD plane); + +static void display_peek(int argc, char** argv) +{ + volatile rt_uint32_t *base = RT_NULL; + unsigned long offset; + unsigned long count = 1; + + if (argc < 3 || argc > 4) { + rt_kprintf("usage: display_peek [count]\n"); + return; + } + + if (vo_display_remap_init() != 0) { + rt_kprintf("display: register remap failed\n"); + return; + } + + if (rt_strcmp(argv[1], "vo") == 0) { + base = (volatile rt_uint32_t *)display_remap->vo_base; + } else if (rt_strcmp(argv[1], "dsi") == 0) { + base = (volatile rt_uint32_t *)display_remap->dsi_base; + } else if (rt_strcmp(argv[1], "phy") == 0) { + base = (volatile rt_uint32_t *)display_remap->phy_base; + } else if (rt_strcmp(argv[1], "pwr") == 0) { + base = (volatile rt_uint32_t *)sysctl_pwr; + } else if (rt_strcmp(argv[1], "rmu") == 0) { + base = (volatile rt_uint32_t *)sysctl_rst; + } else if (rt_strcmp(argv[1], "cmu") == 0) { + base = (volatile rt_uint32_t *)display_remap->clock_base; + } else if (rt_strcmp(argv[1], "stc") == 0) { + base = (volatile rt_uint32_t *)display_remap->timestamp_base; + } else { + rt_kprintf("display: unknown region %s\n", argv[1]); + return; + } + + if (base == RT_NULL) { + rt_kprintf("display: region %s is not mapped\n", argv[1]); + return; + } + + offset = strtoul(argv[2], RT_NULL, 0); + if ((offset & 0x3UL) != 0) { + rt_kprintf("display: offset must be 4-byte aligned\n"); + return; + } + + if (argc == 4) + count = strtoul(argv[3], RT_NULL, 0); + if (count == 0) + count = 1; + if (count > 64) + count = 64; + + for (unsigned long i = 0; i < count; i++) { + volatile rt_uint32_t *reg = (volatile rt_uint32_t *)((rt_uint8_t *)base + offset + i * 4); + + rt_kprintf("%s[0x%04lx] = 0x%08x\n", + argv[1], offset + i * 4, *reg); + } +} +MSH_CMD_EXPORT(display_peek, read K230 display/sysctl registers); + +static void display_poke(int argc, char** argv) +{ + unsigned long offset; + unsigned long value; + + if (argc != 3) { + rt_kprintf("usage: display_poke \n"); + return; + } + + offset = strtoul(argv[1], RT_NULL, 0); + value = strtoul(argv[2], RT_NULL, 0); + if ((offset & 0x3UL) != 0) { + rt_kprintf("display: offset must be 4-byte aligned\n"); + return; + } + + kd_vo_poke((k_u32)offset, (k_u32)value); + rt_kprintf("vo[0x%04lx] <- 0x%08lx\n", offset, value); +} +MSH_CMD_EXPORT(display_poke, write a K230 VO register); + +static void display_osd_tune(int argc, char** argv) +{ + int osd; + unsigned long stride; + unsigned long dma_ctrl; + unsigned long addr_sel; + + if (argc != 5) { + rt_kprintf("usage: display_osd_tune \n"); + rt_kprintf("example: display_osd_tune 2 0x00000078 0x7f 0x100\n"); + return; + } + + if (!g_display.framebuffer_pa) { + rt_kprintf("display: framebuffer is not ready\n"); + return; + } + + osd = atoi(argv[1]); + if (osd < 0 || osd > 3) { + rt_kprintf("display: invalid osd %d\n", osd); + return; + } + + stride = strtoul(argv[2], RT_NULL, 0); + dma_ctrl = strtoul(argv[3], RT_NULL, 0); + addr_sel = strtoul(argv[4], RT_NULL, 0); + + kd_vo_set_osd_rgb565_framebuffer_raw((k_u32)osd, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + g_display.info.width, + g_display.info.height, + (k_u32)stride, + (k_u32)dma_ctrl, + (k_u32)addr_sel); + kd_vo_select_osd((k_u32)osd); + display_commit_framebuffer(); + rt_kprintf("display: osd%d stride=0x%08lx dma=0x%08lx sel=0x%08lx addr=0x%08lx\n", + osd, stride, dma_ctrl, addr_sel, + (unsigned long)(rt_ubase_t)g_display.framebuffer_pa); +} +MSH_CMD_EXPORT(display_osd_tune, tune K230 VO OSD framebuffer registers); + +static void display_phy(int argc, char** argv) +{ + unsigned long m; + unsigned long n; + unsigned long voc; + unsigned long hs_freq; + + if (argc != 5) { + rt_kprintf("usage: display_phy \n"); + return; + } + + if (vo_display_remap_init() != 0) { + rt_kprintf("display: register remap failed\n"); + return; + } + + m = strtoul(argv[1], RT_NULL, 0); + n = strtoul(argv[2], RT_NULL, 0); + voc = strtoul(argv[3], RT_NULL, 0); + hs_freq = strtoul(argv[4], RT_NULL, 0); + + k230_dsi_phy_config(K_DSI_2LAN, (k_u32)m, (k_u32)n, (k_u8)voc, (k_u8)hs_freq); + rt_thread_mdelay(1); + rt_kprintf("display: phy set m=%lu n=%lu voc=0x%02lx hs_freq=0x%02lx\n", + m, n, voc, hs_freq); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_phy, configure K230 DSI PHY clock parameters); + +static void display_hw_on(int argc, char** argv) +{ + (void)argc; + (void)argv; + + if (display_hw_enable() == RT_EOK) + rt_kprintf("display: DISP/DPU power and reset sequence done\n"); +} +MSH_CMD_EXPORT(display_hw_on, enable K230 display power domains and reset blocks); + +static void display_init_now(int argc, char** argv) +{ + rt_err_t ret; + + (void)argc; + (void)argv; + + ret = display_init(&g_display.lcd); + rt_kprintf("display_init_now: ret=%d initialized=%d stage=%s\n", + ret, g_display.initialized, + g_display.last_stage ? g_display.last_stage : ""); +} +MSH_CMD_EXPORT(display_init_now, initialize K230 display immediately); + +static void display_panel_on(int argc, char** argv) +{ + k_u8 vc; + k_u8 sleep_out[] = { 0x11 }; + k_u8 pixel_format[] = { 0x3A, 0x50 }; + k_u8 display_on[] = { 0x29 }; + int ret_sleep; + int ret_format; + int ret_on; + + (void)argc; + (void)argv; + + if (!g_display.panel) { + rt_kprintf("display: no panel selected\n"); + return; + } + + vc = g_display.panel->bus.dsi.vc_id; + ret_sleep = dwc_dsi_dcs_write(sleep_out, sizeof(sleep_out), vc); + rt_thread_mdelay(200); + ret_format = dwc_dsi_dcs_write(pixel_format, sizeof(pixel_format), vc); + ret_on = dwc_dsi_dcs_write(display_on, sizeof(display_on), vc); + rt_thread_mdelay(50); + + rt_kprintf("display_panel_on: sleep=%d format=%d display=%d\n", + ret_sleep, ret_format, ret_on); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_panel_on, send ST7701 sleep-out pixel-format display-on); + +static int display_panel_set_colmod(k_u8 value) +{ + k_u8 vc; + k_u8 pixel_format[2]; + + if (!g_display.panel) + return -RT_ERROR; + + vc = g_display.panel->bus.dsi.vc_id; + pixel_format[0] = 0x3A; + pixel_format[1] = value; + return dwc_dsi_dcs_write(pixel_format, sizeof(pixel_format), vc); +} + +static void display_colmod(int argc, char** argv) +{ + unsigned long value; + int ret; + + if (argc != 2) { + rt_kprintf("usage: display_colmod <0x50|0x55|0x66>\n"); + return; + } + + value = strtoul(argv[1], RT_NULL, 0); + ret = display_panel_set_colmod((k_u8)value); + rt_kprintf("display: panel COLMOD=0x%02lx ret=%d\n", value & 0xffUL, ret); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_colmod, set panel DCS 0x3A pixel format); + +static void display_panel_status_read(k_u8 cmd, const char *name) +{ + k_u8 vc = g_display.panel->bus.dsi.vc_id; + k_u8 max_return[2] = { 1, 0 }; + k_u8 data[4] = { 0 }; + int ret; + + ret = dwc_dsi_send_packet(0x37, vc, max_return, sizeof(max_return), 0); + if (ret != 0) { + rt_kprintf("%s(0x%02x): set-max-return failed ret=%d\n", + name, cmd, ret); + return; + } + + ret = dwc_dsi_dcs_read(cmd, data, 1, vc); + if (ret < 0) { + rt_kprintf("%s(0x%02x): read failed ret=%d\n", name, cmd, ret); + return; + } + + rt_kprintf("%s(0x%02x): ret=%d data=0x%02x\n", + name, cmd, ret, data[0]); +} + +static void display_panel_status(int argc, char** argv) +{ + (void)argc; + (void)argv; + + if (!g_display.panel) { + rt_kprintf("display: no panel selected\n"); + return; + } + + display_panel_status_read(0x0A, "power-mode"); + display_panel_status_read(0x0B, "address-mode"); + display_panel_status_read(0x0C, "pixel-format"); + display_panel_status_read(0x0D, "display-mode"); + display_panel_status_read(0x0E, "signal-mode"); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_panel_status, read basic panel DCS status registers); + +static void display_bg(int argc, char** argv) +{ + unsigned long color; + + if (argc != 2) { + rt_kprintf("usage: display_bg \n"); + return; + } + + color = strtoul(argv[1], RT_NULL, 0); + kd_vo_set_background((k_u32)color); + rt_kprintf("display: background rgb888=0x%06lx\n", color & 0xffffffUL); +} +MSH_CMD_EXPORT(display_bg, set VO background color from RGB888); + +static void display_bg_yuv(int argc, char** argv) +{ + unsigned long color; + + if (argc != 2) { + rt_kprintf("usage: display_bg_yuv \n"); + return; + } + + color = strtoul(argv[1], RT_NULL, 0); + kd_vo_set_background_yuv((k_u32)color); + rt_kprintf("display: background yuv=0x%06lx\n", color & 0xffffffUL); +} +MSH_CMD_EXPORT(display_bg_yuv, set VO background color from packed YUV); + +static rt_uint16_t display_rgb565(rt_uint8_t r, rt_uint8_t g, rt_uint8_t b) +{ + return (rt_uint16_t)(((r & 0xf8U) << 8) | ((g & 0xfcU) << 3) | (b >> 3)); +} + +static void display_fill(int argc, char** argv) +{ + unsigned long rgb; + rt_uint8_t r; + rt_uint8_t g; + rt_uint8_t b; + rt_uint16_t color; + rt_uint16_t *fb; + rt_size_t pixels; + + if (argc != 2) { + rt_kprintf("usage: display_fill \n"); + return; + } + + if (!g_display.framebuffer) { + rt_kprintf("display: framebuffer is not ready\n"); + return; + } + + rgb = strtoul(argv[1], RT_NULL, 0); + r = (rt_uint8_t)((rgb >> 16) & 0xffU); + g = (rt_uint8_t)((rgb >> 8) & 0xffU); + b = (rt_uint8_t)(rgb & 0xffU); + color = display_rgb565(r, g, b); + fb = (rt_uint16_t *)g_display.framebuffer; + pixels = (g_display.info.pitch / 2U) * g_display.info.height; + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + for (rt_size_t i = 0; i < pixels; i++) + fb[i] = color; + display_bind_default_osd(); + display_commit_framebuffer(); + rt_mutex_release(&g_display.lock); + + rt_kprintf("display: filled fb0 rgb888=0x%06lx rgb565=0x%04x\n", + rgb & 0xffffffUL, color); +} +MSH_CMD_EXPORT(display_fill, fill fb0 with one RGB565 color); + +static void display_draw_rect_rgb565(rt_int32_t x, rt_int32_t y, + rt_int32_t w, rt_int32_t h, + rt_uint16_t color) +{ + rt_int32_t x0; + rt_int32_t y0; + rt_int32_t x1; + rt_int32_t y1; + rt_uint16_t *line; + + if (!g_display.framebuffer || w <= 0 || h <= 0) + return; + + x0 = x; + y0 = y; + x1 = x + w; + y1 = y + h; + + if (x0 < 0) + x0 = 0; + if (y0 < 0) + y0 = 0; + if (x1 > (rt_int32_t)g_display.info.width) + x1 = g_display.info.width; + if (y1 > (rt_int32_t)g_display.info.height) + y1 = g_display.info.height; + if (x0 >= x1 || y0 >= y1) + return; + + for (rt_int32_t row = y0; row < y1; row++) { + line = (rt_uint16_t *)(g_display.framebuffer + + row * g_display.info.pitch + + x0 * sizeof(rt_uint16_t)); + for (rt_int32_t col = x0; col < x1; col++) + *line++ = color; + } +} + +static void display_rect(int argc, char** argv) +{ + rt_int32_t x; + rt_int32_t y; + rt_int32_t w; + rt_int32_t h; + unsigned long rgb; + rt_uint16_t color; + + if (argc != 6) { + rt_kprintf("usage: display_rect \n"); + return; + } + + if (!g_display.framebuffer) { + rt_kprintf("display: framebuffer is not ready\n"); + return; + } + + x = (rt_int32_t)strtol(argv[1], RT_NULL, 0); + y = (rt_int32_t)strtol(argv[2], RT_NULL, 0); + w = (rt_int32_t)strtol(argv[3], RT_NULL, 0); + h = (rt_int32_t)strtol(argv[4], RT_NULL, 0); + rgb = strtoul(argv[5], RT_NULL, 0); + color = display_rgb565((rt_uint8_t)((rgb >> 16) & 0xffU), + (rt_uint8_t)((rgb >> 8) & 0xffU), + (rt_uint8_t)(rgb & 0xffU)); + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + display_draw_rect_rgb565(x, y, w, h, color); + display_bind_default_osd(); + display_commit_framebuffer(); + rt_mutex_release(&g_display.lock); + + rt_kprintf("display: rect x=%d y=%d w=%d h=%d rgb888=0x%06lx rgb565=0x%04x\n", + x, y, w, h, rgb & 0xffffffUL, color); +} +MSH_CMD_EXPORT(display_rect, draw an RGB565 rectangle into fb0); + +static void display_blocks(int argc, char** argv) +{ + (void)argc; + (void)argv; + + if (!g_display.framebuffer) { + rt_kprintf("display: framebuffer is not ready\n"); + return; + } + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + display_draw_rect_rgb565(0, 0, 120, 160, display_rgb565(255, 0, 0)); + display_draw_rect_rgb565(120, 0, 120, 160, display_rgb565(0, 255, 0)); + display_draw_rect_rgb565(240, 0, 120, 160, display_rgb565(0, 0, 255)); + display_draw_rect_rgb565(360, 0, 120, 160, display_rgb565(255, 255, 255)); + display_draw_rect_rgb565(0, 160, 240, 160, display_rgb565(255, 255, 0)); + display_draw_rect_rgb565(240, 160, 240, 160, display_rgb565(0, 255, 255)); + display_draw_rect_rgb565(0, 320, 240, 320, display_rgb565(255, 0, 255)); + display_draw_rect_rgb565(240, 320, 240, 320, display_rgb565(32, 32, 32)); + display_bind_default_osd(); + display_commit_framebuffer(); + rt_mutex_release(&g_display.lock); + + rt_kprintf("display: drew RGB565 block pattern\n"); +} +MSH_CMD_EXPORT(display_blocks, draw fixed RGB565 rectangles into fb0); + +static void display_fb_probe(int argc, char** argv) +{ + (void)argc; + (void)argv; + + display_commit_framebuffer(); + display_fb_probe_print("manual"); + kd_vo_debug_summary(); +} +MSH_CMD_EXPORT(display_fb_probe, print framebuffer checksum and key pixels); + +static void display_diag_write_blocks(void) +{ + display_draw_rect_rgb565(0, 0, 120, 160, display_rgb565(255, 0, 0)); + display_draw_rect_rgb565(120, 0, 120, 160, display_rgb565(0, 255, 0)); + display_draw_rect_rgb565(240, 0, 120, 160, display_rgb565(0, 0, 255)); + display_draw_rect_rgb565(360, 0, 120, 160, display_rgb565(255, 255, 255)); + display_draw_rect_rgb565(0, 160, 240, 160, display_rgb565(255, 255, 0)); + display_draw_rect_rgb565(240, 160, 240, 160, display_rgb565(0, 255, 255)); + display_draw_rect_rgb565(0, 320, 240, 320, display_rgb565(255, 0, 255)); + display_draw_rect_rgb565(240, 320, 240, 320, display_rgb565(32, 32, 32)); +} + +static void display_diag_fill_rgb565(rt_uint16_t color) +{ + rt_uint16_t *fb = (rt_uint16_t *)g_display.framebuffer; + rt_size_t pixels = (g_display.info.pitch / 2U) * g_display.info.height; + + for (rt_size_t i = 0; i < pixels; i++) + fb[i] = color; +} + +static void display_diag_case_format(const char *name, int osd, k_u32 stride, + k_u32 info, k_u32 dma_ctrl, k_u32 addr_sel, + rt_bool_t blocks, rt_uint16_t fill); + +static void display_diag_case(const char *name, int osd, k_u32 stride, + k_u32 dma_ctrl, k_u32 addr_sel, rt_bool_t blocks, + rt_uint16_t fill) +{ + display_diag_case_format(name, osd, stride, 0x00000002U, dma_ctrl, addr_sel, + blocks, fill); +} + +static void display_diag_case_format(const char *name, int osd, k_u32 stride, + k_u32 info, k_u32 dma_ctrl, k_u32 addr_sel, + rt_bool_t blocks, rt_uint16_t fill) +{ + rt_kprintf("DIAG_CASE begin %s osd=%d stride=0x%08x info=0x%08x dma=0x%08x sel=0x%08x pattern=%s\n", + name, osd, stride, info, dma_ctrl, addr_sel, blocks ? "blocks" : "fill"); + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + if (blocks) + display_diag_write_blocks(); + else + display_diag_fill_rgb565(fill); + display_commit_framebuffer(); + kd_vo_set_osd_rgb565_framebuffer_format_raw((k_u32)osd, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + g_display.info.width, + g_display.info.height, + stride, + info, + dma_ctrl, + addr_sel); + kd_vo_select_osd((k_u32)osd); + rt_mutex_release(&g_display.lock); + + kd_vo_debug_summary(); + display_fb_probe_print(name); + rt_kprintf("DIAG_CASE end %s observe-screen-now\n", name); + rt_thread_mdelay(800); +} + +static void display_diag_bg_case(const char *name, k_u32 yuv) +{ + rt_kprintf("DIAG_CASE begin %s bg_yuv=0x%06x\n", name, yuv & 0xffffffU); + kd_vo_disable_osd_all(); + kd_vo_set_background_yuv(yuv); + kd_vo_debug_summary(); + display_fb_probe_print(name); + rt_kprintf("DIAG_CASE end %s observe-screen-now\n", name); + rt_thread_mdelay(500); +} + +static void display_bg_only(int argc, char** argv) +{ + unsigned long yuv = 0x4c551dUL; + + if (argc > 2) { + rt_kprintf("usage: display_bg_only [yuv]\n"); + return; + } + if (!g_display.initialized) { + rt_kprintf("display_bg_only: display is not initialized, run display_init_now first\n"); + return; + } + if (argc == 2) + yuv = strtoul(argv[1], RT_NULL, 0); + + kd_vo_disable_osd_all(); + kd_vo_set_background_yuv((k_u32)yuv); + rt_kprintf("display: background only yuv=0x%06lx\n", yuv & 0xffffffUL); + kd_vo_debug_summary(); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_bg_only, disable OSD planes and show VO background color); + +static void display_diag(int argc, char** argv) +{ + k_u32 stride_sdk; + k_u32 stride_packed16; + k_u32 stride_legacy_low; + + (void)argc; + (void)argv; + + if (!g_display.initialized) { + rt_kprintf("display_diag: display is not initialized, run display_init_now first\n"); + return; + } + if (!g_display.framebuffer || !g_display.framebuffer_pa) { + rt_kprintf("display_diag: framebuffer is not ready\n"); + return; + } + + stride_sdk = g_display.info.pitch / 8U; + stride_packed16 = (g_display.info.pitch / 32U) | ((g_display.info.pitch / 32U) << 16); + stride_legacy_low = g_display.info.pitch / 32U; + + rt_kprintf("DIAG_START fb_va=%p fb_pa=%p size=0x%lx w=%u h=%u pitch=%u stride_sdk64=0x%08x stride_packed16=0x%08x stride_legacy_low=0x%08x\n", + g_display.framebuffer, g_display.framebuffer_pa, + (unsigned long)g_display.framebuffer_size, + g_display.info.width, g_display.info.height, g_display.info.pitch, + stride_sdk, stride_packed16, stride_legacy_low); + + display_commit_framebuffer(); + display_fb_probe_print("start"); + kd_vo_debug_summary(); + dwc_dsi_debug_dump(); + + display_diag_bg_case("bg-red-yuv", 0x4c551d); + display_diag_bg_case("bg-green-yuv", 0x952b15); + display_diag_bg_case("bg-blue-yuv", 0x1d6bff); + + display_diag_case_format("osd2-blocks-sdk-rgb565", 2, stride_sdk, 0x00000002U, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd2-fill-red-sdk-rgb565", 2, stride_sdk, 0x00000002U, 0x0000007fU, 0x00000100U, RT_FALSE, display_rgb565(255, 0, 0)); + display_diag_case_format("osd0-blocks-sdk-rgb565", 0, stride_sdk, 0x00000002U, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd1-blocks-sdk-rgb565", 1, stride_sdk, 0x00000002U, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd3-blocks-sdk-rgb565", 3, stride_sdk, 0x00000002U, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + + display_diag_case_format("osd2-blocks-prev-dma0f", 2, stride_sdk, 0x00000002U, 0x0000000fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd2-blocks-prev-dma4f", 2, stride_sdk, 0x00000002U, 0x0000004fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd2-blocks-info2-dma3f", 2, stride_sdk, 0x00000002U, 0x0000003fU, 0x00000100U, RT_TRUE, 0); + display_diag_case_format("osd2-blocks-info2-dma5f", 2, stride_sdk, 0x00000002U, 0x0000005fU, 0x00000100U, RT_TRUE, 0); + display_diag_case("osd2-blocks-packed16", 2, stride_packed16, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + display_diag_case("osd2-blocks-legacy-low", 2, stride_legacy_low, 0x0000007fU, 0x00000100U, RT_TRUE, 0); + display_diag_case("osd2-blocks-sel0", 2, stride_sdk, 0x0000007fU, 0x00000000U, RT_TRUE, 0); + + rt_kprintf("DIAG_DONE\n"); +} +MSH_CMD_EXPORT(display_diag, run concentrated display scanout diagnostics); + +static void display_dsi_video(int argc, char** argv) +{ + unsigned long dpi_color; + unsigned long pkt; + unsigned long hsa; + unsigned long hbp; + unsigned long hline; + unsigned long mode; + + if (argc != 7) { + rt_kprintf("usage: display_dsi_video \n"); + return; + } + + dpi_color = strtoul(argv[1], RT_NULL, 0); + pkt = strtoul(argv[2], RT_NULL, 0); + hsa = strtoul(argv[3], RT_NULL, 0); + hbp = strtoul(argv[4], RT_NULL, 0); + hline = strtoul(argv[5], RT_NULL, 0); + mode = strtoul(argv[6], RT_NULL, 0); + + dwc_dsi_set_video_scan((k_u32)dpi_color, (k_u32)pkt, + (k_u32)hsa, (k_u32)hbp, + (k_u32)hline, (k_u32)mode); + rt_kprintf("display: dsi video dpi=0x%lx pkt=%lu hsa=%lu hbp=%lu hline=%lu mode=%lu\n", + dpi_color & 0x7UL, pkt, hsa, hbp, hline, mode); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_dsi_video, set DSI DPI video scan registers); + +static void display_dsi_diag_case(const char *name, k_u8 colmod, + k_u32 dpi_color, k_u32 pkt, + k_u32 hsa, k_u32 hbp, + k_u32 hline, k_u32 mode) +{ + int ret; + k_u32 stride_sdk; + + stride_sdk = g_display.info.pitch / 8U; + + rt_kprintf("DSI_DIAG_CASE begin %s colmod=0x%02x dpi=0x%08x pkt=%u hsa=%u hbp=%u hline=%u mode=%u\n", + name, colmod, dpi_color, pkt, hsa, hbp, hline, mode); + + ret = display_panel_set_colmod(colmod); + rt_kprintf("DSI_DIAG_CASE %s colmod_ret=%d\n", name, ret); + dwc_dsi_set_video_scan(dpi_color, pkt, hsa, hbp, hline, mode); + + rt_mutex_take(&g_display.lock, RT_WAITING_FOREVER); + display_diag_write_blocks(); + display_commit_framebuffer(); + kd_vo_set_osd_rgb565_framebuffer_raw(2, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + (k_u64)(rt_ubase_t)g_display.framebuffer_pa, + g_display.info.width, + g_display.info.height, + stride_sdk, + 0x0000007fU, + 0x00000100U); + kd_vo_select_osd(2); + rt_mutex_release(&g_display.lock); + + kd_vo_debug_summary(); + dwc_dsi_debug_dump(); + display_fb_probe_print(name); + rt_kprintf("DSI_DIAG_CASE end %s observe-screen-now\n", name); + rt_thread_mdelay(1000); +} + +static void display_dsi_diag(int argc, char** argv) +{ + (void)argc; + (void)argv; + + if (!g_display.initialized) { + rt_kprintf("display_dsi_diag: display is not initialized, run display_init_now first\n"); + return; + } + if (!g_display.framebuffer || !g_display.framebuffer_pa) { + rt_kprintf("display_dsi_diag: framebuffer is not ready\n"); + return; + } + + rt_kprintf("DSI_DIAG_START w=%u h=%u pitch=%u fb_pa=%p\n", + g_display.info.width, g_display.info.height, + g_display.info.pitch, g_display.framebuffer_pa); + kd_vo_debug_summary(); + dwc_dsi_debug_dump(); + + display_dsi_diag_case("col70-dpi5-p480-h840-burst", 0x70, 5, 480, 30, 30, 840, K_BURST_MODE); + display_dsi_diag_case("col70-dpi5-p480-h840-sync-event", 0x70, 5, 480, 30, 30, 840, K_NON_BURST_MODE_WITH_SYNC_EVENT); + display_dsi_diag_case("col70-dpi5-p480-h840-pulses", 0x70, 5, 480, 30, 30, 840, K_NON_BURST_MODE_WITH_PULSES); + display_dsi_diag_case("col50-dpi0-p480-h560-burst", 0x50, 0, 480, 20, 20, 560, K_BURST_MODE); + display_dsi_diag_case("col50-dpi1-p480-h560-burst", 0x50, 1, 480, 20, 20, 560, K_BURST_MODE); + display_dsi_diag_case("col50-dpi2-p480-h560-burst", 0x50, 2, 480, 20, 20, 560, K_BURST_MODE); + display_dsi_diag_case("col55-dpi5-p480-h840-burst", 0x55, 5, 480, 30, 30, 840, K_BURST_MODE); + display_dsi_diag_case("col55-dpi5-p480-h560-burst", 0x55, 5, 480, 20, 20, 560, K_BURST_MODE); + display_dsi_diag_case("col66-dpi5-p480-h840-burst", 0x66, 5, 480, 30, 30, 840, K_BURST_MODE); + + (void)display_panel_set_colmod(0x50); + dwc_dsi_set_video_scan(1, 480, 20, 20, 560, K_BURST_MODE); + rt_kprintf("DSI_DIAG_DONE restored colmod=0x50 dpi=1 pkt=480 hline=560 burst\n"); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_dsi_diag, scan DSI video color and timing combinations); + +static void display_dpi_color(int argc, char** argv) +{ + unsigned long coding; + + if (argc != 2) { + rt_kprintf("usage: display_dpi_color <0|1|2|5>\n"); + return; + } + + coding = strtoul(argv[1], RT_NULL, 0); + dwc_dsi_set_dpi_color_coding((k_u32)coding); + rt_kprintf("display: DSI DPI color coding=0x%lx\n", coding & 0x7UL); + dwc_dsi_debug_dump(); +} +MSH_CMD_EXPORT(display_dpi_color, set DSI DPI color coding register); + static const struct rt_device_ops display_ops = { .init = display_init, .open = display_open, @@ -461,14 +1501,10 @@ int k230_display_init(void) rt_device_register(&g_display.lcd, "lcd", RT_DEVICE_FLAG_RDWR); rt_device_register(&g_display.fb, "fb0", RT_DEVICE_FLAG_RDWR); + g_display.last_stage = "registered"; + g_display.last_error = RT_EOK; - if (display_init(&g_display.lcd) != RT_EOK) { - rt_kprintf("display: auto-init failed\n"); - return -1; - } - - rt_kprintf("display: lcd/fb0 device ready, %ux%u RGB565\n", - g_display.info.width, g_display.info.height); + rt_kprintf("display: lcd/fb0 device registered\n"); return 0; } INIT_DEVICE_EXPORT(k230_display_init); diff --git a/bsp/k230/drivers/display/drv_display.h b/bsp/k230/drivers/display/drv_display.h index 3de9fd2cf2f..440a940e860 100644 --- a/bsp/k230/drivers/display/drv_display.h +++ b/bsp/k230/drivers/display/drv_display.h @@ -7,7 +7,7 @@ #define K230D_LCD_RESET_PIN 3 #define K230D_LCD_BACKLIGHT_PIN 5 -#define K230_DISPLAY_FB_ALIGN 64 +#define K230_DISPLAY_FB_ALIGN 4096 #define LCD_CTRL_BACKLIGHT_OFF 0 #define LCD_CTRL_BACKLIGHT_ON 1 diff --git a/bsp/k230/drivers/display/lib/vo_stubs.c b/bsp/k230/drivers/display/lib/vo_stubs.c index 73c6d7370d1..d3bf2f91eb7 100644 --- a/bsp/k230/drivers/display/lib/vo_stubs.c +++ b/bsp/k230/drivers/display/lib/vo_stubs.c @@ -3,6 +3,10 @@ #include #include +#ifndef VO_LOG_LEVEL +#define VO_LOG_LEVEL 3 +#endif + void cpu_ticks_delay_us(uint64_t us) { rt_hw_us_delay(us); @@ -12,6 +16,10 @@ void K_LOG(int level, int module, const char* fmt, ...) { char buf[256]; va_list args; + + if (level > VO_LOG_LEVEL) + return; + va_start(args, fmt); rt_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); diff --git a/bsp/k230/drivers/display/panels/mipi_st7701.c b/bsp/k230/drivers/display/panels/mipi_st7701.c index 8cbd6737b54..ea2cd8c5233 100644 --- a/bsp/k230/drivers/display/panels/mipi_st7701.c +++ b/bsp/k230/drivers/display/panels/mipi_st7701.c @@ -49,12 +49,13 @@ static int st7701_480x640_atk_init(const struct panel_desc* desc) 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13, 0x39, 0, 3, 0xE8, 0x00, 0x0E, 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00, - 0x05,20, 1, 0x11, + 0x05,200, 1, 0x11, 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13, 0x39,10, 3, 0xE8, 0x00, 0x0C, 0x39, 0, 3, 0xE8, 0x00, 0x00, 0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00, - 0x05,20, 1, 0x29, + 0x15, 0, 2, 0x3A, 0x50, + 0x05,50, 1, 0x29, }; /* clang-format on */ diff --git a/bsp/k230/drivers/display/vo/kd_dsi_reg.c b/bsp/k230/drivers/display/vo/kd_dsi_reg.c index 4dfef64e9dc..94b87f68a58 100644 --- a/bsp/k230/drivers/display/vo/kd_dsi_reg.c +++ b/bsp/k230/drivers/display/vo/kd_dsi_reg.c @@ -13,6 +13,9 @@ #define DSI_REG_DPI_VCID 0x00c #define DSI_REG_DPI_COLOR_CODING 0x010 #define DSI_REG_DPI_CFG_POL 0x014 +#define DSI_REG_DPI_LP_CMD_TIM 0x018 +#define DSI_REG_PCKHDL_CFG 0x02c +#define DSI_REG_GEN_VCID 0x030 #define DSI_REG_VID_MODE_CFG 0x038 #define DSI_REG_VID_PKT_SIZE 0x03c #define DSI_REG_VID_NUM_CHUNKS 0x040 @@ -29,9 +32,12 @@ #define DSI_REG_GEN_PLD_DATA 0x070 #define DSI_REG_CMD_PKT_STATUS 0x074 #define DSI_REG_TO_CNT_CFG 0x078 +#define DSI_REG_HS_RD_TO_CNT 0x080 #define DSI_REG_BTA_TO_CNT 0x08c -#define DSI_REG_PHY_TMR_CFG 0x098 -#define DSI_REG_PHY_TMR_LPCLK_CFG 0x09c +#define DSI_REG_LPCLK_CTRL 0x094 +#define DSI_REG_PHY_TMR_LPCLK_CFG 0x098 +#define DSI_REG_PHY_TMR_CFG 0x09c +#define DSI_REG_PHY_TMR_RD_CFG 0x0f4 #define DSI_REG_PHY_IF_CFG 0x0a4 #define DSI_REG_PHY_RSTZ 0x0a0 #define DSI_REG_PHY_STATUS 0x0b0 @@ -41,7 +47,11 @@ #define DSI_REG_INT_ST1 0x0c0 #define DSI_REG_INT_MSK0 0x0c4 #define DSI_REG_INT_MSK1 0x0c8 -#define DSI_REG_MODE_CFG 0x094 +#define DSI_REG_MODE_CFG 0x034 + +#define DSI_CMD_MODE_ALL_LP 0x010f7f00U +#define DSI_DPI_COLOR_RGB565 0x1U +#define DSI_DPI_BYTES_PER_PIXEL 2U #define DSI_PACKET_DCS_SHORT_WRITE0 0x05 #define DSI_PACKET_DCS_SHORT_WRITE1 0x15 @@ -97,11 +107,89 @@ struct kd_dsi_config { uint8_t lp_div; }; +struct dsi_dphy_timing { + k_u32 lane_mbps; + k_u16 clk_lp2hs; + k_u16 clk_hs2lp; + k_u16 data_lp2hs; + k_u16 data_hs2lp; +}; + +static const k_u32 minimum_lbccs[] = {10U, 5U, 4U, 3U}; + +static const struct dsi_dphy_timing dphy_timings[] = { + { 80U, 21U, 17U, 15U, 10U}, + { 90U, 23U, 17U, 16U, 10U}, + { 100U, 22U, 17U, 16U, 10U}, + { 110U, 25U, 18U, 17U, 11U}, + { 120U, 26U, 20U, 18U, 11U}, + { 130U, 27U, 19U, 19U, 11U}, + { 140U, 27U, 19U, 19U, 11U}, + { 150U, 28U, 20U, 20U, 12U}, + { 160U, 30U, 21U, 22U, 13U}, + { 170U, 30U, 21U, 23U, 13U}, + { 180U, 31U, 21U, 23U, 13U}, + { 190U, 32U, 22U, 24U, 13U}, + { 205U, 35U, 22U, 25U, 13U}, + { 220U, 37U, 26U, 27U, 15U}, + { 235U, 38U, 28U, 27U, 16U}, + { 250U, 41U, 29U, 30U, 17U}, + { 275U, 43U, 29U, 32U, 18U}, + { 300U, 45U, 32U, 35U, 19U}, + { 325U, 48U, 33U, 36U, 18U}, + { 350U, 51U, 35U, 40U, 20U}, + { 400U, 59U, 37U, 44U, 21U}, + { 450U, 65U, 40U, 49U, 23U}, + { 500U, 71U, 41U, 54U, 24U}, + { 550U, 77U, 44U, 57U, 26U}, + { 600U, 82U, 46U, 64U, 27U}, + { 650U, 87U, 48U, 67U, 28U}, + { 700U, 94U, 52U, 71U, 29U}, + { 750U, 99U, 52U, 75U, 31U}, + { 800U, 105U, 55U, 82U, 32U}, + { 850U, 110U, 58U, 85U, 32U}, + { 900U, 115U, 58U, 88U, 35U}, + { 950U, 120U, 62U, 93U, 36U}, + {1000U, 128U, 63U, 99U, 38U}, + {1050U, 132U, 65U, 102U, 38U}, + {1100U, 138U, 67U, 106U, 39U}, + {1150U, 146U, 69U, 112U, 42U}, + {1200U, 151U, 71U, 117U, 43U}, + {1250U, 153U, 74U, 120U, 45U}, + {1300U, 160U, 73U, 124U, 46U}, + {1350U, 165U, 76U, 130U, 47U}, + {1400U, 172U, 78U, 134U, 49U}, + {1450U, 177U, 80U, 138U, 49U}, + {1500U, 183U, 81U, 143U, 52U}, + {1550U, 191U, 84U, 147U, 52U}, + {1600U, 194U, 85U, 152U, 52U}, + {1650U, 201U, 86U, 155U, 53U}, + {1700U, 208U, 88U, 161U, 53U}, + {1750U, 212U, 89U, 165U, 53U}, + {1800U, 220U, 90U, 171U, 54U}, + {1850U, 223U, 92U, 175U, 54U}, + {1900U, 231U, 91U, 180U, 55U}, + {1950U, 236U, 95U, 185U, 56U}, + {2000U, 243U, 97U, 190U, 56U}, + {2050U, 248U, 99U, 194U, 58U}, + {2100U, 252U, 100U, 199U, 59U}, + {2150U, 259U, 102U, 204U, 61U}, + {2200U, 266U, 105U, 210U, 62U}, + {2250U, 269U, 109U, 213U, 63U}, + {2300U, 272U, 109U, 217U, 65U}, + {2350U, 281U, 112U, 225U, 66U}, + {2400U, 283U, 115U, 226U, 66U}, + {2450U, 282U, 115U, 226U, 67U}, + {2500U, 281U, 118U, 227U, 67U}, +}; + extern void K_LOG(int level, int module, const char *fmt, ...); extern void *memcpy(void *dst, const void *src, unsigned long count); static k_u32 curren_video_mode; +static void dsi_video_mode_config(k_u32 mode); + static k_u32 dsi_lane_count(k_vo_dsi_lane_num lanes) { switch (lanes) { @@ -180,6 +268,72 @@ static k_u32 dsi_read(k_u32 offset) return value; } +static k_u32 dsi_phy_read(k_u32 offset) +{ + uintptr_t base = phy_base_addr(); + k_u32 value = 0; + + if (base != 0U) { + value = raw_readl((void *)(base + offset)); + DSI_FENCE_IR(); + } + + return value; +} + +void dwc_dsi_debug_dump(void) +{ + rt_kprintf("DSI base=%p phy=%p mode=%u\n", + display_remap ? display_remap->dsi_base : RT_NULL, + display_remap ? display_remap->phy_base : RT_NULL, + curren_video_mode); + rt_kprintf("DSI pwr=0x%08x clk=0x%08x mode=0x%08x vid_mode=0x%08x cmd_mode=0x%08x lpclk=0x%08x dpi_lp=0x%08x dpi_color=0x%08x\n", + dsi_read(DSI_REG_PWR_UP), dsi_read(DSI_REG_CLKMGR_CFG), + dsi_read(DSI_REG_MODE_CFG), dsi_read(DSI_REG_VID_MODE_CFG), + dsi_read(DSI_REG_CMD_MODE_CFG), dsi_read(DSI_REG_LPCLK_CTRL), + dsi_read(DSI_REG_DPI_LP_CMD_TIM), + dsi_read(DSI_REG_DPI_COLOR_CODING)); + rt_kprintf("DSI phy_if=0x%08x phy_rstz=0x%08x phy_status=0x%08x hs_rd_to=0x%08x phy_tmr_rd=0x%08x\n", + dsi_read(DSI_REG_PHY_IF_CFG), dsi_read(DSI_REG_PHY_RSTZ), + dsi_read(DSI_REG_PHY_STATUS), dsi_read(DSI_REG_HS_RD_TO_CNT), + dsi_read(DSI_REG_PHY_TMR_RD_CFG)); + rt_kprintf("DSI pkt=%u chunks=%u null=%u hsa=%u hbp=%u hline=%u vsa=%u vbp=%u vfp=%u vact=%u\n", + dsi_read(DSI_REG_VID_PKT_SIZE), dsi_read(DSI_REG_VID_NUM_CHUNKS), + dsi_read(DSI_REG_VID_NULL_SIZE), dsi_read(DSI_REG_VID_HSA_TIME), + dsi_read(DSI_REG_VID_HBP_TIME), dsi_read(DSI_REG_VID_HLINE_TIME), + dsi_read(DSI_REG_VID_VSA_LINES), dsi_read(DSI_REG_VID_VBP_LINES), + dsi_read(DSI_REG_VID_VFP_LINES), dsi_read(DSI_REG_VID_VACTIVE_LINES)); + rt_kprintf("DSI status=0x%08x msk0=0x%08x msk1=0x%08x\n", + dsi_read(DSI_REG_CMD_PKT_STATUS), + dsi_read(DSI_REG_INT_MSK0), dsi_read(DSI_REG_INT_MSK1)); + rt_kprintf("DSI_PHY 0x00=0x%08x 0x04=0x%08x 0x08=0x%08x 0x0c=0x%08x 0x10=0x%08x 0x14=0x%08x 0x18=0x%08x\n", + dsi_phy_read(0x00), dsi_phy_read(0x04), dsi_phy_read(0x08), + dsi_phy_read(0x0c), dsi_phy_read(0x10), dsi_phy_read(0x14), + dsi_phy_read(0x18)); +} + +void dwc_dsi_set_dpi_color_coding(k_u32 coding) +{ + dsi_write(coding & 0x7U, DSI_REG_DPI_COLOR_CODING); +} + +void dwc_dsi_set_video_scan(k_u32 dpi_color, k_u32 pkt_size, + k_u32 hsa, k_u32 hbp, k_u32 hline, + k_u32 video_mode) +{ + dsi_write(0, DSI_REG_PWR_UP); + dsi_write(dpi_color & 0x7U, DSI_REG_DPI_COLOR_CODING); + dsi_write(pkt_size & 0x3fffU, DSI_REG_VID_PKT_SIZE); + dsi_write(hsa, DSI_REG_VID_HSA_TIME); + dsi_write(hbp, DSI_REG_VID_HBP_TIME); + dsi_write(hline, DSI_REG_VID_HLINE_TIME); + curren_video_mode = video_mode; + dsi_write(0, DSI_REG_MODE_CFG); + dsi_video_mode_config(video_mode); + dsi_write(1, DSI_REG_LPCLK_CTRL); + dsi_write(1, DSI_REG_PWR_UP); +} + static void phy_update_bits(k_u32 offset, k_u32 mask, k_u32 value) { uintptr_t base = phy_base_addr(); @@ -242,6 +396,23 @@ static int wait_status_set(k_u32 mask) return -1; } +static void dsi_dump_packet_error(k_u8 type, k_u32 header, k_u32 status) +{ + K_LOG(3, KD_DSI_MODULE_ID, + "%s: packet 0x%x timeout, header 0x%x status 0x%x\n", + __func__, type, header, status); + rt_kprintf("DSI packet error: type=0x%02x header=0x%08x status=0x%08x\n", + type, header, status); + rt_kprintf("DSI packet regs: pwr=0x%08x mode=0x%08x cmd=0x%08x vid=0x%08x lpclk=0x%08x dpi_lp=0x%08x phy_rstz=0x%08x phy_status=0x%08x\n", + dsi_read(DSI_REG_PWR_UP), dsi_read(DSI_REG_MODE_CFG), + dsi_read(DSI_REG_CMD_MODE_CFG), dsi_read(DSI_REG_VID_MODE_CFG), + dsi_read(DSI_REG_LPCLK_CTRL), dsi_read(DSI_REG_DPI_LP_CMD_TIM), + dsi_read(DSI_REG_PHY_RSTZ), dsi_read(DSI_REG_PHY_STATUS)); + rt_kprintf("DSI packet ints: int0=0x%08x int1=0x%08x msk0=0x%08x msk1=0x%08x\n", + dsi_read(DSI_REG_INT_ST0), dsi_read(DSI_REG_INT_ST1), + dsi_read(DSI_REG_INT_MSK0), dsi_read(DSI_REG_INT_MSK1)); +} + static int write_payload(const uint8_t *payload, uint32_t len) { uint32_t offset = 0; @@ -298,19 +469,31 @@ static int read_payload(uint8_t *data, uint32_t len) return (int)offset; } -static void dsi_message_config(uint8_t channel, uint8_t ack, uint8_t lp) +static void dsi_message_config(uint8_t channel, uint8_t lp, uint8_t ack) { k_u32 value = 0; + k_u32 video_mode; + + (void)channel; + + dsi_write(0x00100004U, DSI_REG_DPI_LP_CMD_TIM); if (ack != 0U) { - value |= 0x1U; + value |= 0x2U; } if (lp != 0U) { - value |= 0x70fU; + value |= DSI_CMD_MODE_ALL_LP; } - value |= ((k_u32)channel & 0x3U) << 8; dsi_write(value, DSI_REG_CMD_MODE_CFG); + + video_mode = dsi_read(DSI_REG_VID_MODE_CFG); + if (lp != 0U) { + video_mode |= 0x00008000U; + } else { + video_mode &= ~0x00008000U; + } + dsi_write(video_mode, DSI_REG_VID_MODE_CFG); } static void dsi_video_mode_config(k_u32 mode) @@ -331,13 +514,13 @@ static void dsi_set_mode(uint8_t enable, k_u32 video_mode) dsi_write(0, DSI_REG_PWR_UP); if (enable == 0U) { dsi_write(1, DSI_REG_MODE_CFG); - dsi_write(0x010f7f00U, DSI_REG_CMD_MODE_CFG); + dsi_write(DSI_CMD_MODE_ALL_LP, DSI_REG_CMD_MODE_CFG); dsi_write(0, DSI_REG_VID_MODE_CFG); } else { dsi_write(0, DSI_REG_MODE_CFG); dsi_video_mode_config(video_mode); } - dsi_write(1, DSI_REG_MODE_CFG); + dsi_write(1, DSI_REG_LPCLK_CTRL); dsi_write(1, DSI_REG_PWR_UP); } @@ -368,14 +551,18 @@ void k230_dsi_write_phy_reg(uint8_t addr, uint8_t value) dsi_write(0, DSI_REG_PHY_TST_CTRL0); } -void k230_dsi_phy_pll_config(uint32_t n, uint32_t m, uint8_t hs_freq) +void k230_dsi_phy_pll_config(uint32_t m, uint32_t n, uint8_t voc) { phy_update_bits(0x10, 0x00000200U, 0x00000200U); phy_update_bits(0x10, 0x00000200U, 0); phy_update_bits(0x10, 0x00000003U, 0x00000001U); phy_update_bits(0x08, 0x07fe0000U, (n & 0x3ffU) << 17); phy_update_bits(0x08, 0x78000000U, (m & 0x0fU) << 27); - phy_update_bits(0x10, 0x0001f800U, ((k_u32)hs_freq & 0x3fU) << 11); + phy_update_bits(0x10, 0x0001f800U, ((k_u32)voc & 0x3fU) << 11); + phy_update_bits(0x08, 0x0000007fU, 0x00000010U); + phy_update_bits(0x08, 0x00000300U, 0); + phy_update_bits(0x08, 0x0001f800U, 0); + phy_update_bits(0x10, 0x000001f8U, 0x00000040U); k230_dsi_write_phy_reg(0x14, 0x02); k230_dsi_write_phy_reg(0x15, 0x60); @@ -387,7 +574,7 @@ void k230_dsi_phy_pll_config(uint32_t n, uint32_t m, uint8_t hs_freq) phy_update_bits(0x10, 0x00000400U, 0); } -void k230_dsi_phy0_config(uint32_t n, uint32_t m, uint8_t hs_freq, uint8_t lane_num) +void k230_dsi_phy0_config(uint32_t m, uint32_t n, uint8_t voc, uint8_t hs_freq) { uintptr_t base = phy_base_addr(); @@ -401,7 +588,7 @@ void k230_dsi_phy0_config(uint32_t n, uint32_t m, uint8_t hs_freq, uint8_t lane_ dsi_write(0, DSI_REG_PHY_TST_CTRL0); k230_dsi_write_phy_reg(0x0c, 0x03); - k230_dsi_write_phy_reg(0x44, lane_num); + k230_dsi_write_phy_reg(0x44, hs_freq); k230_dsi_write_phy_reg(0xa0, 0x40); k230_dsi_write_phy_reg(0xa4, 0x11); k230_dsi_write_phy_reg(0xa4, 0x85); @@ -410,7 +597,7 @@ void k230_dsi_phy0_config(uint32_t n, uint32_t m, uint8_t hs_freq, uint8_t lane_ k230_dsi_write_phy_reg(0x4a, 0x40); phy_update_bits(0x00, 0x00003f3cU, 0x000028a0U); - k230_dsi_phy_pll_config(n, m, hs_freq); + k230_dsi_phy_pll_config(m, n, voc); if (base != 0U) { DSI_FENCE_WO(); @@ -420,9 +607,10 @@ void k230_dsi_phy0_config(uint32_t n, uint32_t m, uint8_t hs_freq, uint8_t lane_ dsi_write(0x0c, DSI_REG_PHY_RSTZ); } -void k230_dsi_phy1_config(uint8_t lane_num) +void k230_dsi_phy1_config(uint8_t hs_freq) { uintptr_t base = phy_base_addr(); + int retry = 10; if (base != 0U) { DSI_FENCE_WO(); @@ -433,7 +621,104 @@ void k230_dsi_phy1_config(uint8_t lane_num) rt_thread_mdelay(1); dsi_write(0, DSI_REG_PHY_TST_CTRL0); k230_dsi_write_phy_reg(0x0c, 0); - k230_dsi_write_phy_reg(0x44, lane_num); + k230_dsi_write_phy_reg(0x44, hs_freq); + k230_dsi_write_phy_reg(0x30, 0xff); + k230_dsi_write_phy_reg(0xa0, 0x40); + k230_dsi_write_phy_reg(0xa4, 0x11); + k230_dsi_write_phy_reg(0xa4, 0x85); + k230_dsi_write_phy_reg(0xa3, 0x01); + k230_dsi_write_phy_reg(0x1f, 0x01); + k230_dsi_write_phy_reg(0x4a, 0x40); + + if (base != 0U) { + k_u32 value = raw_readl((void *)base); + + DSI_FENCE_IR(); + value &= ~0x000000fcU; + value |= 0x000000a0U; + value &= ~0x00003f00U; + value |= 0x00002800U; + DSI_FENCE_WO(); + raw_writel(value, (void *)base); + } + + dsi_write(4, DSI_REG_PHY_RSTZ); + dsi_write(0x0d, DSI_REG_PHY_RSTZ); + dsi_write(0x0f, DSI_REG_PHY_RSTZ); + k230_dsi_write_phy_reg(0x03, 0x80); + + do { + if (dsi_read(DSI_REG_PHY_TST_CTRL1) == 0x580U) { + return; + } + k230_dsi_write_phy_reg(0x03, 0x80); + rt_thread_mdelay(1); + } while (--retry > 0); + + K_LOG(7, KD_DSI_MODULE_ID, "%s: test interface ready status 0x%x\n", + __func__, dsi_read(DSI_REG_PHY_TST_CTRL1)); +} + +static k_u32 dsi_phy_stopstate_mask(k_u32 lane_num) +{ + k_u32 mask = 0x0dU; + + for (k_u32 i = 0; i < lane_num; i++) { + if (i == 0U) { + mask |= 0x30U; + } else if (i == 1U) { + mask |= 0x180U; + } else if (i == 2U) { + mask |= 0x600U; + } else if (i == 3U) { + mask |= 0x1800U; + } + } + + return mask; +} + +static void dsi_wait_phy_status(k_u32 mask, const char *stage) +{ + k_u32 status = 0; + + for (k_u32 timeout = 50000U; timeout != 0U; timeout -= DSI_WAIT_US) { + status = dsi_read(DSI_REG_PHY_STATUS); + if ((status & mask) == mask) { + return; + } + rt_hw_us_delay(DSI_WAIT_US); + } + + K_LOG(3, KD_DSI_MODULE_ID, "%s: %s timeout, status 0x%x mask 0x%x\n", + __func__, stage, status, mask); +} + +void k230_dsi_phy_config(k_u32 lane_sel, k_u32 m, k_u32 n, k_u8 voc, + k_u8 hs_freq) +{ + uintptr_t base = phy_base_addr(); + k_u32 mask = dsi_phy_stopstate_mask(lane_sel); + + k230_dsi_phy0_config(m, n, voc, hs_freq); + k230_dsi_phy1_config(hs_freq); + + if (base != 0U) { + DSI_FENCE_WO(); + raw_writel(0, (void *)(base + 0x04)); + } + + dsi_write(0x0d, DSI_REG_PHY_RSTZ); + dsi_write(0x0f, DSI_REG_PHY_RSTZ); + dsi_wait_phy_status(mask, "stop-state"); + rt_thread_mdelay(1); + + if (base != 0U) { + DSI_FENCE_WO(); + raw_writel(0x00400000U, (void *)(base + 0x04)); + } + + dsi_wait_phy_status(mask, "external stop-state"); } int dwc_dsi_send_packet(k_u8 type, k_u8 channel, const void *payload, @@ -468,8 +753,7 @@ int dwc_dsi_send_packet(k_u8 type, k_u8 channel, const void *payload, dsi_write(header, DSI_REG_GEN_HDR); if (wait_status_set(0x5U) != 0) { - K_LOG(3, KD_DSI_MODULE_ID, "%s: packet 0x%x timeout, status 0x%x\n", - __func__, type, dsi_read(DSI_REG_CMD_PKT_STATUS)); + dsi_dump_packet_error(type, header, dsi_read(DSI_REG_CMD_PKT_STATUS)); return -1; } @@ -563,13 +847,101 @@ void dwc_dsi_dump_config(const k_vo_dsi_config *config) config->phy.hs_freq); } +static k_u32 dsi_get_minimum_lbcc(k_u32 lane_count) +{ + if (lane_count == 0U || lane_count > 4U) { + return minimum_lbccs[0]; + } + + return minimum_lbccs[lane_count - 1U]; +} + +static k_u32 dsi_get_hcomponent_lbcc(const k_vo_dsi_config *config, + k_u32 component) +{ + uint64_t lbcc; + uint64_t rem; + k_u32 lane_count = dsi_lane_count(config->lanes); + k_u32 minimum; + + if (config->video_mode == K_BURST_MODE) { + lbcc = ((uint64_t)component * (uint64_t)(config->phy.datarate / 1000U)) >> 3; + } else { + lbcc = ((uint64_t)component * (uint64_t)config->timing->pclk_khz * + DSI_DPI_BYTES_PER_PIXEL) / + (uint64_t)(lane_count * 8U); + } + + rem = lbcc % (uint64_t)config->timing->pclk_khz; + lbcc = lbcc / (uint64_t)config->timing->pclk_khz; + if (rem != 0U) { + lbcc++; + } + + minimum = dsi_get_minimum_lbcc(lane_count); + if (lbcc < minimum) { + lbcc = minimum; + } + + return (k_u32)lbcc; +} + +static int dsi_get_phy_timings(k_u32 lane_mbps, struct dsi_dphy_timing *timing) +{ + k_u32 best_delta = 0xffffffffU; + int best = -1; + + for (k_u32 i = 0; i < sizeof(dphy_timings) / sizeof(dphy_timings[0]); i++) { + k_u32 table_mbps = dphy_timings[i].lane_mbps; + k_u32 delta = table_mbps > lane_mbps ? table_mbps - lane_mbps : + lane_mbps - table_mbps; + + if (delta < best_delta) { + best_delta = delta; + best = (int)i; + } + } + + if (best < 0) { + return -1; + } + + *timing = dphy_timings[best]; + return 0; +} + +static void dsi_wait_phy_bit(k_u32 bit, const char *stage) +{ + k_u32 status = 0; + + for (k_u32 timeout = 10000U; timeout != 0U; timeout -= DSI_WAIT_US) { + status = dsi_read(DSI_REG_PHY_STATUS); + if ((status & bit) != 0U) { + return; + } + rt_hw_us_delay(DSI_WAIT_US); + } + + K_LOG(3, KD_DSI_MODULE_ID, "%s: %s timeout, status 0x%x\n", + __func__, stage, status); +} + void dwc_dsi_init(k_vo_dsi_config *config) { struct kd_dsi_resolution res; + struct dsi_dphy_timing phy_timing; k_u32 lane_num; + k_u32 lane_mbps; k_u32 byte_clk; + k_u32 lane_byte_mbps; k_u32 tx_escape_clk_division; - k_u32 hline; + k_u32 timeout_clock_division; + k_u32 hline_pixels; + k_u32 hsa_lbcc; + k_u32 hbp_lbcc; + k_u32 hline_lbcc; + k_u32 phy_tmr_cfg; + k_u32 phy_tmr_lpclk_cfg; if (config == NULL || config->timing == NULL) { K_LOG(3, KD_DSI_MODULE_ID, "%s: invalid dsi config\n", __func__); @@ -596,11 +968,16 @@ void dwc_dsi_init(k_vo_dsi_config *config) __func__, config->lanes); return; } - byte_clk = res.phyclk / 8000000U; + + lane_mbps = config->phy.datarate / 1000000U; + lane_byte_mbps = lane_mbps / 8U; + byte_clk = lane_byte_mbps; if (byte_clk == 0U) { byte_clk = 1U; } - tx_escape_clk_division = byte_clk / (config->lp_speed_mhz == 0U ? 20U : config->lp_speed_mhz); + + tx_escape_clk_division = (lane_byte_mbps + (config->lp_speed_mhz == 0U ? 20U : config->lp_speed_mhz) - 1U) / + (config->lp_speed_mhz == 0U ? 20U : config->lp_speed_mhz); if (tx_escape_clk_division == 0U) { tx_escape_clk_division = 1U; } @@ -608,47 +985,90 @@ void dwc_dsi_init(k_vo_dsi_config *config) tx_escape_clk_division = 255U; } + timeout_clock_division = (lane_byte_mbps + 1U - 1U) / 1U; + if (timeout_clock_division == 0U) { + timeout_clock_division = 1U; + } + if (timeout_clock_division > 255U) { + timeout_clock_division = 255U; + } + + if (tx_escape_clk_division < 1U || tx_escape_clk_division > 20U) { + K_LOG(4, KD_DSI_MODULE_ID, + "%s: unusual escape clock divider %u for lane_mbps=%u\n", + __func__, tx_escape_clk_division, lane_mbps); + } + + if (dsi_get_phy_timings(lane_mbps, &phy_timing) != 0) { + phy_timing.clk_lp2hs = 0x73U; + phy_timing.clk_hs2lp = 0x3aU; + phy_timing.data_lp2hs = 0xceU; + phy_timing.data_hs2lp = 0x23U; + K_LOG(4, KD_DSI_MODULE_ID, + "%s: using default dphy timings for lane_mbps=%u\n", + __func__, lane_mbps); + } + phy_timing.data_lp2hs += phy_timing.clk_lp2hs; + phy_tmr_cfg = (((k_u32)phy_timing.data_hs2lp & 0x3ffU) << 16) | + ((k_u32)phy_timing.data_lp2hs & 0x3ffU); + phy_tmr_lpclk_cfg = (((k_u32)phy_timing.clk_hs2lp & 0x3ffU) << 16) | + ((k_u32)phy_timing.clk_lp2hs & 0x3ffU); + + hline_pixels = res.hdisplay + res.hsync_len + res.hback_porch + res.hfront_porch; + hsa_lbcc = dsi_get_hcomponent_lbcc(config, res.hsync_len); + hbp_lbcc = dsi_get_hcomponent_lbcc(config, res.hback_porch); + hline_lbcc = dsi_get_hcomponent_lbcc(config, hline_pixels); + curren_video_mode = config->video_mode; dsi_write(0, DSI_REG_PWR_UP); - dsi_write(((tx_escape_clk_division & 0xffU) << 8) | (byte_clk & 0xffU), + dsi_write(((timeout_clock_division & 0xffU) << 8) | + (tx_escape_clk_division & 0xffU), DSI_REG_CLKMGR_CFG); dsi_write(config->vc_id & 0x3U, DSI_REG_DPI_VCID); - dsi_write(0x5U, DSI_REG_DPI_COLOR_CODING); + dsi_write((config->vc_id & 0x3U) | ((config->vc_id & 0x3U) << 8), + DSI_REG_GEN_VCID); + dsi_write(DSI_DPI_COLOR_RGB565, DSI_REG_DPI_COLOR_CODING); dsi_write(0, DSI_REG_DPI_CFG_POL); + dsi_write(0x1cU, DSI_REG_PCKHDL_CFG); dsi_video_mode_config(config->video_mode); dsi_write(res.hdisplay & 0x3fffU, DSI_REG_VID_PKT_SIZE); dsi_write(0, DSI_REG_VID_NUM_CHUNKS); dsi_write(0, DSI_REG_VID_NULL_SIZE); - hline = res.hdisplay + res.hsync_len + res.hback_porch + res.hfront_porch; - dsi_write(res.hsync_len, DSI_REG_VID_HSA_TIME); - dsi_write(res.hback_porch, DSI_REG_VID_HBP_TIME); - dsi_write(hline, DSI_REG_VID_HLINE_TIME); + dsi_write(0x1388U, DSI_REG_TO_CNT_CFG); + dsi_write(0x0d00U, DSI_REG_BTA_TO_CNT); + dsi_write(0x1388U, DSI_REG_HS_RD_TO_CNT); + dsi_write(1, DSI_REG_MODE_CFG); + dsi_write(hsa_lbcc, DSI_REG_VID_HSA_TIME); + dsi_write(hbp_lbcc, DSI_REG_VID_HBP_TIME); + dsi_write(hline_lbcc, DSI_REG_VID_HLINE_TIME); dsi_write(res.vsync_len, DSI_REG_VID_VSA_LINES); dsi_write(res.vback_porch, DSI_REG_VID_VBP_LINES); dsi_write(res.vfront_porch, DSI_REG_VID_VFP_LINES); dsi_write(res.vdisplay, DSI_REG_VID_VACTIVE_LINES); - - dsi_write(0x1388U, DSI_REG_TO_CNT_CFG); - dsi_write(0x0d00U, DSI_REG_BTA_TO_CNT); - dsi_write(0x2710U, DSI_REG_PHY_TMR_CFG); - dsi_write(0x0073003aU, DSI_REG_PHY_TMR_LPCLK_CFG); + dsi_write(0, DSI_REG_PHY_RSTZ); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); + dsi_write(1, DSI_REG_PHY_TST_CTRL0); + dsi_write(0, DSI_REG_PHY_TST_CTRL0); + dsi_write(phy_tmr_cfg, DSI_REG_PHY_TMR_CFG); + dsi_write(0x2710U, DSI_REG_PHY_TMR_RD_CFG); + dsi_write(phy_tmr_lpclk_cfg, DSI_REG_PHY_TMR_LPCLK_CFG); dsi_write(0x2800U | ((lane_num - 1U) & 0x3U), DSI_REG_PHY_IF_CFG); + dsi_read(DSI_REG_INT_ST0); + dsi_read(DSI_REG_INT_ST1); dsi_write(0xffffffffU, DSI_REG_INT_MSK0); dsi_write(0xffffffffU, DSI_REG_INT_MSK1); - k230_dsi_phy0_config(config->phy.n, config->phy.m, - (uint8_t)config->phy.hs_freq, (uint8_t)lane_num); + k230_dsi_phy_config((k_u32)config->lanes, config->phy.m, config->phy.n, + (uint8_t)config->phy.voc, + (uint8_t)config->phy.hs_freq); dsi_write(0x0f, DSI_REG_PHY_RSTZ); - if ((dsi_read(DSI_REG_PHY_STATUS) & 0x1U) == 0U) { - K_LOG(3, KD_DSI_MODULE_ID, "%s: phy lock timeout\n", __func__); - } - if ((dsi_read(DSI_REG_PHY_STATUS) & 0x4U) == 0U) { - K_LOG(3, KD_DSI_MODULE_ID, "%s: phy stop-state timeout\n", __func__); - } + + dsi_wait_phy_bit(0x1U, "phy lock"); + dsi_wait_phy_bit(0x4U, "clk lane stop-state"); wait_for_two_frames(&res); dsi_set_mode(0, 0); diff --git a/bsp/k230/drivers/display/vo/kd_dsi_reg.h b/bsp/k230/drivers/display/vo/kd_dsi_reg.h index e57e02b85e2..485de2f2944 100644 --- a/bsp/k230/drivers/display/vo/kd_dsi_reg.h +++ b/bsp/k230/drivers/display/vo/kd_dsi_reg.h @@ -8,9 +8,11 @@ extern "C" { #endif void k230_dsi_write_phy_reg(k_u8 addr, k_u8 value); -void k230_dsi_phy_pll_config(k_u32 n, k_u32 m, k_u8 hs_freq); -void k230_dsi_phy0_config(k_u32 n, k_u32 m, k_u8 hs_freq, k_u8 lane_num); -void k230_dsi_phy1_config(k_u8 lane_num); +void k230_dsi_phy_pll_config(k_u32 m, k_u32 n, k_u8 voc); +void k230_dsi_phy0_config(k_u32 m, k_u32 n, k_u8 voc, k_u8 hs_freq); +void k230_dsi_phy1_config(k_u8 hs_freq); +void k230_dsi_phy_config(k_u32 lane_num, k_u32 m, k_u32 n, k_u8 voc, + k_u8 hs_freq); int dwc_dsi_send_packet(k_u8 type, k_u8 channel, const void *payload, k_u32 payload_len, k_u8 read); @@ -24,6 +26,11 @@ void dwc_dsi_init(k_vo_dsi_config *config); int dwc_dsi_enable(void); int dwc_dsi_disable(void); void dwc_dsi_dump_config(const k_vo_dsi_config *config); +void dwc_dsi_debug_dump(void); +void dwc_dsi_set_dpi_color_coding(k_u32 coding); +void dwc_dsi_set_video_scan(k_u32 dpi_color, k_u32 pkt_size, + k_u32 hsa, k_u32 hbp, k_u32 hline, + k_u32 video_mode); #ifdef __cplusplus } diff --git a/bsp/k230/drivers/display/vo/kd_vo_reg.c b/bsp/k230/drivers/display/vo/kd_vo_reg.c index f74652d6139..f571b988b9b 100644 --- a/bsp/k230/drivers/display/vo/kd_vo_reg.c +++ b/bsp/k230/drivers/display/vo/kd_vo_reg.c @@ -37,6 +37,7 @@ #define VO_REG_MIX_PRIORITY0 0x3cc #define VO_REG_MIX_PRIORITY1 0x950 #define VO_REG_LAYER_ENABLE 0x380 +#define VO_REG_LOAD_CTL 0x004 #define VO_REG_INTR_FRAME 0x3e0 #define VO_REG_INTR_VTTH 0x3e4 #define VO_REG_INTR_CLEAR0 0x3d4 @@ -44,6 +45,35 @@ #define VO_REG_INTR_MASK0 0x3e8 #define VO_REG_USER_SYNC 0x780 +#define VO_MIX_ENABLE_SDK 0x000000ffU + +#define VO_OSD_COUNT 4U +#define VO_OSD_INFO 0x00 +#define VO_OSD_SIZE 0x04 +#define VO_OSD_VLU_ADDR0 0x08 +#define VO_OSD_ALP_ADDR0 0x0c +#define VO_OSD_VLU_ADDR1 0x10 +#define VO_OSD_ALP_ADDR1 0x14 +#define VO_OSD_DMA_CTRL 0x18 +#define VO_OSD_STRIDE 0x1c +#define VO_OSD_ADDR_SEL_MODE 0x20 + +#define VO_OSD_FORMAT_RGB565 0x02 + +struct vo_osd_plane { + k_u32 offset; + k_u32 enable_bit; + k_u32 xctl; + k_u32 yctl; +}; + +static const struct vo_osd_plane vo_osd_planes[VO_OSD_COUNT] = { + {0x280, 4, 0x0e8, 0x0ec}, + {0x2c0, 5, 0x0f0, 0x0f4}, + {0x300, 6, 0x0f8, 0x0fc}, + {0x850, 7, 0x820, 0x824}, +}; + #define VO_SYS_RESET_OFFSET 0x090 #define VO_PIXCLK_REG_OFFSET 0x078 #define VO_TIMESTAMP_CTRL_OFFSET 0x000 @@ -118,6 +148,16 @@ static void vo_write(k_u32 value, k_u32 offset) __raw_writel(value, (void *)(vo_base_addr() + offset)); } +static k_u32 vo_read(k_u32 offset) +{ + k_u32 value; + + value = __raw_readl((void *)(vo_base_addr() + offset)); + VO_FENCE_IR(); + + return value; +} + void kd_vo_set_pixclk(k_u32 div) { uintptr_t addr = clock_base_addr() + VO_PIXCLK_REG_OFFSET; @@ -304,6 +344,206 @@ void kd_vo_set_background(k_u32 rgb888) yuv = ((cr & 0xffU) << 16) | ((cb & 0xffU) << 8) | (y & 0xffU); vo_write(yuv, VO_REG_BG_COLOR); + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_set_background_yuv(k_u32 yuv) +{ + vo_write(yuv, VO_REG_BG_COLOR); + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_set_osd_rgb565_framebuffer(k_u32 osd, k_u64 paddr, k_u32 width, k_u32 height, k_u32 pitch) +{ + kd_vo_set_osd_rgb565_framebuffer_ex(osd, paddr, paddr, width, height, pitch, + 0x0000007fU, 0x00000100U); +} + +void kd_vo_set_osd_rgb565_framebuffer_ex(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 pitch, + k_u32 dma_ctrl, k_u32 addr_sel) +{ + k_u32 stride; + + if (pitch == 0) + return; + + /* + * The K230 SDK passes OSD stride in 64-bit words. For RGB565 this is + * width * 2 / 8, which is equivalent to pitch / 8. + */ + stride = pitch / 8U; + kd_vo_set_osd_rgb565_framebuffer_raw(osd, paddr, alpha_paddr, width, height, + stride, dma_ctrl, addr_sel); +} + +void kd_vo_set_osd_rgb565_framebuffer_raw(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 stride_reg, + k_u32 dma_ctrl, k_u32 addr_sel) +{ + kd_vo_set_osd_rgb565_framebuffer_format_raw(osd, paddr, alpha_paddr, + width, height, stride_reg, + VO_OSD_FORMAT_RGB565, + dma_ctrl, addr_sel); +} + +void kd_vo_set_osd_rgb565_framebuffer_format_raw(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 stride_reg, + k_u32 info, k_u32 dma_ctrl, k_u32 addr_sel) +{ + k_u32 base; + const struct vo_osd_plane *plane; + k_u32 start_x; + k_u32 start_y; + k_u32 value; + + if (osd >= VO_OSD_COUNT || paddr == 0 || width == 0 || height == 0) + return; + + plane = &vo_osd_planes[osd]; + base = (k_u32)paddr; + (void)alpha_paddr; + + vo_write(info, plane->offset + VO_OSD_INFO); + vo_write(width | (height << 16), plane->offset + VO_OSD_SIZE); + + start_x = vo_read(VO_REG_ACTIVE_H) & 0x1fffU; + start_y = vo_read(VO_REG_ACTIVE_V) & 0x1fffU; + vo_write(((start_x + width - 1U) << 16) | start_x, plane->xctl); + vo_write(((start_y + height - 1U) << 16) | start_y, plane->yctl); + + vo_write(base, plane->offset + VO_OSD_VLU_ADDR0); + vo_write(base, plane->offset + VO_OSD_VLU_ADDR1); + vo_write(base, plane->offset + VO_OSD_ALP_ADDR0); + vo_write(base, plane->offset + VO_OSD_ALP_ADDR1); + vo_write(stride_reg, plane->offset + VO_OSD_STRIDE); + vo_write(dma_ctrl, plane->offset + VO_OSD_DMA_CTRL); + vo_write(addr_sel, plane->offset + VO_OSD_ADDR_SEL_MODE); + + value = vo_read(VO_REG_LAYER_CFG_EXTRA); + value |= 1U << plane->enable_bit; + vo_write(value, VO_REG_LAYER_CFG_EXTRA); + + value = vo_read(VO_REG_MIX_ENABLE); + value |= 1U << plane->enable_bit; + vo_write(value, VO_REG_MIX_ENABLE); + + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_disable_osd_all(void) +{ + k_u32 layer_enable; + + layer_enable = vo_read(VO_REG_LAYER_CFG_EXTRA); + + for (k_u32 i = 0; i < VO_OSD_COUNT; i++) { + layer_enable &= ~(1U << vo_osd_planes[i].enable_bit); + } + + vo_write(layer_enable, VO_REG_LAYER_CFG_EXTRA); + vo_write(0x00000000U, VO_REG_MIX_ENABLE); + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_select_osd(k_u32 osd) +{ + k_u32 layer_enable; + k_u32 mix_enable; + + if (osd >= VO_OSD_COUNT) + return; + + layer_enable = vo_read(VO_REG_LAYER_CFG_EXTRA); + mix_enable = vo_read(VO_REG_MIX_ENABLE); + + for (k_u32 i = 0; i < VO_OSD_COUNT; i++) { + layer_enable &= ~(1U << vo_osd_planes[i].enable_bit); + } + + layer_enable |= 1U << vo_osd_planes[osd].enable_bit; + mix_enable |= VO_MIX_ENABLE_SDK; + + vo_write(layer_enable, VO_REG_LAYER_CFG_EXTRA); + vo_write(mix_enable, VO_REG_MIX_ENABLE); + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_commit(void) +{ + vo_write(0x00000011U, VO_REG_LOAD_CTL); +} + +void kd_vo_poke(k_u32 offset, k_u32 value) +{ + vo_write(value, offset); +} + +void kd_vo_debug_dump(void) +{ + (void)vo_display_remap_init(); + + rt_kprintf("VO base=%p\n", display_remap ? display_remap->vo_base : RT_NULL); + rt_kprintf("VO load/enable=0x%08x dma_sw=0x%08x active_h=0x%08x active_v=0x%08x total=0x%08x\n", + vo_read(VO_REG_LOAD_CTL), vo_read(VO_REG_WRAP_CTRL0), + vo_read(VO_REG_ACTIVE_H), vo_read(VO_REG_ACTIVE_V), vo_read(VO_REG_TOTAL_SIZE)); + rt_kprintf("VO layer_en=0x%08x mix_en=0x%08x mix_alpha0=0x%08x mix_alpha1=0x%08x bg=0x%08x\n", + vo_read(VO_REG_LAYER_CFG_EXTRA), vo_read(VO_REG_MIX_ENABLE), + vo_read(VO_REG_MIX_ALPHA0), vo_read(VO_REG_MIX_ALPHA1), vo_read(VO_REG_BG_COLOR)); + rt_kprintf("VO pri0=0x%08x pri1=0x%08x intr_frame=0x%08x intr_vtth=0x%08x intr_mask=0x%08x\n", + vo_read(VO_REG_MIX_PRIORITY0), vo_read(VO_REG_MIX_PRIORITY1), + vo_read(VO_REG_INTR_FRAME), vo_read(VO_REG_INTR_VTTH), vo_read(VO_REG_INTR_MASK0)); + + for (k_u32 i = 0; i < VO_OSD_COUNT; i++) { + const struct vo_osd_plane *plane = &vo_osd_planes[i]; + + rt_kprintf("OSD%u off=0x%03x bit=%u info=0x%08x size=0x%08x x=0x%08x y=0x%08x\n", + i, plane->offset, plane->enable_bit, + vo_read(plane->offset + VO_OSD_INFO), + vo_read(plane->offset + VO_OSD_SIZE), + vo_read(plane->xctl), vo_read(plane->yctl)); + rt_kprintf("OSD%u addr0=0x%08x alp0=0x%08x addr1=0x%08x alp1=0x%08x dma=0x%08x stride=0x%08x sel=0x%08x\n", + i, + vo_read(plane->offset + VO_OSD_VLU_ADDR0), + vo_read(plane->offset + VO_OSD_ALP_ADDR0), + vo_read(plane->offset + VO_OSD_VLU_ADDR1), + vo_read(plane->offset + VO_OSD_ALP_ADDR1), + vo_read(plane->offset + VO_OSD_DMA_CTRL), + vo_read(plane->offset + VO_OSD_STRIDE), + vo_read(plane->offset + VO_OSD_ADDR_SEL_MODE)); + } +} + +void kd_vo_debug_summary(void) +{ + (void)vo_display_remap_init(); + + rt_kprintf("VO_SUM load=0x%08x dma_sw=0x%08x layer_en=0x%08x mix_en=0x%08x alpha0=0x%08x alpha1=0x%08x bg=0x%08x\n", + vo_read(VO_REG_LOAD_CTL), vo_read(VO_REG_WRAP_CTRL0), + vo_read(VO_REG_LAYER_CFG_EXTRA), vo_read(VO_REG_MIX_ENABLE), + vo_read(VO_REG_MIX_ALPHA0), vo_read(VO_REG_MIX_ALPHA1), + vo_read(VO_REG_BG_COLOR)); + rt_kprintf("VO_SUM active_h=0x%08x active_v=0x%08x total=0x%08x pri0=0x%08x pri1=0x%08x intr=0x%08x\n", + vo_read(VO_REG_ACTIVE_H), vo_read(VO_REG_ACTIVE_V), + vo_read(VO_REG_TOTAL_SIZE), vo_read(VO_REG_MIX_PRIORITY0), + vo_read(VO_REG_MIX_PRIORITY1), vo_read(VO_REG_INTR_FRAME)); + + for (k_u32 i = 0; i < VO_OSD_COUNT; i++) { + const struct vo_osd_plane *plane = &vo_osd_planes[i]; + k_u32 info = vo_read(plane->offset + VO_OSD_INFO); + k_u32 size = vo_read(plane->offset + VO_OSD_SIZE); + k_u32 addr = vo_read(plane->offset + VO_OSD_VLU_ADDR0); + k_u32 stride = vo_read(plane->offset + VO_OSD_STRIDE); + k_u32 dma = vo_read(plane->offset + VO_OSD_DMA_CTRL); + k_u32 sel = vo_read(plane->offset + VO_OSD_ADDR_SEL_MODE); + + if (info || size || addr || (vo_read(VO_REG_LAYER_CFG_EXTRA) & (1U << plane->enable_bit))) { + rt_kprintf("VO_SUM OSD%u bit=%u off=0x%03x info=0x%08x size=0x%08x addr=0x%08x alp=0x%08x stride=0x%08x dma=0x%08x sel=0x%08x x=0x%08x y=0x%08x\n", + i, plane->enable_bit, plane->offset, info, size, addr, + vo_read(plane->offset + VO_OSD_ALP_ADDR0), stride, dma, + sel, vo_read(plane->xctl), vo_read(plane->yctl)); + } + } } void kd_vo_set_timing(const k_vo_timing *timing) diff --git a/bsp/k230/drivers/display/vo/kd_vo_reg.h b/bsp/k230/drivers/display/vo/kd_vo_reg.h index 2112a1eee0f..0cbfbd7f680 100644 --- a/bsp/k230/drivers/display/vo/kd_vo_reg.h +++ b/bsp/k230/drivers/display/vo/kd_vo_reg.h @@ -15,9 +15,26 @@ void kd_vo_set_vtth_intr(k_u32 status, k_u32 line); void kd_vo_set_pixclk(k_u32 div); void kd_vo_set_timing(const k_vo_timing *timing); void kd_vo_set_background(k_u32 rgb888); +void kd_vo_set_background_yuv(k_u32 yuv); +void kd_vo_set_osd_rgb565_framebuffer(k_u32 osd, k_u64 paddr, k_u32 width, k_u32 height, k_u32 pitch); +void kd_vo_set_osd_rgb565_framebuffer_ex(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 pitch, + k_u32 dma_ctrl, k_u32 addr_sel); +void kd_vo_set_osd_rgb565_framebuffer_raw(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 stride_reg, + k_u32 dma_ctrl, k_u32 addr_sel); +void kd_vo_set_osd_rgb565_framebuffer_format_raw(k_u32 osd, k_u64 paddr, k_u64 alpha_paddr, + k_u32 width, k_u32 height, k_u32 stride_reg, + k_u32 info, k_u32 dma_ctrl, k_u32 addr_sel); +void kd_vo_select_osd(k_u32 osd); +void kd_vo_disable_osd_all(void); +void kd_vo_commit(void); +void kd_vo_poke(k_u32 offset, k_u32 value); void kd_vo_enable(void); void kd_vo_timestamp_enable(void); void k230_get_timestamp(k_u32 *ptp_time, k_u32 *time); +void kd_vo_debug_dump(void); +void kd_vo_debug_summary(void); #ifdef __cplusplus } diff --git a/bsp/k230/drivers/display/vo/vo_remap.c b/bsp/k230/drivers/display/vo/vo_remap.c index 3ac196ae4c1..4bc5cb74d3f 100644 --- a/bsp/k230/drivers/display/vo/vo_remap.c +++ b/bsp/k230/drivers/display/vo/vo_remap.c @@ -2,27 +2,19 @@ #include +#include "board.h" +#include "ioremap.h" + #include -#define VO_REG_BASE_PHYS 0x09084000UL -#define VO_REG_SIZE 0x00010000UL -#define DSI_REG_BASE_PHYS 0x09085000UL -#define DSI_REG_SIZE 0x00001000UL -#define SYSCTL_REG_BASE_PHYS 0x91101000UL -#define DSI_PHY_REG_BASE_PHYS 0x09085400UL -#define CLOCK_REG_BASE_PHYS 0x91100000UL -#define TIMESTAMP_REG_BASE_PHYS 0x91108000UL -#define AUX_REG_SIZE 0x00001000UL +#define DSI_PHY_REG_BASE_PHYS (DSI_BASE_ADDR + 0x400UL) +#define DSI_PHY_REG_SIZE (DSI_IO_SIZE - 0x400UL) struct vo_display_remap *display_remap; static struct vo_display_remap g_display_remap; static int g_remap_ready; -extern void *rt_ioremap(unsigned long phys_addr, unsigned long size); -extern void *rt_ioremap_nocache(unsigned long phys_addr, unsigned long size); -extern void rt_iounmap(void *addr); - static void unmap_if_present(void **addr) { if (addr != RT_NULL && *addr != RT_NULL) @@ -60,12 +52,12 @@ int vo_display_remap_init(void) memset(&g_display_remap, 0, sizeof(g_display_remap)); - g_display_remap.vo_base = rt_ioremap_nocache(VO_REG_BASE_PHYS, VO_REG_SIZE); - g_display_remap.dsi_base = rt_ioremap_nocache(DSI_REG_BASE_PHYS, DSI_REG_SIZE); - g_display_remap.sysctl_base = rt_ioremap(SYSCTL_REG_BASE_PHYS, AUX_REG_SIZE); - g_display_remap.phy_base = rt_ioremap(DSI_PHY_REG_BASE_PHYS, AUX_REG_SIZE); - g_display_remap.clock_base = rt_ioremap(CLOCK_REG_BASE_PHYS, AUX_REG_SIZE); - g_display_remap.timestamp_base = rt_ioremap(TIMESTAMP_REG_BASE_PHYS, AUX_REG_SIZE); + g_display_remap.vo_base = rt_ioremap_nocache((void *)VO_BASE_ADDR, VO_IO_SIZE); + g_display_remap.dsi_base = rt_ioremap_nocache((void *)DSI_BASE_ADDR, DSI_IO_SIZE); + g_display_remap.sysctl_base = rt_ioremap((void *)RMU_BASE_ADDR, RMU_IO_SIZE); + g_display_remap.phy_base = rt_ioremap_nocache((void *)DSI_PHY_REG_BASE_PHYS, DSI_PHY_REG_SIZE); + g_display_remap.clock_base = rt_ioremap((void *)CMU_BASE_ADDR, CMU_IO_SIZE); + g_display_remap.timestamp_base = rt_ioremap((void *)STC_BASE_ADDR, STC_IO_SIZE); if (g_display_remap.vo_base == RT_NULL || g_display_remap.dsi_base == RT_NULL || diff --git a/bsp/k230/rtconfig.h b/bsp/k230/rtconfig.h index e0a4e114508..7e979a0d755 100644 --- a/bsp/k230/rtconfig.h +++ b/bsp/k230/rtconfig.h @@ -72,7 +72,7 @@ /* end of rt_strnlen options */ /* end of klibc options */ -#define RT_NAME_MAX 16 +#define RT_NAME_MAX 32 #define RT_USING_SMART #define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 @@ -90,6 +90,7 @@ #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 8192 #define RT_USING_CPU_USAGE_TRACER +#define RT_CPU_USAGE_CALC_INTERVAL_MS 200 /* kservice options */ @@ -120,7 +121,8 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x50201 +#define RT_USING_CONSOLE_OUTPUT_CTL +#define RT_VER_NUM 0x50300 #define RT_USING_STDC_ATOMIC #define RT_BACKTRACE_LEVEL_MAX_NR 32 /* end of RT-Thread Kernel */ @@ -130,11 +132,10 @@ #define KERNEL_VADDR_START 0xffffffc000000000 #define ARCH_RISCV #define ARCH_RISCV_FPU -#define ARCH_RISCV_VECTOR -#define ARCH_VECTOR_VLEN_128 -#define ARCH_RISCV_FPU_D #define ARCH_RISCV64 +#define ARCH_RISCV_XUANTIE #define ARCH_USING_NEW_CTX_SWITCH +#define CONFIG_XUANTIE_SVPBMT 1 #define ARCH_REMAP_KERNEL /* RT-Thread Components */ @@ -183,7 +184,6 @@ /* end of elm-chan's FatFs, Generic FAT Filesystem Module */ #define RT_USING_DFS_DEVFS #define RT_USING_DFS_PTYFS -#define RT_USING_DFS_CROMFS #define RT_USING_DFS_TMPFS #define RT_USING_PAGECACHE @@ -210,13 +210,13 @@ #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_SERIAL_BYPASS -#define RT_USING_CPUTIME -#define RT_USING_CPUTIME_RISCV -#define CPUTIME_TIMER_FREQ 25000000 +#define RT_USING_CLOCK_TIME +#define CLOCK_TIMER_FREQ 250000 #define RT_USING_NULL #define RT_USING_ZERO #define RT_USING_RANDOM #define RT_USING_RTC +#define RT_USING_SOFT_RTC #define RT_USING_SDIO #define RT_SDIO_STACK_SIZE 8192 #define RT_SDIO_THREAD_PRIORITY 15 @@ -231,7 +231,6 @@ #define RT_BLK_PARTITION_EFI /* end of Partition Types */ #define RT_USING_PIN -#define RT_USING_KTIME /* end of Device Drivers */ /* C/C++ and POSIX layer */ @@ -265,6 +264,8 @@ /* Interprocess Communication (IPC) */ +#define RT_USING_POSIX_PIPE +#define RT_USING_POSIX_PIPE_SIZE 2048 /* Socket is in the 'Network' category */ @@ -462,6 +463,9 @@ /* Micrium: Micrium software products porting for RT-Thread */ /* end of Micrium: Micrium software products porting for RT-Thread */ +#define PKG_USING_LWEXT4 +#define RT_USING_DFS_LWEXT4 +#define PKG_USING_LWEXT4_LATEST_VERSION /* end of system packages */ /* peripheral libraries and drivers */ @@ -503,6 +507,14 @@ /* GD32 Drivers */ /* end of GD32 Drivers */ + +/* HPMicro SDK */ + +/* end of HPMicro SDK */ + +/* FT32 HAL & SDK Drivers */ + +/* end of FT32 HAL & SDK Drivers */ /* end of HAL & SDK Drivers */ /* sensors drivers */ @@ -535,8 +547,6 @@ /* entertainment: terminal games and other interesting software packages */ /* end of entertainment: terminal games and other interesting software packages */ -#define PKG_USING_ZLIB -#define PKG_USING_ZLIB_LATEST_VERSION /* end of miscellaneous packages */ /* Arduino libraries */ @@ -587,17 +597,20 @@ /* Drivers Configuration */ +#define BSP_USING_GPIO +#define BSP_USING_DISPLAY #define BSP_USING_UART #define BSP_UART_USING_DMA #define BSP_USING_UART0 #define BSP_USING_HARDLOCK #define BSP_USING_SDIO #define BSP_USING_SDIO0 -#define BSP_SD_MNT_DEVNAME "sd0p1" +#define BSP_SD_MNT_DEVNAME "sd0p0" /* end of Drivers Configuration */ +#define SOC_K230D #define BOARD_C908 #define __STACKSIZE__ 65536 #define BSP_ROOTFS_TYPE_ELMFAT -#define BSP_RISCV_FPU_D +#define BSP_RISCV_FPU_SOFT #endif diff --git a/bsp/k230/rtconfig.py b/bsp/k230/rtconfig.py index 10987fa320b..7f390e8765b 100644 --- a/bsp/k230/rtconfig.py +++ b/bsp/k230/rtconfig.py @@ -30,7 +30,7 @@ if PLATFORM == 'gcc': # toolchains #PREFIX = 'riscv64-unknown-elf-' - PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-linux-musl-' + PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-linux-musleabi-' CC = PREFIX + 'gcc' CXX = PREFIX + 'g++' AS = PREFIX + 'gcc' diff --git a/bsp/qemu-virt64-riscv/.config b/bsp/qemu-virt64-riscv/.config index 2bca112cf86..09c479f430a 100644 --- a/bsp/qemu-virt64-riscv/.config +++ b/bsp/qemu-virt64-riscv/.config @@ -116,10 +116,10 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 # end of rt_strnlen options # end of klibc options -CONFIG_RT_NAME_MAX=24 +CONFIG_RT_NAME_MAX=32 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_NANO is not set -# CONFIG_RT_USING_SMART is not set +CONFIG_RT_USING_SMART=y # CONFIG_RT_USING_AMP is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_CPUS_NR=1 @@ -141,6 +141,7 @@ CONFIG_RT_TIMER_THREAD_PRIO=4 CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384 # CONFIG_RT_USING_TIMER_ALL_SOFT is not set CONFIG_RT_USING_CPU_USAGE_TRACER=y +CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200 # # kservice options @@ -191,7 +192,8 @@ CONFIG_RT_USING_DEVICE_OPS=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x50201 +CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y +CONFIG_RT_VER_NUM=0x50300 CONFIG_RT_USING_STDC_ATOMIC=y CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 # end of RT-Thread Kernel @@ -199,6 +201,7 @@ CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 CONFIG_ARCH_CPU_64BIT=y CONFIG_RT_USING_CACHE=y CONFIG_ARCH_MM_MMU=y +CONFIG_KERNEL_VADDR_START=0xffffffc000000000 CONFIG_ARCH_RISCV=y CONFIG_ARCH_RISCV_FPU=y CONFIG_ARCH_RISCV64=y @@ -240,7 +243,6 @@ CONFIG_RT_USING_DFS=y CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FD_MAX=32 -# CONFIG_RT_USING_DFS_V1 is not set CONFIG_RT_USING_DFS_V2=y CONFIG_RT_USING_DFS_ELMFAT=y @@ -270,9 +272,23 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000 CONFIG_RT_USING_DFS_DEVFS=y CONFIG_RT_USING_DFS_ROMFS=y +CONFIG_RT_USING_DFS_PTYFS=y +# CONFIG_RT_USING_DFS_PROCFS is not set # CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_TMPFS is not set # CONFIG_RT_USING_DFS_MQUEUE is not set +CONFIG_RT_USING_PAGECACHE=y + +# +# page cache config +# +CONFIG_RT_PAGECACHE_COUNT=4096 +CONFIG_RT_PAGECACHE_ASPACE_COUNT=1024 +CONFIG_RT_PAGECACHE_PRELOAD=4 +CONFIG_RT_PAGECACHE_HASH_NR=1024 +CONFIG_RT_PAGECACHE_GC_WORK_LEVEL=90 +CONFIG_RT_PAGECACHE_GC_STOP_LEVEL=70 +# end of page cache config # end of DFS: device virtual file system # CONFIG_RT_USING_FAL is not set @@ -280,8 +296,8 @@ CONFIG_RT_USING_DFS_ROMFS=y # # Device Drivers # -# CONFIG_RT_USING_DM is not set -# CONFIG_RT_USING_DEV_BUS is not set +CONFIG_RT_USING_DM=y +CONFIG_RT_USING_DEV_BUS=y CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_UNAMED_PIPE_NUMBER=64 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y @@ -292,11 +308,13 @@ CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 -# CONFIG_RT_USING_SERIAL_BYPASS is not set +CONFIG_RT_USING_SERIAL_BYPASS=y +# CONFIG_RT_SERIAL_EARLY_HVC is not set +# CONFIG_RT_SERIAL_PL011 is not set +# CONFIG_RT_SERIAL_8250 is not set # CONFIG_RT_USING_CAN is not set -CONFIG_RT_USING_CPUTIME=y -CONFIG_RT_USING_CPUTIME_RISCV=y -CONFIG_CPUTIME_TIMER_FREQ=10000000 +CONFIG_RT_USING_CLOCK_TIME=y +CONFIG_CLOCK_TIMER_FREQ=0 # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set # CONFIG_RT_USING_PHY_V2 is not set @@ -314,16 +332,37 @@ CONFIG_RT_USING_RANDOM=y CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set CONFIG_RT_USING_SOFT_RTC=y +# CONFIG_RT_RTC_GOLDFISH is not set +# CONFIG_RT_RTC_PL031 is not set # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set # CONFIG_RT_USING_WDT is not set # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set -# CONFIG_RT_USING_LCD is not set +# CONFIG_RT_USING_GRAPHIC is not set # CONFIG_RT_USING_HWCRYPTO is not set # CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_LED is not set +# CONFIG_RT_USING_INPUT is not set +# CONFIG_RT_USING_MBOX is not set +# CONFIG_RT_USING_HWSPINLOCK is not set +# CONFIG_RT_USING_PHYE is not set # CONFIG_RT_USING_BLK is not set +# CONFIG_RT_USING_SCSI is not set +# CONFIG_RT_USING_FIRMWARE is not set +# CONFIG_RT_USING_HWCACHE is not set +# CONFIG_RT_USING_REGULATOR is not set +# CONFIG_RT_USING_RESET is not set + +# +# Power Management (PM) Domains device drivers +# +# end of Power Management (PM) Domains device drivers + +# CONFIG_RT_USING_POWER_RESET is not set +# CONFIG_RT_USING_POWER_SUPPLY is not set +# CONFIG_RT_USING_THERMAL is not set CONFIG_RT_USING_VIRTIO=y CONFIG_RT_USING_VIRTIO10=y # CONFIG_RT_USING_VIRTIO_MMIO_ALIGN is not set @@ -333,10 +372,23 @@ CONFIG_RT_USING_VIRTIO_CONSOLE=y CONFIG_RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR=4 CONFIG_RT_USING_VIRTIO_GPU=y CONFIG_RT_USING_VIRTIO_INPUT=y +# CONFIG_RT_USING_NVMEM is not set +# CONFIG_RT_USING_DMA is not set +# CONFIG_RT_USING_MFD is not set +CONFIG_RT_USING_OFW=y +# CONFIG_RT_USING_BUILTIN_FDT is not set +CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128 +CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8 +# CONFIG_RT_USING_PIC is not set CONFIG_RT_USING_PIN=y -CONFIG_RT_USING_KTIME=y -# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_PIN_PL061 is not set +# CONFIG_RT_USING_PINCTRL is not set +CONFIG_RT_USING_CLK=y # CONFIG_RT_USING_CHERRYUSB is not set + +# +# SoC (System on Chip) Drivers +# # end of Device Drivers # @@ -367,6 +419,9 @@ CONFIG_RT_USING_POSIX_STDIO=y CONFIG_RT_USING_POSIX_POLL=y CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_EVENTFD is not set +CONFIG_RT_USING_POSIX_EPOLL=y +CONFIG_RT_USING_POSIX_SIGNALFD=y +CONFIG_RT_SIGNALFD_MAX_NUM=10 # CONFIG_RT_USING_POSIX_TIMERFD is not set # CONFIG_RT_USING_POSIX_SOCKET is not set CONFIG_RT_USING_POSIX_TERMIOS=y @@ -497,7 +552,11 @@ CONFIG_RT_LWIP_USING_PING=y # # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set -# CONFIG_RT_USING_UTEST is not set +CONFIG_RT_USING_UTEST=y +CONFIG_UTEST_THR_STACK_SIZE=4096 +CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_UTEST_USING_AUTO_RUN is not set +CONFIG_RT_UTEST_MAX_OPTIONS=64 # CONFIG_RT_USING_VAR_EXPORT is not set CONFIG_RT_USING_RESOURCE_ID=y CONFIG_RT_USING_ADT=y @@ -508,14 +567,14 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_RT_USING_RT_LINK is not set # end of Utilities -# CONFIG_RT_USING_VBUS is not set - # # Memory management # +# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000 CONFIG_RT_PAGE_MAX_ORDER=11 -# CONFIG_RT_USING_MEMBLOCK is not set +CONFIG_RT_USING_MEMBLOCK=y +CONFIG_RT_INIT_MEMORY_REGIONS=128 # # Debugging @@ -526,6 +585,21 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # end of Debugging # end of Memory management +CONFIG_RT_USING_LWP=y +# CONFIG_LWP_DEBUG is not set +CONFIG_LWP_USING_RUNTIME=y +CONFIG_RT_LWP_MAX_NR=30 +CONFIG_LWP_TASK_STACK_SIZE=16384 +CONFIG_RT_CH_MSG_MAX_NR=1024 +CONFIG_LWP_TID_MAX_NR=64 +CONFIG_RT_LWP_SHM_MAX_NR=64 +CONFIG_RT_USING_LDSO=y +# CONFIG_ELF_DEBUG_ENABLE is not set +# CONFIG_ELF_LOAD_RANDOMIZE is not set +CONFIG_LWP_USING_TERMINAL=y +CONFIG_LWP_PTY_MAX_PARIS_LIMIT=64 +# CONFIG_RT_USING_VDSO is not set + # # Using USB legacy version # @@ -534,6 +608,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # end of Using USB legacy version # CONFIG_RT_USING_FDT is not set +# CONFIG_RT_USING_RUST is not set # end of RT-Thread Components # @@ -542,1031 +617,10 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # CONFIG_RT_USING_UTESTCASES is not set # end of RT-Thread Utestcases -# -# RT-Thread online packages -# - -# -# IoT - internet of things -# -# CONFIG_PKG_USING_LORAWAN_DRIVER is not set -# CONFIG_PKG_USING_PAHOMQTT is not set -# CONFIG_PKG_USING_UMQTT is not set -# CONFIG_PKG_USING_WEBCLIENT is not set -# CONFIG_PKG_USING_WEBNET is not set -# CONFIG_PKG_USING_MONGOOSE is not set -# CONFIG_PKG_USING_MYMQTT is not set -# CONFIG_PKG_USING_KAWAII_MQTT is not set -# CONFIG_PKG_USING_BC28_MQTT is not set -# CONFIG_PKG_USING_WEBTERMINAL is not set -# CONFIG_PKG_USING_FREEMODBUS is not set -# CONFIG_PKG_USING_NANOPB is not set -# CONFIG_PKG_USING_WIFI_HOST_DRIVER is not set -# CONFIG_PKG_USING_ESP_HOSTED is not set - -# -# Wi-Fi -# - -# -# Marvell WiFi -# -# CONFIG_PKG_USING_WLANMARVELL is not set -# end of Marvell WiFi - -# -# Wiced WiFi -# -# CONFIG_PKG_USING_WLAN_WICED is not set -# end of Wiced WiFi - -# CONFIG_PKG_USING_RW007 is not set - -# -# CYW43012 WiFi -# -# CONFIG_PKG_USING_WLAN_CYW43012 is not set -# end of CYW43012 WiFi - -# -# BL808 WiFi -# -# CONFIG_PKG_USING_WLAN_BL808 is not set -# end of BL808 WiFi - -# -# CYW43439 WiFi -# -# CONFIG_PKG_USING_WLAN_CYW43439 is not set -# end of CYW43439 WiFi -# end of Wi-Fi - -# CONFIG_PKG_USING_COAP is not set -# CONFIG_PKG_USING_NOPOLL is not set -# CONFIG_PKG_USING_NETUTILS is not set -# CONFIG_PKG_USING_CMUX is not set -# CONFIG_PKG_USING_PPP_DEVICE is not set -# CONFIG_PKG_USING_AT_DEVICE is not set -# CONFIG_PKG_USING_ATSRV_SOCKET is not set -# CONFIG_PKG_USING_WIZNET is not set -# CONFIG_PKG_USING_ZB_COORDINATOR is not set - -# -# IoT Cloud -# -# CONFIG_PKG_USING_ONENET is not set -# CONFIG_PKG_USING_GAGENT_CLOUD is not set -# CONFIG_PKG_USING_ALI_IOTKIT is not set -# CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set -# CONFIG_PKG_USING_JIOT-C-SDK is not set -# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set -# CONFIG_PKG_USING_JOYLINK is not set -# CONFIG_PKG_USING_IOTSHARP_SDK is not set -# end of IoT Cloud - -# CONFIG_PKG_USING_NIMBLE is not set -# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set -# CONFIG_PKG_USING_OTA_DOWNLOADER is not set -# CONFIG_PKG_USING_IPMSG is not set -# CONFIG_PKG_USING_LSSDP is not set -# CONFIG_PKG_USING_AIRKISS_OPEN is not set -# CONFIG_PKG_USING_LIBRWS is not set -# CONFIG_PKG_USING_TCPSERVER is not set -# CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_DLT645 is not set -# CONFIG_PKG_USING_QXWZ is not set -# CONFIG_PKG_USING_SMTP_CLIENT is not set -# CONFIG_PKG_USING_ABUP_FOTA is not set -# CONFIG_PKG_USING_LIBCURL2RTT is not set -# CONFIG_PKG_USING_CAPNP is not set -# CONFIG_PKG_USING_AGILE_TELNET is not set -# CONFIG_PKG_USING_NMEALIB is not set -# CONFIG_PKG_USING_PDULIB is not set -# CONFIG_PKG_USING_BTSTACK is not set -# CONFIG_PKG_USING_BT_CYW43012 is not set -# CONFIG_PKG_USING_CYW43XX is not set -# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set -# CONFIG_PKG_USING_WAYZ_IOTKIT is not set -# CONFIG_PKG_USING_MAVLINK is not set -# CONFIG_PKG_USING_BSAL is not set -# CONFIG_PKG_USING_AGILE_MODBUS is not set -# CONFIG_PKG_USING_AGILE_FTP is not set -# CONFIG_PKG_USING_EMBEDDEDPROTO is not set -# CONFIG_PKG_USING_RT_LINK_HW is not set -# CONFIG_PKG_USING_RYANMQTT is not set -# CONFIG_PKG_USING_RYANW5500 is not set -# CONFIG_PKG_USING_LORA_PKT_FWD is not set -# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set -# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set -# CONFIG_PKG_USING_HM is not set -# CONFIG_PKG_USING_SMALL_MODBUS is not set -# CONFIG_PKG_USING_NET_SERVER is not set -# CONFIG_PKG_USING_ZFTP is not set -# CONFIG_PKG_USING_WOL is not set -# CONFIG_PKG_USING_ZEPHYR_POLLING is not set -# CONFIG_PKG_USING_MATTER_ADAPTATION_LAYER is not set -# CONFIG_PKG_USING_LHC_MODBUS is not set -# CONFIG_PKG_USING_QMODBUS is not set -# CONFIG_PKG_USING_PNET is not set -# CONFIG_PKG_USING_OPENER is not set -# CONFIG_PKG_USING_FREEMQTT is not set -# end of IoT - internet of things - -# -# security packages -# -# CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_LIBSODIUM is not set -# CONFIG_PKG_USING_LIBHYDROGEN is not set -# CONFIG_PKG_USING_TINYCRYPT is not set -# CONFIG_PKG_USING_TFM is not set -# CONFIG_PKG_USING_YD_CRYPTO is not set -# end of security packages - -# -# language packages -# - -# -# JSON: JavaScript Object Notation, a lightweight data-interchange format -# -# CONFIG_PKG_USING_CJSON is not set -# CONFIG_PKG_USING_LJSON is not set -# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set -# CONFIG_PKG_USING_RAPIDJSON is not set -# CONFIG_PKG_USING_JSMN is not set -# CONFIG_PKG_USING_AGILE_JSMN is not set -# CONFIG_PKG_USING_PARSON is not set -# CONFIG_PKG_USING_RYAN_JSON is not set -# end of JSON: JavaScript Object Notation, a lightweight data-interchange format - -# -# XML: Extensible Markup Language -# -# CONFIG_PKG_USING_SIMPLE_XML is not set -# CONFIG_PKG_USING_EZXML is not set -# end of XML: Extensible Markup Language - -# CONFIG_PKG_USING_LUATOS_SOC is not set -# CONFIG_PKG_USING_LUA is not set -# CONFIG_PKG_USING_JERRYSCRIPT is not set -# CONFIG_PKG_USING_MICROPYTHON is not set -# CONFIG_PKG_USING_PIKASCRIPT is not set -# CONFIG_PKG_USING_RTT_RUST is not set -# end of language packages - -# -# multimedia packages -# - -# -# LVGL: powerful and easy-to-use embedded GUI library -# -# CONFIG_PKG_USING_LVGL is not set -# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set -# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set -# end of LVGL: powerful and easy-to-use embedded GUI library - -# -# u8g2: a monochrome graphic library -# -# CONFIG_PKG_USING_U8G2_OFFICIAL is not set -# CONFIG_PKG_USING_U8G2 is not set -# end of u8g2: a monochrome graphic library - -# CONFIG_PKG_USING_OPENMV is not set -# CONFIG_PKG_USING_MUPDF is not set -# CONFIG_PKG_USING_STEMWIN is not set -# CONFIG_PKG_USING_WAVPLAYER is not set -# CONFIG_PKG_USING_TJPGD is not set -# CONFIG_PKG_USING_PDFGEN is not set -# CONFIG_PKG_USING_HELIX is not set -# CONFIG_PKG_USING_AZUREGUIX is not set -# CONFIG_PKG_USING_TOUCHGFX2RTT is not set -# CONFIG_PKG_USING_NUEMWIN is not set -# CONFIG_PKG_USING_MP3PLAYER is not set -# CONFIG_PKG_USING_TINYJPEG is not set -# CONFIG_PKG_USING_UGUI is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_TERMBOX is not set -# CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_QRCODE is not set -# CONFIG_PKG_USING_GUIENGINE is not set -# CONFIG_PKG_USING_3GPP_AMRNB is not set -# end of multimedia packages - -# -# tools packages -# -# CONFIG_PKG_USING_CMBACKTRACE is not set -# CONFIG_PKG_USING_MCOREDUMP is not set -# CONFIG_PKG_USING_EASYFLASH is not set -# CONFIG_PKG_USING_EASYLOGGER is not set -# CONFIG_PKG_USING_SYSTEMVIEW is not set -# CONFIG_PKG_USING_SEGGER_RTT is not set -# CONFIG_PKG_USING_RTT_AUTO_EXE_CMD is not set -# CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_ULOG_EASYFLASH is not set -# CONFIG_PKG_USING_LOGMGR is not set -# CONFIG_PKG_USING_ADBD is not set -# CONFIG_PKG_USING_COREMARK is not set -# CONFIG_PKG_USING_DHRYSTONE is not set -# CONFIG_PKG_USING_MEMORYPERF is not set -# CONFIG_PKG_USING_NR_MICRO_SHELL is not set -# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set -# CONFIG_PKG_USING_LUNAR_CALENDAR is not set -# CONFIG_PKG_USING_BS8116A is not set -# CONFIG_PKG_USING_GPS_RMC is not set -# CONFIG_PKG_USING_URLENCODE is not set -# CONFIG_PKG_USING_UMCN is not set -# CONFIG_PKG_USING_LWRB2RTT is not set -# CONFIG_PKG_USING_CPU_USAGE is not set -# CONFIG_PKG_USING_GBK2UTF8 is not set -# CONFIG_PKG_USING_VCONSOLE is not set -# CONFIG_PKG_USING_KDB is not set -# CONFIG_PKG_USING_WAMR is not set -# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set -# CONFIG_PKG_USING_LWLOG is not set -# CONFIG_PKG_USING_ANV_TRACE is not set -# CONFIG_PKG_USING_ANV_MEMLEAK is not set -# CONFIG_PKG_USING_ANV_TESTSUIT is not set -# CONFIG_PKG_USING_ANV_BENCH is not set -# CONFIG_PKG_USING_DEVMEM is not set -# CONFIG_PKG_USING_REGEX is not set -# CONFIG_PKG_USING_MEM_SANDBOX is not set -# CONFIG_PKG_USING_SOLAR_TERMS is not set -# CONFIG_PKG_USING_GAN_ZHI is not set -# CONFIG_PKG_USING_FDT is not set -# CONFIG_PKG_USING_CBOX is not set -# CONFIG_PKG_USING_SNOWFLAKE is not set -# CONFIG_PKG_USING_HASH_MATCH is not set -# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set -# CONFIG_PKG_USING_VOFA_PLUS is not set -# CONFIG_PKG_USING_ZDEBUG is not set -# CONFIG_PKG_USING_RVBACKTRACE is not set -# CONFIG_PKG_USING_HPATCHLITE is not set -# CONFIG_PKG_USING_THREAD_METRIC is not set -# end of tools packages - -# -# system packages -# - -# -# enhanced kernel services -# -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set -# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# end of enhanced kernel services - -# CONFIG_PKG_USING_AUNITY is not set - -# -# acceleration: Assembly language or algorithmic acceleration packages -# -# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set -# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set -# CONFIG_PKG_USING_QFPLIB_M3 is not set -# end of acceleration: Assembly language or algorithmic acceleration packages - -# -# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard -# -# CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_CORE is not set -# CONFIG_PKG_USING_CMSIS_NN is not set -# CONFIG_PKG_USING_CMSIS_RTOS1 is not set -# CONFIG_PKG_USING_CMSIS_RTOS2 is not set -# end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set -# end of Micrium: Micrium software products porting for RT-Thread - -# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set -# CONFIG_PKG_USING_LITEOS_SDK is not set -# CONFIG_PKG_USING_TZ_DATABASE is not set -# CONFIG_PKG_USING_CAIRO is not set -# CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_PARTITION is not set -# CONFIG_PKG_USING_PERF_COUNTER is not set -# CONFIG_PKG_USING_FILEX is not set -# CONFIG_PKG_USING_LEVELX is not set -# CONFIG_PKG_USING_FLASHDB is not set -# CONFIG_PKG_USING_SQLITE is not set -# CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_DFS_YAFFS is not set -# CONFIG_PKG_USING_LITTLEFS is not set -# CONFIG_PKG_USING_DFS_JFFS2 is not set -# CONFIG_PKG_USING_DFS_UFFS is not set -# CONFIG_PKG_USING_LWEXT4 is not set -# CONFIG_PKG_USING_THREAD_POOL is not set -# CONFIG_PKG_USING_ROBOTS is not set -# CONFIG_PKG_USING_EV is not set -# CONFIG_PKG_USING_SYSWATCH is not set -# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set -# CONFIG_PKG_USING_PLCCORE is not set -# CONFIG_PKG_USING_RAMDISK is not set -# CONFIG_PKG_USING_MININI is not set -# CONFIG_PKG_USING_QBOOT is not set -# CONFIG_PKG_USING_PPOOL is not set -# CONFIG_PKG_USING_OPENAMP is not set -# CONFIG_PKG_USING_RPMSG_LITE is not set -# CONFIG_PKG_USING_LPM is not set -# CONFIG_PKG_USING_TLSF is not set -# CONFIG_PKG_USING_EVENT_RECORDER is not set -# CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_MCUBOOT is not set -# CONFIG_PKG_USING_TINYUSB is not set -# CONFIG_PKG_USING_KMULTI_RTIMER is not set -# CONFIG_PKG_USING_TFDB is not set -# CONFIG_PKG_USING_QPC is not set -# CONFIG_PKG_USING_AGILE_UPGRADE is not set -# CONFIG_PKG_USING_FLASH_BLOB is not set -# CONFIG_PKG_USING_MLIBC is not set -# CONFIG_PKG_USING_TASK_MSG_BUS is not set -# CONFIG_PKG_USING_UART_FRAMEWORK is not set -# CONFIG_PKG_USING_SFDB is not set -# CONFIG_PKG_USING_RTP is not set -# CONFIG_PKG_USING_REB is not set -# CONFIG_PKG_USING_RMP is not set -# CONFIG_PKG_USING_R_RHEALSTONE is not set -# CONFIG_PKG_USING_HEARTBEAT is not set -# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set -# end of system packages - -# -# peripheral libraries and drivers -# - -# -# HAL & SDK Drivers -# - -# -# STM32 HAL & SDK Drivers -# -# CONFIG_PKG_USING_STM32F0_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F0_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32F1_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F1_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32F2_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F2_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32F3_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F3_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32F4_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F4_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32F7_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32F7_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32G0_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32G0_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32G4_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32G4_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32H5_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32H5_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32H7_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32H7_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32H7RS_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32H7RS_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32L0_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32L0_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32L4_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32L4_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32L5_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32L5_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32U5_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32U5_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32WB55_SDK is not set -# CONFIG_PKG_USING_STM32_SDIO is not set -# CONFIG_PKG_USING_STM32WL_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32WL_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32WB_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32WB_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_STM32MP1_M4_HAL_DRIVER is not set -# CONFIG_PKG_USING_STM32MP1_M4_CMSIS_DRIVER is not set -# end of STM32 HAL & SDK Drivers - -# -# Infineon HAL Packages -# -# CONFIG_PKG_USING_INFINEON_CAT1CM0P is not set -# CONFIG_PKG_USING_INFINEON_CMSIS is not set -# CONFIG_PKG_USING_INFINEON_CORE_LIB is not set -# CONFIG_PKG_USING_INFINEON_MTB_HAL_CAT1 is not set -# CONFIG_PKG_USING_INFINEON_MTB_PDL_CAT1 is not set -# CONFIG_PKG_USING_INFINEON_RETARGET_IO is not set -# CONFIG_PKG_USING_INFINEON_CAPSENSE is not set -# CONFIG_PKG_USING_INFINEON_CSDIDAC is not set -# CONFIG_PKG_USING_INFINEON_SERIAL_FLASH is not set -# CONFIG_PKG_USING_INFINEON_USBDEV is not set -# end of Infineon HAL Packages - -# CONFIG_PKG_USING_BLUETRUM_SDK is not set -# CONFIG_PKG_USING_EMBARC_BSP is not set -# CONFIG_PKG_USING_ESP_IDF is not set - -# -# Kendryte SDK -# -# CONFIG_PKG_USING_K210_SDK is not set -# CONFIG_PKG_USING_KENDRYTE_SDK is not set -# end of Kendryte SDK - -# CONFIG_PKG_USING_NRF5X_SDK is not set -# CONFIG_PKG_USING_NRFX is not set -# CONFIG_PKG_USING_NUCLEI_SDK is not set -# CONFIG_PKG_USING_RASPBERRYPI_PICO_RP2350_SDK is not set -# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set -# CONFIG_PKG_USING_MM32 is not set - -# -# WCH HAL & SDK Drivers -# -# CONFIG_PKG_USING_CH32V20x_SDK is not set -# CONFIG_PKG_USING_CH32V307_SDK is not set -# end of WCH HAL & SDK Drivers - -# -# AT32 HAL & SDK Drivers -# -# CONFIG_PKG_USING_AT32A403A_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32A403A_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32A423_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32A423_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F45x_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F45x_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F402_405_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F402_405_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F403A_407_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F403A_407_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F413_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F413_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F415_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F415_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F421_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F421_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F423_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F423_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F425_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F425_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32F435_437_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32F435_437_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_AT32M412_416_HAL_DRIVER is not set -# CONFIG_PKG_USING_AT32M412_416_CMSIS_DRIVER is not set -# end of AT32 HAL & SDK Drivers - -# -# HC32 DDL Drivers -# -# CONFIG_PKG_USING_HC32F3_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_HC32F3_SERIES_DRIVER is not set -# CONFIG_PKG_USING_HC32F4_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_HC32F4_SERIES_DRIVER is not set -# end of HC32 DDL Drivers - -# -# NXP HAL & SDK Drivers -# -# CONFIG_PKG_USING_NXP_MCX_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_NXP_MCX_SERIES_DRIVER is not set -# CONFIG_PKG_USING_NXP_LPC_DRIVER is not set -# CONFIG_PKG_USING_NXP_LPC55S_DRIVER is not set -# CONFIG_PKG_USING_NXP_IMX6SX_DRIVER is not set -# CONFIG_PKG_USING_NXP_IMX6UL_DRIVER is not set -# CONFIG_PKG_USING_NXP_IMXRT_DRIVER is not set -# end of NXP HAL & SDK Drivers - -# -# NUVOTON Drivers -# -# CONFIG_PKG_USING_NUVOTON_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_NUVOTON_SERIES_DRIVER is not set -# CONFIG_PKG_USING_NUVOTON_ARM926_LIB is not set -# end of NUVOTON Drivers - -# -# GD32 Drivers -# -# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set -# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set -# end of GD32 Drivers -# end of HAL & SDK Drivers - -# -# sensors drivers -# -# CONFIG_PKG_USING_LSM6DSM is not set -# CONFIG_PKG_USING_LSM6DSL is not set -# CONFIG_PKG_USING_LPS22HB is not set -# CONFIG_PKG_USING_HTS221 is not set -# CONFIG_PKG_USING_LSM303AGR is not set -# CONFIG_PKG_USING_BME280 is not set -# CONFIG_PKG_USING_BME680 is not set -# CONFIG_PKG_USING_BMA400 is not set -# CONFIG_PKG_USING_BMI160_BMX160 is not set -# CONFIG_PKG_USING_SPL0601 is not set -# CONFIG_PKG_USING_MS5805 is not set -# CONFIG_PKG_USING_DA270 is not set -# CONFIG_PKG_USING_DF220 is not set -# CONFIG_PKG_USING_HSHCAL001 is not set -# CONFIG_PKG_USING_BH1750 is not set -# CONFIG_PKG_USING_MPU6XXX is not set -# CONFIG_PKG_USING_AHT10 is not set -# CONFIG_PKG_USING_AP3216C is not set -# CONFIG_PKG_USING_TSL4531 is not set -# CONFIG_PKG_USING_DS18B20 is not set -# CONFIG_PKG_USING_DHT11 is not set -# CONFIG_PKG_USING_DHTXX is not set -# CONFIG_PKG_USING_GY271 is not set -# CONFIG_PKG_USING_GP2Y10 is not set -# CONFIG_PKG_USING_SGP30 is not set -# CONFIG_PKG_USING_HDC1000 is not set -# CONFIG_PKG_USING_BMP180 is not set -# CONFIG_PKG_USING_BMP280 is not set -# CONFIG_PKG_USING_SHTC1 is not set -# CONFIG_PKG_USING_BMI088 is not set -# CONFIG_PKG_USING_HMC5883 is not set -# CONFIG_PKG_USING_MAX6675 is not set -# CONFIG_PKG_USING_MAX31855 is not set -# CONFIG_PKG_USING_TMP1075 is not set -# CONFIG_PKG_USING_SR04 is not set -# CONFIG_PKG_USING_CCS811 is not set -# CONFIG_PKG_USING_PMSXX is not set -# CONFIG_PKG_USING_RT3020 is not set -# CONFIG_PKG_USING_MLX90632 is not set -# CONFIG_PKG_USING_MLX90382 is not set -# CONFIG_PKG_USING_MLX90393 is not set -# CONFIG_PKG_USING_MLX90392 is not set -# CONFIG_PKG_USING_MLX90394 is not set -# CONFIG_PKG_USING_MLX90397 is not set -# CONFIG_PKG_USING_MS5611 is not set -# CONFIG_PKG_USING_MAX31865 is not set -# CONFIG_PKG_USING_VL53L0X is not set -# CONFIG_PKG_USING_INA260 is not set -# CONFIG_PKG_USING_MAX30102 is not set -# CONFIG_PKG_USING_INA226 is not set -# CONFIG_PKG_USING_LIS2DH12 is not set -# CONFIG_PKG_USING_HS300X is not set -# CONFIG_PKG_USING_ZMOD4410 is not set -# CONFIG_PKG_USING_ISL29035 is not set -# CONFIG_PKG_USING_MMC3680KJ is not set -# CONFIG_PKG_USING_QMP6989 is not set -# CONFIG_PKG_USING_BALANCE is not set -# CONFIG_PKG_USING_SHT2X is not set -# CONFIG_PKG_USING_SHT3X is not set -# CONFIG_PKG_USING_SHT4X is not set -# CONFIG_PKG_USING_AD7746 is not set -# CONFIG_PKG_USING_ADT74XX is not set -# CONFIG_PKG_USING_MAX17048 is not set -# CONFIG_PKG_USING_AS7341 is not set -# CONFIG_PKG_USING_CW2015 is not set -# CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_PAJ7620 is not set -# CONFIG_PKG_USING_STHS34PF80 is not set -# CONFIG_PKG_USING_P3T1755 is not set -# CONFIG_PKG_USING_QMI8658 is not set -# CONFIG_PKG_USING_ICM20948 is not set -# end of sensors drivers - -# -# touch drivers -# -# CONFIG_PKG_USING_GT9147 is not set -# CONFIG_PKG_USING_GT1151 is not set -# CONFIG_PKG_USING_GT917S is not set -# CONFIG_PKG_USING_GT911 is not set -# CONFIG_PKG_USING_FT6206 is not set -# CONFIG_PKG_USING_FT5426 is not set -# CONFIG_PKG_USING_FT6236 is not set -# CONFIG_PKG_USING_XPT2046_TOUCH is not set -# CONFIG_PKG_USING_CST816X is not set -# CONFIG_PKG_USING_CST812T is not set -# end of touch drivers - -# CONFIG_PKG_USING_REALTEK_AMEBA is not set -# CONFIG_PKG_USING_BUTTON is not set -# CONFIG_PKG_USING_PCF8574 is not set -# CONFIG_PKG_USING_SX12XX is not set -# CONFIG_PKG_USING_SIGNAL_LED is not set -# CONFIG_PKG_USING_LEDBLINK is not set -# CONFIG_PKG_USING_LITTLED is not set -# CONFIG_PKG_USING_LKDGUI is not set -# CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_MULTI_INFRARED is not set -# CONFIG_PKG_USING_AGILE_BUTTON is not set -# CONFIG_PKG_USING_AGILE_LED is not set -# CONFIG_PKG_USING_AT24CXX is not set -# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set -# CONFIG_PKG_USING_PCA9685 is not set -# CONFIG_PKG_USING_ILI9341 is not set -# CONFIG_PKG_USING_I2C_TOOLS is not set -# CONFIG_PKG_USING_NRF24L01 is not set -# CONFIG_PKG_USING_RPLIDAR is not set -# CONFIG_PKG_USING_AS608 is not set -# CONFIG_PKG_USING_RC522 is not set -# CONFIG_PKG_USING_WS2812B is not set -# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set -# CONFIG_PKG_USING_MULTI_RTIMER is not set -# CONFIG_PKG_USING_MAX7219 is not set -# CONFIG_PKG_USING_BEEP is not set -# CONFIG_PKG_USING_EASYBLINK is not set -# CONFIG_PKG_USING_PMS_SERIES is not set -# CONFIG_PKG_USING_CAN_YMODEM is not set -# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set -# CONFIG_PKG_USING_QLED is not set -# CONFIG_PKG_USING_AGILE_CONSOLE is not set -# CONFIG_PKG_USING_LD3320 is not set -# CONFIG_PKG_USING_WK2124 is not set -# CONFIG_PKG_USING_LY68L6400 is not set -# CONFIG_PKG_USING_DM9051 is not set -# CONFIG_PKG_USING_SSD1306 is not set -# CONFIG_PKG_USING_QKEY is not set -# CONFIG_PKG_USING_RS485 is not set -# CONFIG_PKG_USING_RS232 is not set -# CONFIG_PKG_USING_NES is not set -# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set -# CONFIG_PKG_USING_VDEVICE is not set -# CONFIG_PKG_USING_SGM706 is not set -# CONFIG_PKG_USING_RDA58XX is not set -# CONFIG_PKG_USING_LIBNFC is not set -# CONFIG_PKG_USING_MFOC is not set -# CONFIG_PKG_USING_TMC51XX is not set -# CONFIG_PKG_USING_TCA9534 is not set -# CONFIG_PKG_USING_KOBUKI is not set -# CONFIG_PKG_USING_ROSSERIAL is not set -# CONFIG_PKG_USING_MICRO_ROS is not set -# CONFIG_PKG_USING_MCP23008 is not set -# CONFIG_PKG_USING_MISAKA_AT24CXX is not set -# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set -# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set -# CONFIG_PKG_USING_SOFT_SERIAL is not set -# CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_RFM300 is not set -# CONFIG_PKG_USING_IO_INPUT_FILTER is not set -# CONFIG_PKG_USING_LRF_NV7LIDAR is not set -# CONFIG_PKG_USING_AIP650 is not set -# CONFIG_PKG_USING_FINGERPRINT is not set -# CONFIG_PKG_USING_BT_ECB02C is not set -# CONFIG_PKG_USING_UAT is not set -# CONFIG_PKG_USING_ST7789 is not set -# CONFIG_PKG_USING_VS1003 is not set -# CONFIG_PKG_USING_X9555 is not set -# CONFIG_PKG_USING_SYSTEM_RUN_LED is not set -# CONFIG_PKG_USING_BT_MX01 is not set -# CONFIG_PKG_USING_RGPOWER is not set -# CONFIG_PKG_USING_BT_MX02 is not set -# CONFIG_PKG_USING_GC9A01 is not set -# CONFIG_PKG_USING_IK485 is not set -# CONFIG_PKG_USING_SERVO is not set -# CONFIG_PKG_USING_SEAN_WS2812B is not set -# CONFIG_PKG_USING_IC74HC165 is not set -# CONFIG_PKG_USING_IST8310 is not set -# CONFIG_PKG_USING_ST7789_SPI is not set -# CONFIG_PKG_USING_SPI_TOOLS is not set -# end of peripheral libraries and drivers - -# -# AI packages -# -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set -# CONFIG_PKG_USING_ELAPACK is not set -# CONFIG_PKG_USING_ULAPACK is not set -# CONFIG_PKG_USING_QUEST is not set -# CONFIG_PKG_USING_NAXOS is not set -# CONFIG_PKG_USING_R_TINYMAIX is not set -# CONFIG_PKG_USING_LLMCHAT is not set -# end of AI packages - -# -# Signal Processing and Control Algorithm Packages -# -# CONFIG_PKG_USING_APID is not set -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set -# CONFIG_PKG_USING_QPID is not set -# CONFIG_PKG_USING_UKAL is not set -# CONFIG_PKG_USING_DIGITALCTRL is not set -# CONFIG_PKG_USING_KISSFFT is not set -# end of Signal Processing and Control Algorithm Packages - -# -# miscellaneous packages -# - -# -# project laboratory -# -# end of project laboratory - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set -# end of samples: kernel and components samples - -# -# entertainment: terminal games and other interesting software packages -# -# CONFIG_PKG_USING_CMATRIX is not set -# CONFIG_PKG_USING_SL is not set -# CONFIG_PKG_USING_CAL is not set -# CONFIG_PKG_USING_ACLOCK is not set -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_DONUT is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_MORSE is not set -# end of entertainment: terminal games and other interesting software packages - -# CONFIG_PKG_USING_LIBCSV is not set -# CONFIG_PKG_USING_OPTPARSE is not set -# CONFIG_PKG_USING_FASTLZ is not set -# CONFIG_PKG_USING_MINILZO is not set -# CONFIG_PKG_USING_QUICKLZ is not set -# CONFIG_PKG_USING_LZMA is not set -# CONFIG_PKG_USING_RALARAM is not set -# CONFIG_PKG_USING_MULTIBUTTON is not set -# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set -# CONFIG_PKG_USING_CANFESTIVAL is not set -# CONFIG_PKG_USING_ZLIB is not set -# CONFIG_PKG_USING_MINIZIP is not set -# CONFIG_PKG_USING_HEATSHRINK is not set -# CONFIG_PKG_USING_DSTR is not set -# CONFIG_PKG_USING_TINYFRAME is not set -# CONFIG_PKG_USING_KENDRYTE_DEMO is not set -# CONFIG_PKG_USING_UPACKER is not set -# CONFIG_PKG_USING_UPARAM is not set -# CONFIG_PKG_USING_HELLO is not set -# CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_CRCLIB is not set -# CONFIG_PKG_USING_LIBCRC is not set -# CONFIG_PKG_USING_LWGPS is not set -# CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_DESIGN_PATTERN is not set -# CONFIG_PKG_USING_CONTROLLER is not set -# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set -# CONFIG_PKG_USING_MFBD is not set -# CONFIG_PKG_USING_SLCAN2RTT is not set -# CONFIG_PKG_USING_SOEM is not set -# CONFIG_PKG_USING_QPARAM is not set -# CONFIG_PKG_USING_CorevMCU_CLI is not set -# CONFIG_PKG_USING_DRMP is not set -# end of miscellaneous packages - -# -# Arduino libraries -# -# CONFIG_PKG_USING_RTDUINO is not set - -# -# Projects and Demos -# -# CONFIG_PKG_USING_ARDUINO_MSGQ_C_CPP_DEMO is not set -# CONFIG_PKG_USING_ARDUINO_SKETCH_LOADER_DEMO is not set -# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set -# CONFIG_PKG_USING_ARDUINO_RTDUINO_SENSORFUSION_SHIELD is not set -# CONFIG_PKG_USING_ARDUINO_NINEINONE_SENSOR_SHIELD is not set -# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set -# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set -# end of Projects and Demos - -# -# Sensors -# -# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31855 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MSA301 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_ITG3200 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_MP503 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set -# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set -# CONFIG_PKG_USING_ARDUINO_JARZEBSKI_MPU6050 is not set -# end of Sensors - -# -# Display -# -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_GFX_LIBRARY is not set -# CONFIG_PKG_USING_ARDUINO_U8G2 is not set -# CONFIG_PKG_USING_ARDUINO_TFT_ESPI is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ST7735 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SSD1306 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ILI9341 is not set -# CONFIG_PKG_USING_SEEED_TM1637 is not set -# end of Display - -# -# Timing -# -# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set -# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set -# CONFIG_PKG_USING_ARDUINO_TICKER is not set -# CONFIG_PKG_USING_ARDUINO_TASKSCHEDULER is not set -# end of Timing - -# -# Data Processing -# -# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set -# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set -# CONFIG_PKG_USING_ARDUINO_TENSORFLOW_LITE_MICRO is not set -# CONFIG_PKG_USING_ARDUINO_RUNNINGMEDIAN is not set -# end of Data Processing - -# -# Data Storage -# - -# -# Communication -# -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set -# end of Communication - -# -# Device Control -# -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TPA2016 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DRV2605 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS1841 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS3502 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set -# end of Device Control - -# -# Other -# -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MFRC630 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI5351 is not set -# end of Other - -# -# Signal IO -# -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set -# end of Signal IO - -# -# Uncategorized -# -# end of Arduino libraries -# end of RT-Thread online packages +CONFIG_PKG_USING_LVGL=y +CONFIG_PKG_LVGL_THREAD_STACK_SIZE=8192 +CONFIG_PKG_LVGL_THREAD_PRIO=10 +CONFIG_PKG_LVGL_DISP_REFR_PERIOD=33 # # RISC-V QEMU virt64 configs diff --git a/bsp/qemu-virt64-riscv/driver/board.c b/bsp/qemu-virt64-riscv/driver/board.c index 7250159e300..7bf6581b5d9 100644 --- a/bsp/qemu-virt64-riscv/driver/board.c +++ b/bsp/qemu-virt64-riscv/driver/board.c @@ -28,6 +28,14 @@ #include "interrupt.h" #endif /* RT_USING_SMP */ +#ifdef RT_USING_OFW +#include +#endif + +#ifdef RT_USING_DM +#include +#endif + #ifdef RT_USING_SMART #include "riscv_mmu.h" #include "mmu.h" @@ -46,6 +54,84 @@ struct mem_desc platform_mem_desc[] = { #endif +#ifdef RT_USING_OFW +#define QEMU_RISCV_FDT_MAX_SIZE (256 * 1024) + +extern rt_ubase_t boot_fdt_addr; + +static rt_align(8) rt_uint8_t qemu_riscv_fdt[QEMU_RISCV_FDT_MAX_SIZE]; +static void *qemu_riscv_fdt_ptr; + +static void qemu_riscv_fdt_copy_early(void) +{ + void *fdt; + rt_size_t fdt_size; + + if (!boot_fdt_addr) + { + rt_kprintf("OFW: boot FDT address is empty\n"); + return; + } + +#ifdef RT_USING_SMART + fdt = (void *)(boot_fdt_addr - PV_OFFSET); +#else + fdt = (void *)boot_fdt_addr; +#endif + + if (fdt_check_header(fdt)) + { + rt_kprintf("OFW: invalid boot FDT at %p\n", (void *)boot_fdt_addr); + return; + } + + fdt_size = fdt_totalsize(fdt); + if (fdt_size > sizeof(qemu_riscv_fdt)) + { + rt_kprintf("OFW: boot FDT is too large: %u > %u\n", + (unsigned int)fdt_size, (unsigned int)sizeof(qemu_riscv_fdt)); + return; + } + + rt_memcpy(qemu_riscv_fdt, fdt, fdt_size); + qemu_riscv_fdt_ptr = qemu_riscv_fdt; +} + +static void qemu_riscv_ofw_init(void) +{ + rt_err_t err; + + if (!qemu_riscv_fdt_ptr) + { + return; + } + + err = rt_fdt_prefetch(qemu_riscv_fdt_ptr); + if (err) + { + rt_kprintf("OFW: FDT prefetch failed: %d\n", err); + return; + } + + rt_fdt_scan_chosen_stdout(); + rt_fdt_scan_memory(); + + err = rt_fdt_unflatten(); + if (err) + { + rt_kprintf("OFW: FDT unflatten failed: %d\n", err); + } +} +#endif + +static void qemu_riscv_machine_shutdown(void) +{ + sbi_shutdown(); + + while (1) + ; +} + rt_uint64_t rt_hw_get_clock_timer_freq(void) { return 10000000ULL; @@ -73,6 +159,10 @@ void rt_hw_board_init(void) /* init data structure */ rt_hw_mmu_map_init(&rt_kernel_space, (void *)(IOREMAP_VEND - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, PV_OFFSET); +#ifdef RT_USING_OFW + qemu_riscv_fdt_copy_early(); +#endif + /* init page allocator */ rt_page_init(init_page_region); @@ -85,6 +175,15 @@ void rt_hw_board_init(void) rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); #endif +#ifdef RT_USING_OFW + qemu_riscv_ofw_init(); +#endif + +#ifdef RT_USING_DM + rt_dm_machine_shutdown = qemu_riscv_machine_shutdown; + rt_dm_machine_reset = qemu_riscv_machine_shutdown; +#endif + plic_init(); rt_hw_interrupt_init(); @@ -112,11 +211,10 @@ void rt_hw_board_init(void) #endif /* RT_USING_HEAP */ } +#ifndef RT_USING_DM void rt_hw_cpu_reset(void) { - sbi_shutdown(); - - while (1) - ; + qemu_riscv_machine_shutdown(); } MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); +#endif diff --git a/bsp/qemu-virt64-riscv/link_cpus.lds b/bsp/qemu-virt64-riscv/link_cpus.lds index 2659b2befb4..e4cd5b88712 100644 --- a/bsp/qemu-virt64-riscv/link_cpus.lds +++ b/bsp/qemu-virt64-riscv/link_cpus.lds @@ -1 +1 @@ -RT_CPUS_NR = 8; +RT_CPUS_NR = 1; diff --git a/bsp/qemu-virt64-riscv/rtconfig.h b/bsp/qemu-virt64-riscv/rtconfig.h index 430730ff68c..e5d6f721dd1 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.h +++ b/bsp/qemu-virt64-riscv/rtconfig.h @@ -72,7 +72,8 @@ /* end of rt_strnlen options */ /* end of klibc options */ -#define RT_NAME_MAX 24 +#define RT_NAME_MAX 32 +#define RT_USING_SMART #define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 @@ -88,6 +89,7 @@ #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 16384 #define RT_USING_CPU_USAGE_TRACER +#define RT_CPU_USAGE_CALC_INTERVAL_MS 200 /* kservice options */ @@ -120,13 +122,15 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x50201 +#define RT_USING_CONSOLE_OUTPUT_CTL +#define RT_VER_NUM 0x50300 #define RT_USING_STDC_ATOMIC #define RT_BACKTRACE_LEVEL_MAX_NR 32 /* end of RT-Thread Kernel */ #define ARCH_CPU_64BIT #define RT_USING_CACHE #define ARCH_MM_MMU +#define KERNEL_VADDR_START 0xffffffc000000000 #define ARCH_RISCV #define ARCH_RISCV_FPU #define ARCH_RISCV64 @@ -180,10 +184,24 @@ /* end of elm-chan's FatFs, Generic FAT Filesystem Module */ #define RT_USING_DFS_DEVFS #define RT_USING_DFS_ROMFS +#define RT_USING_DFS_PTYFS +#define RT_USING_PAGECACHE + +/* page cache config */ + +#define RT_PAGECACHE_COUNT 4096 +#define RT_PAGECACHE_ASPACE_COUNT 1024 +#define RT_PAGECACHE_PRELOAD 4 +#define RT_PAGECACHE_HASH_NR 1024 +#define RT_PAGECACHE_GC_WORK_LEVEL 90 +#define RT_PAGECACHE_GC_STOP_LEVEL 70 +/* end of page cache config */ /* end of DFS: device virtual file system */ /* Device Drivers */ +#define RT_USING_DM +#define RT_USING_DEV_BUS #define RT_USING_DEVICE_IPC #define RT_UNAMED_PIPE_NUMBER 64 #define RT_USING_SYSTEM_WORKQUEUE @@ -193,14 +211,18 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_CPUTIME -#define RT_USING_CPUTIME_RISCV -#define CPUTIME_TIMER_FREQ 10000000 +#define RT_USING_SERIAL_BYPASS +#define RT_USING_CLOCK_TIME +#define CLOCK_TIMER_FREQ 0 #define RT_USING_NULL #define RT_USING_ZERO #define RT_USING_RANDOM #define RT_USING_RTC #define RT_USING_SOFT_RTC + +/* Power Management (PM) Domains device drivers */ + +/* end of Power Management (PM) Domains device drivers */ #define RT_USING_VIRTIO #define RT_USING_VIRTIO10 #define RT_USING_VIRTIO_BLK @@ -209,8 +231,14 @@ #define RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR 4 #define RT_USING_VIRTIO_GPU #define RT_USING_VIRTIO_INPUT +#define RT_USING_OFW +#define RT_FDT_EARLYCON_MSG_SIZE 128 +#define RT_USING_OFW_BUS_RANGES_NUMBER 8 #define RT_USING_PIN -#define RT_USING_KTIME +#define RT_USING_CLK + +/* SoC (System on Chip) Drivers */ + /* end of Device Drivers */ /* C/C++ and POSIX layer */ @@ -233,6 +261,9 @@ #define RT_USING_POSIX_STDIO #define RT_USING_POSIX_POLL #define RT_USING_POSIX_SELECT +#define RT_USING_POSIX_EPOLL +#define RT_USING_POSIX_SIGNALFD +#define RT_SIGNALFD_MAX_NUM 10 #define RT_USING_POSIX_TERMIOS #define RT_USING_POSIX_AIO #define RT_USING_POSIX_DELAY @@ -320,6 +351,10 @@ /* Utilities */ +#define RT_USING_UTEST +#define UTEST_THR_STACK_SIZE 4096 +#define UTEST_THR_PRIORITY 20 +#define RT_UTEST_MAX_OPTIONS 64 #define RT_USING_RESOURCE_ID #define RT_USING_ADT #define RT_USING_ADT_AVL @@ -332,11 +367,23 @@ #define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000 #define RT_PAGE_MAX_ORDER 11 +#define RT_USING_MEMBLOCK +#define RT_INIT_MEMORY_REGIONS 128 /* Debugging */ /* end of Debugging */ /* end of Memory management */ +#define RT_USING_LWP +#define LWP_USING_RUNTIME +#define RT_LWP_MAX_NR 30 +#define LWP_TASK_STACK_SIZE 16384 +#define RT_CH_MSG_MAX_NR 1024 +#define LWP_TID_MAX_NR 64 +#define RT_LWP_SHM_MAX_NR 64 +#define RT_USING_LDSO +#define LWP_USING_TERMINAL +#define LWP_PTY_MAX_PARIS_LIMIT 64 /* Using USB legacy version */ @@ -346,207 +393,10 @@ /* RT-Thread Utestcases */ /* end of RT-Thread Utestcases */ - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - -/* end of Marvell WiFi */ - -/* Wiced WiFi */ - -/* end of Wiced WiFi */ - -/* CYW43012 WiFi */ - -/* end of CYW43012 WiFi */ - -/* BL808 WiFi */ - -/* end of BL808 WiFi */ - -/* CYW43439 WiFi */ - -/* end of CYW43439 WiFi */ -/* end of Wi-Fi */ - -/* IoT Cloud */ - -/* end of IoT Cloud */ -/* end of IoT - internet of things */ - -/* security packages */ - -/* end of security packages */ - -/* language packages */ - -/* JSON: JavaScript Object Notation, a lightweight data-interchange format */ - -/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */ - -/* XML: Extensible Markup Language */ - -/* end of XML: Extensible Markup Language */ -/* end of language packages */ - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - -/* end of LVGL: powerful and easy-to-use embedded GUI library */ - -/* u8g2: a monochrome graphic library */ - -/* end of u8g2: a monochrome graphic library */ -/* end of multimedia packages */ - -/* tools packages */ - -/* end of tools packages */ - -/* system packages */ - -/* enhanced kernel services */ - -/* end of enhanced kernel services */ - -/* acceleration: Assembly language or algorithmic acceleration packages */ - -/* end of acceleration: Assembly language or algorithmic acceleration packages */ - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - -/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - -/* Micrium: Micrium software products porting for RT-Thread */ - -/* end of Micrium: Micrium software products porting for RT-Thread */ -/* end of system packages */ - -/* peripheral libraries and drivers */ - -/* HAL & SDK Drivers */ - -/* STM32 HAL & SDK Drivers */ - -/* end of STM32 HAL & SDK Drivers */ - -/* Infineon HAL Packages */ - -/* end of Infineon HAL Packages */ - -/* Kendryte SDK */ - -/* end of Kendryte SDK */ - -/* WCH HAL & SDK Drivers */ - -/* end of WCH HAL & SDK Drivers */ - -/* AT32 HAL & SDK Drivers */ - -/* end of AT32 HAL & SDK Drivers */ - -/* HC32 DDL Drivers */ - -/* end of HC32 DDL Drivers */ - -/* NXP HAL & SDK Drivers */ - -/* end of NXP HAL & SDK Drivers */ - -/* NUVOTON Drivers */ - -/* end of NUVOTON Drivers */ - -/* GD32 Drivers */ - -/* end of GD32 Drivers */ -/* end of HAL & SDK Drivers */ - -/* sensors drivers */ - -/* end of sensors drivers */ - -/* touch drivers */ - -/* end of touch drivers */ -/* end of peripheral libraries and drivers */ - -/* AI packages */ - -/* end of AI packages */ - -/* Signal Processing and Control Algorithm Packages */ - -/* end of Signal Processing and Control Algorithm Packages */ - -/* miscellaneous packages */ - -/* project laboratory */ - -/* end of project laboratory */ - -/* samples: kernel and components samples */ - -/* end of samples: kernel and components samples */ - -/* entertainment: terminal games and other interesting software packages */ - -/* end of entertainment: terminal games and other interesting software packages */ -/* end of miscellaneous packages */ - -/* Arduino libraries */ - - -/* Projects and Demos */ - -/* end of Projects and Demos */ - -/* Sensors */ - -/* end of Sensors */ - -/* Display */ - -/* end of Display */ - -/* Timing */ - -/* end of Timing */ - -/* Data Processing */ - -/* end of Data Processing */ - -/* Data Storage */ - -/* Communication */ - -/* end of Communication */ - -/* Device Control */ - -/* end of Device Control */ - -/* Other */ - -/* end of Other */ - -/* Signal IO */ - -/* end of Signal IO */ - -/* Uncategorized */ - -/* end of Arduino libraries */ -/* end of RT-Thread online packages */ +#define PKG_USING_LVGL +#define PKG_LVGL_THREAD_STACK_SIZE 8192 +#define PKG_LVGL_THREAD_PRIO 10 +#define PKG_LVGL_DISP_REFR_PERIOD 33 /* RISC-V QEMU virt64 configs */ @@ -561,4 +411,6 @@ #define ENABLE_FPU #define __STACKSIZE__ 16384 +#define PKG_USING_LWEXT4 +#define RT_USING_DFS_LWEXT4 #endif diff --git a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c index 90b87a178b4..1f15adad7c7 100644 --- a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c @@ -444,7 +444,7 @@ int dfs_elm_open(struct dfs_file *file) } file->vnode->data = dir; - rt_mutex_init(&file->vnode->lock, file->dentry->pathname, RT_IPC_FLAG_PRIO); + rt_mutex_init(&file->vnode->lock, "elm_vn", RT_IPC_FLAG_PRIO); return RT_EOK; } else @@ -485,7 +485,7 @@ int dfs_elm_open(struct dfs_file *file) file->vnode->size = f_size(fd); file->vnode->type = FT_REGULAR; file->vnode->data = fd; - rt_mutex_init(&file->vnode->lock, file->dentry->pathname, RT_IPC_FLAG_PRIO); + rt_mutex_init(&file->vnode->lock, "elm_vn", RT_IPC_FLAG_PRIO); if (file->flags & O_APPEND) { diff --git a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c index 1dc1fd54f9e..79039b8acbf 100644 --- a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c +++ b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c @@ -455,7 +455,7 @@ static int dfs_tmpfs_open(struct dfs_file *file) RT_ASSERT(file->vnode->ref_count > 0); if(file->vnode->ref_count == 1) { - rt_mutex_init(&file->vnode->lock, file->dentry->pathname, RT_IPC_FLAG_PRIO); + rt_mutex_init(&file->vnode->lock, "tmp_vn", RT_IPC_FLAG_PRIO); } return 0; diff --git a/components/drivers/sdio/dev_block.c b/components/drivers/sdio/dev_block.c index d4f8f62885d..ed4c4c3cad5 100644 --- a/components/drivers/sdio/dev_block.c +++ b/components/drivers/sdio/dev_block.c @@ -375,7 +375,6 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) host->max_dma_segs * host->max_seg_size, host->max_blk_count * host->max_blk_size) >> 9; blk_dev->geometry.bytes_per_sector = 1 << 9; - blk_dev->geometry.block_size = card->card_blksize; blk_dev->geometry.sector_count = card->card_capacity * (1024 / 512); /* Set blk size before partitions probe, Why? */ @@ -383,6 +382,7 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) { goto _fail; } + blk_dev->geometry.block_size = blk_dev->geometry.bytes_per_sector; rt_thread_mdelay(1); #ifdef RT_USING_DM diff --git a/components/lwp/lwp_elf.c b/components/lwp/lwp_elf.c index c6809f8cae2..3ec49bd227e 100644 --- a/components/lwp/lwp_elf.c +++ b/components/lwp/lwp_elf.c @@ -616,6 +616,15 @@ static int elf_zero_bss(struct rt_lwp *lwp, int fd, const Elf_Phdr *phdr, rt_uba * @return -RT_ERROR if memory mapping fails. * @return -ENOMEM if memory allocation fails. */ +static size_t elf_prot_from_pflags(uint32_t p_flags) +{ + size_t prot = PROT_NONE; + if (p_flags & PF_R) prot |= PROT_READ; + if (p_flags & PF_W) prot |= PROT_WRITE; + if (p_flags & PF_X) prot |= PROT_EXEC; + return prot; +} + static int elf_file_mmap(elf_load_info_t *load_info, elf_info_t *elf_info, rt_ubase_t *elfload_addr, rt_uint32_t map_size, rt_ubase_t *load_base) { @@ -626,7 +635,6 @@ static int elf_file_mmap(elf_load_info_t *load_info, elf_info_t *elf_info, rt_ub const Elf_Phdr *tmp_phdr = phdr; /* Current program header */ int fd = elf_info->fd; /* File descriptor for ELF file */ rt_ubase_t load_addr; /* Calculated load address */ - size_t prot = PROT_READ | PROT_WRITE; /* Memory protection flags */ size_t flags = MAP_FIXED | MAP_PRIVATE; /* Memory mapping flags */ /* Iterate through all program headers */ @@ -659,8 +667,8 @@ static int elf_file_mmap(elf_load_info_t *load_info, elf_info_t *elf_info, rt_ub flags &= ~MAP_FIXED; } - /* Map the segment into memory */ - map_va = elf_map(load_info->lwp, tmp_phdr, fd, load_addr, prot, flags, map_size); + /* Map the segment into memory with correct permissions */ + map_va = elf_map(load_info->lwp, tmp_phdr, fd, load_addr, elf_prot_from_pflags(tmp_phdr->p_flags), flags, map_size); if (!map_va) { LOG_E("%s : elf_map failed", __func__); diff --git a/components/mm/mm_fault.c b/components/mm/mm_fault.c index 01e32fed95c..f659cb8456b 100644 --- a/components/mm/mm_fault.c +++ b/components/mm/mm_fault.c @@ -33,6 +33,9 @@ static int _fetch_page(rt_varea_t varea, struct rt_aspace_fault_msg *msg) err = rt_varea_map_with_msg(varea, msg); err = (err == RT_EOK ? MM_FAULT_FIXABLE_TRUE : MM_FAULT_FIXABLE_FALSE); } + else + { + } return err; } @@ -101,6 +104,10 @@ static int _exec_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg *m RT_ASSERT(!(varea->flag & MMF_PREFETCH)); err = _fetch_page(varea, msg); } + else + { + /* signal a fault to user? */ + } return err; } diff --git a/libcpu/risc-v/common64/mmu.c b/libcpu/risc-v/common64/mmu.c index fc1a348efb9..60ca9f423a0 100644 --- a/libcpu/risc-v/common64/mmu.c +++ b/libcpu/risc-v/common64/mmu.c @@ -105,15 +105,6 @@ void rt_hw_aspace_switch(rt_aspace_t aspace) current_mmu_table[rt_hw_cpu_id()] = (void *)ptr; #endif -#ifdef ARCH_REMAP_KERNEL - /* - * Bring-up guard: keep low physical memory identity-mapped while switching - * away from the early page table. This validates whether any low-address - * boot context is still live during the transition. - */ - ((rt_ubase_t *)ptr)[0] = COMBINEPTE(0, MMU_MAP_EARLY); - rt_hw_cpu_dcache_clean((void *)ptr, sizeof(rt_ubase_t)); -#endif write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | ((rt_ubase_t)page_table >> PAGE_OFFSET_BIT)); rt_hw_tlb_invalidate_all_local(); @@ -1009,6 +1000,19 @@ void *rt_hw_mmu_pgtbl_create(void) return RT_NULL; } rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE); + +#ifdef RT_USING_SMART + { + int i; + int start_idx = USER_VADDR_START >> VPN2_SHIFT; + int end_idx = USER_VADDR_TOP >> VPN2_SHIFT; + for (i = start_idx; i <= end_idx; i++) + { + mmu_table[i] = 0; + } + } +#endif + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); return mmu_table; diff --git a/libcpu/risc-v/common64/startup_gcc.S b/libcpu/risc-v/common64/startup_gcc.S index dde3c092408..63b0ff49b5b 100644 --- a/libcpu/risc-v/common64/startup_gcc.S +++ b/libcpu/risc-v/common64/startup_gcc.S @@ -18,6 +18,10 @@ .global boot_hartid /* global varible rt_boot_hartid in .data section */ boot_hartid: .word 0xdeadbeef + .align 3 + .global boot_fdt_addr +boot_fdt_addr: + .dword 0 .global _start .section ".start", "ax" @@ -41,6 +45,8 @@ _start: #endif mv t1, a0 /* get hartid in S-mode frome a0 register */ sw t1, (t0) /* store t1 register low 4 bits in memory address which is stored in t0 */ + la t0, boot_fdt_addr /* QEMU/OpenSBI passes FDT address in a1 */ + sd a1, (t0) #ifdef RT_USING_SMP system_init: @@ -236,4 +242,4 @@ _start_link_addr: .space RT_CPUS_NR * 5 * page_size #endif -#endif /* ARCH_MM_MMU */ \ No newline at end of file +#endif /* ARCH_MM_MMU */