0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

零基础上手rt-smart适配bsp

冬至子 来源:燕十三 作者:燕十三 2023-08-08 10:34 次阅读

RT-Thread Smart(简称rt-smart)是基于RT-Thread操作系统衍生,面向带MMU(Memory Management Unit),中高端应用的芯片,例如ARM Cortex-A,MIPS,带MMU的RISC-V芯片等。rt-smart在RT-Thread操作系统的基础上启用独立、完整的进程方式,同时以混合微内核模式执行。

1.jpg

自 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主流程。

此外 startupgcc.S 会调用 stack_start 变量和 STACKSIZE 宏,赋值给 sp , STACKSIZE 宏在 Kconfig 配置,内置脚本会自动生成 linkstacksize.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 版本。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM处理器
    +关注

    关注

    6

    文章

    360

    浏览量

    41736
  • 虚拟机
    +关注

    关注

    1

    文章

    916

    浏览量

    28180
  • MMU
    MMU
    +关注

    关注

    0

    文章

    91

    浏览量

    18287
  • RT-Thread
    +关注

    关注

    31

    文章

    1288

    浏览量

    40112
  • RISC-V
    +关注

    关注

    45

    文章

    2277

    浏览量

    46150
收藏 人收藏

    评论

    相关推荐

    通过Uboot TFTP启动rt-smart内核

    介绍Windows下通过 Uboot  TFTP 方式下载和启动rt-smart 内核
    的头像 发表于 06-30 12:34 3710次阅读
    通过Uboot TFTP启动<b class='flag-5'>rt-smart</b>内核

    RT-Smart的资料合集

    时,需要使用 GDB 直接进行代码调试。本文档记录了以 RT-Thread qemu-vexpress-a9 BSP 为例,使用 GDB 对 RT-Smart 进行代码调试的方法。
    发表于 03-22 15:06

    rt-smart中断阻塞问题是怎么引起的

    rt-smart 中断阻塞问题如何解决?该问题是怎么引起的?为了测试rt-smart的实时性,测试了一下中断的稳定性。用systick的1ms中断做测试源。平时都正常的,但是发现打印时,波形老是抖动
    发表于 03-25 09:56

    快速上手RT-Thread Smart入门指南

    ,带 MMU 的 RISC-V 芯片等。rt-smartRT-Thread 操作系统的基础上启用独立、完整的进程方式,同时以混合微内核模式执行。rt-smart 软件包是
    发表于 04-01 17:38

    基于RT-Thread操作系统衍生rt-smart实时操作系统简介

    ,例如 ARM Cortex-A 系列芯片,MIPS 芯片,带 MMU 的 RISC-V 芯片等。rt-smartRT-Thread 操作系统的基础上启用独立、完整的进程方式,同时以混合微内核模式
    发表于 06-22 17:56

    RT-Thread Smart快速上手入门指南

    /mkromfs.py root ../kernel/bsp/qemu-vexpress-a9/applications/romfs.c编译rt-smart内核1cd rt-smart/kernel
    发表于 09-08 15:40

    RT-Thread Smart快速上手

    或其他开发中。目录说明编译内核进入到rt-smart/kernel/kernel/bsp/allwinner_tina目录中,运行scons\\rt-smart\\kernel\\bsp
    发表于 10-26 14:48

    D1S使用rt-smart驱动OLED

    原文链接:https://bbs.elecfans.com/jishu_2344522_1_1.htmlD1S使用rt-smart驱动OLED前言本次使用RT-Smart的IIC驱动OLED屏幕
    发表于 04-03 11:27

    树莓派上rt-smart的应用编程入门

    我们从现在开始会逐步连载RT-Thread Smart(简称rt-smart,甚至有时会称为smart os)的介绍文章,旨在让大家认识,接触到sm
    的头像 发表于 05-13 14:10 3164次阅读
    树莓派上<b class='flag-5'>rt-smart</b>的应用编程入门

    rt-smart移植分析:从树莓派3b入手

    移植rt-smart到最新的板子上具体需要注意哪些细节,哪些才是移植rt-smart的关键点?本文从树莓派3b上移植rt-smart的角度,从头分析rt-sm...
    发表于 01-25 18:48 0次下载
    <b class='flag-5'>rt-smart</b>移植分析:从树莓派3b入手

    RT-Thread Smart 上手指南

    RT-Thread Smart(简称rt-smart)是基于RT-Thread操作系统衍生的新分支,面向带MMU,中高端应用的芯片,例如ARM Cortex-A系列芯片,MIPS...
    发表于 01-25 20:09 13次下载
    <b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b> <b class='flag-5'>上手</b>指南

    优雅的在D1S上运行RT-Smart

    前言 最近在学习 RT-Smart ,正巧有在全志开发者william hill官网 看到这么一篇帖子【惊】在麻雀上运行国产rt-smart系统,看到很多人都在关注 D1S 在 Smart 上的运行情况。如今该 BSP
    的头像 发表于 11-16 20:15 2886次阅读

    丝滑的在RT-Smart用户态运行LVGL

    开发流程 1、RT-Smart 环境搭建 下载 RT-Smart 用户态应用代码: 1 git clone https: //github.com/RT-Thread/userapps.git
    的头像 发表于 11-22 20:20 1268次阅读

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码仓库地址https://gitee.com/rtthread/rt
    的头像 发表于 02-08 21:40 1159次阅读

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码
    的头像 发表于 10-12 17:26 619次阅读
    <b class='flag-5'>RT-Smart</b> riscv64汇编注释