Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
risc-v_RISCV
rt-smart
博流_BL61x_BL808
零基础上手rt-smart适配bsp
发布于 2023-05-13 19:46:52 浏览:1637
订阅该版
[tocm] RT-Thread Smart(简称rt-smart)是基于RT-Thread操作系统衍生,面向带MMU(Memory Management Unit),中高端应用的芯片,例如ARM Cortex-A,MIPS,带MMU的RISC-V芯片等。rt-smart在RT-Thread操作系统的基础上启用独立、完整的进程方式,同时以混合微内核模式执行。 ![rt-smart.png](https://oss-club.rt-thread.org/uploads/20230513/779e7b1472dfae3bb4ec81eca12f91d7.png.webp) 自 V5.0.0 起,rt-smart 分支已合并至 rt-thread master 分支上,可以在 bsp 下通过 menuconfig 启用`Enable RT-Thread Smart (microkernel on kernel/userland)`选项即可使用 rt-smart。 目前有 allwinner 下 d1/d1s , bouffalo_lab 下的 bl808/d0 ,raspi4-64,qemu-virt64-aarch64,qemu-virt64-riscv 等多个bsp已经支持 rt-smart。 本文通过介绍 RISC-V64 架构的 BL808,介绍适配 rt-smart 与 rt-thread 区别点,从零开始适配一个支持 rt-smart 的 bsp。 BL808是RISC-V三核异构架构,分别为m0(E907/RV32IMA)、lp(E902/RV32E[M]C)、d0,(C906/RV64IMA[FD]C[V])都采用的是平头哥的玄铁RISC-V核, RISC-V有3种工作状态,分别为机器模式machine mode(M态)、监督模式supervisor mode(S态)、用户模式user mode(U态)。 RISC-V架构定义机器模式为必选模式,另外两种模式为可选模式,通过不同的模式组合可以实现不同的系统,C906同时支持M/S/U态。 rt-smart工作在S态,需要MMU支持。C906 虚拟内存管理 MMU兼容 RISC-V Sv39 虚拟内存系统。rt-smart和工作在M态的RT-Thread 标准版有较多不同。 # 启动 在适配RT-Thread标准版本,芯片工作在M态(芯片启动默认状态),启动文件一般采用原厂SDK提供的启动文件完成硬件初始化(操作M态下的寄存器)、bss初始化等软件初始化工作,跳转到entry()函数即可开始rt-thread流程,剩下的工作在rt_hw_board_init()函数中完成。 bl808-d0核运行在S态,芯片启动默认工作在M态,芯片需要通过一些流程,将opensbi、kernel等相关代码从flash上copy到ram上,并通过opensbi芯片切换到S态。opensbi完成一些了配置后跳转到rt-smart(kernel)。 rt-smart此时工作在S态,不能操作任何M态下的寄存器,只能操作S态下的寄存器,否则会发生异常。 C906启动文件startup_gcc.S在libcpu/risc-v/t-head/c906目录下,在bsp下需要完成init_bss()、primary_cpu_entry()两个函数,这两个函数作用为清除bss区、禁止全局中断,调用entry()进入rt-smart主流程。 此外 startup_gcc.S 会调用 `__stack_start__` 变量和 `__STACKSIZE__` 宏,赋值给 sp , `__STACKSIZE__` 宏在 Kconfig 配置,内置脚本会自动生成 link_stacksize.lds 文件,并在 link.ld 文件中被调用,`__stack_start__` 在 link.ld 中自动生成。 进入entry后,rt-thread初始化流程基本一致,内核已经通过RT_USING_SMART宏作了处理,在Kconfig开启该宏即可。 # ld文件 RT-Thread标准版适配的时候,一般也采用原厂SDK中提供的ld文件,做一些适当的修改后即可使用。 bl808-d0核运行在S态下,启动文件和ld文件都不能使用原厂SDK中的文件。RISC-V可参考 qemu-virt64-riscv 、 allwinner 下 d1/d1s 等bsp,复制对应的 link.ld 文件,并根据自己的芯片、开发板内存修改 Memory layout。 ``` MEMORY { SRAM : ORIGIN = 0x50100000, LENGTH = 63M } SECTIONS { . = 0x50100000 ; } ``` 该地址为rt-smart程序开始地址,与bootload、opensbi等跳转地址一致。 # 中断 bl808-d0核工作在S态,中断相关操作与M态不一样,同样不能使用原厂SDK中的相关接口,rt-thread提供相关S态下中断管理的一系列函数。包括: ``` rt_hw_interrupt_init() rt_hw_interrupt_install() rt_hw_interrupt_mask() rt_hw_interrupt_umask() ``` 操作S态下的外设中断时需使用这一套接口,相关函数实现在`libcpu/risc-v/t-head/c906/interrupt.c`文件下。 # Kconfig 配置 - bl808-d0核运行在S态,必须开启ARCH_RISCV64、ARCH_MM_MMU、RT_USING_CACHE这三个宏,否则会编译不过。 bl808相关配置在bsp/bouffalo_lab/bl808/d0/board/Kconfig下。 ``` config BSP_USING_BL808 bool select ARCH_RISCV64 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select RT_USING_CACHE select ARCH_MM_MMU select BL808_CORE_D0 default y ``` - 同时在上文启动相关流程中讲到需要配置栈空间大小 ``` config __STACKSIZE__ int "stack size for interrupt" default 4096 ``` 相关配置在`bsp/bouffalo_lab/bl808/d0/Kconfig`下。 - 芯片相关PLIC地址、IRQ数量、STimer频率配置 C906相关中断管理、STimer管理都已经在`libcpu/risc-v/t-head/c906`下实现,需要对相关地址、数量通过宏配置。相关配置在`bsp/bouffalo_lab/bl808/d0/board/Kconfig`下 ``` config C906_PLIC_PHY_ADDR hex default 0xe0000000 config IRQ_MAX_NR int default 64 config TIMER_CLK_FREQ int default 1000000 ``` 完成以上配置, bl808-d0 核可以正常工作在S态下,可以使用 RT-Thread 标准版,需要使用 rt-smart 版还需要完成一些 rt-smart 对应的 mmu 初始化、页表建立等工作。 # SMART初始化 - bl808-d0核可以正常工作在S态下,可以通过在Kconfig中选中 `RT-Thread Kernel` -> `Enable RT-Thread Smart (microkernel on kernel/userland)` 即可是能rt-smart。 使能 rt-smart 后,在Kconfig根选项中,会显示 `The virtural address of kernel start` 选项,该地址为内核虚拟地址起始地点,bl808-d0核配置为`0x50000000`。 - heap和页表地址配置 在board.h中根据实际芯片或开发板当前RAM情况做配置 ``` extern unsigned int __bss_start; extern unsigned int __bss_end; #ifndef RT_USING_SMART #define KERNEL_VADDR_START 0x0 #endif #define RT_HW_HEAP_BEGIN ((void *)&__bss_end) #define RT_HW_HEAP_END ((void *)(RT_HW_HEAP_BEGIN + 16 * 1024 * 1024)) #define RT_HW_PAGE_START RT_HW_HEAP_END #define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + 64 * 1024 * 1024)) ``` bl808芯片内封了64M高速psarm,将64M内存做了适当划分,分给heap和page。 并在board.c中做了相关page映射: ``` rt_region_t init_page_region = {(rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END}; ``` - mmu页表相关地址配置 ``` struct mem_desc platform_mem_desc[] = { {KERNEL_VADDR_START, (rt_size_t)RT_HW_PAGE_END - 1, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM}, {0x1000, ((KERNEL_VADDR_START - 1) & 0xfffff000) - 1, (rt_size_t)ARCH_MAP_FAILED, DEVICE_MEM}, }; #define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0])) ``` 其中DEVICE_MEM项将0x1000~0x4FFF1000做了1:1映射,这样操作 bl808 外设的时候,在 0x50000000 之前的寄存器就不需要在做 ioremap 了。否则会出现如下异常 ``` Unhandled Exception 7:Store/AMO Access Fault scause:0x0000000000000007,stval:0x0000000010201000,sepc:0x00000000500248b4 --------------Dump Registers----------------- Function Registers: ra(x1) = 0x0000000050024cca user_sp = 0x000000005003f840 gp(x3) = 0x000000005003c0a0 tp(x4) = 0x0000000000000000 Temporary Registers: t0(x5) = 0x0000000000004000 t1(x6) = 0x0000000000000000 t2(x7) = 0x0000000000000001 t3(x28) = 0x0000000000000000 t4(x29) = 0x0000000000000000 t5(x30) = 0x0000000000000000 t6(x31) = 0x0000000000000000 Saved Registers: s0/fp(x8) = 0x000000005003f860 s1(x9) = 0x0000000000000000 s2(x18) = 0x0000000000000000 s3(x19) = 0x0000000000000000 s4(x20) = 0x0000000000000000 s5(x21) = 0x0000000000000000 s6(x22) = 0x0000000000000000 s7(x23) = 0x0000000000000000 s8(x24) = 0x0000000000000000 s9(x25) = 0x0000000000000000 s10(x26) = 0x0000000000000000 s11(x27) = 0x0000000000000000 Function Arguments Registers: a0(x10) = 0x0000000000000000 a1(x11) = 0x0000000010201000 a2(x12) = 0x0000000000000004 a3(x13) = 0x0000000000000080 a4(x14) = 0x0000000000000000 a5(x15) = 0x0000000010201000 a6(x16) = 0xfefefefefefefeff a7(x17) = 0x0000000000000007 sstatus = 0x0000000200040100 Supervisor Interrupt Disabled Last Time Supervisor Interrupt Disabled Last Privilege is Supervisor Mode Permit to Access User Page Not Permit to Read Executable-only Page satp = 0x800000000005006f Current Page Table(Physical) = 0x000000005006f000 Current ASID = 0x0000000000000000 Mode = Page-based 39-bit Virtual Addressing Mode -----------------Dump OK--------------------- --------------Thread list-------------- current thread: (NULL) --------------Backtrace-------------- riscv64-unknown-linux-musl-addr2line -e rtthread.elf -a -f 00000000500248b0 ``` - 在rt_hw_board_init()函数中,进入函数后,添加 ``` #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 */ rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, NUM_MEM_DESC); #endif ``` 对mmu做地址映射,建立页表等初始化工作,并在最后启动 mmu。 然后与RT-Thread标准版流程一致,完成heap、interrupt、uart等硬件初始化后,就可以正常启动rt-smart了。 # bl808 rt-thread bsp 当前 bl80 8的 bsp 已实现三核同时启动,位于 bsp/bouffalo_lab/bl808,三核分别采用了不同的 RT-Thread 版本。 | 名称 | CPU核 | RT-Thread版本 | | ---- | ----- | ---------------- | | M0 | E907(RV32IMA) | RT-Thread 标准版 | | LP | E902(RV32E[M]C) | RT-Thread Nano | | D0 | C906(RV64IMA[FD]C[V]) | RT-SMART | bl808-bsp简单使用说明可参考[https://club.rt-thread.org/ask/article/80a1c03cbccc6ca7.html](https://club.rt-thread.org/ask/article/80a1c03cbccc6ca7.html)
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
燕十三
这家伙很懒,什么也没写!
文章
12
回答
15
被采纳
0
关注TA
发私信
相关文章
1
studio能否支持risc-v的工程,包括调试。
2
移植rt-nano至risc-v时,无法在main函数创建用户线程
3
risc-v移植rtthread,程序莫名跳转到异常Exception
4
GD32VF103出现to free a bad data block:错误
5
rtt os riscv Store address misaligned异常
6
仅实现机器模式的芯片是否可以移植RT-THREAD系统
7
nano版本移植finsh(基于risc-v)
8
C++在多核下cout打印引起崩溃
9
RT-SMART求助
10
RT-Thread在RISC-V架构的芯片上有成熟的市场项目吗?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部