手把手带你做 LiteOS 的树莓派移植
摘要:树莓派是英国的慈善组织“Raspberry Pi 基金会”开发的一款基于 arm 的微型电脑主板。本文介绍基于 LiteOS 的树莓派移植过程。
本文分享自华为云社区《2021 LiteOS树莓派移植指南(一)》,作者: Lionlace 。
硬件信息
开发板:Raspberry Pi 2 Model B(树莓派 2B)
CPU:Broadcom BCM2836
主频:900MHz
内存:1GB
GPU:VideoCore IV GPU
移植准备
硬件环境
本实验使用了 Raspberry Pi 2 Model B 开发板、USB 转 TTL 模块、SDcard 和读卡器。
软件环境
本实验需要先按照码云上的 LiteOS 教程搭建好 linux 环境(make、arm-none-eabi 编译工具链)。环境搭建教程:https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Build_and_IDE.md
本实验需要下载官方的镜像制作工具(Raspberry Pi Imager),下载地址:https://www.raspberrypi.org/software/
移植步骤
创建目录结构
在 targets 目录下新增 Raspberry_Pi2B 目录,参考与 cortex-A7 架构差异较小的 realview-pbx-a9 的启动流程进行移植。
将 realview-pbx-a9 目录下的 reset_vector.S 和 main.c 拷贝到 Raspberry_Pi2B 目录下并将 reset_vector.S 重命名为 los_startup_gcc.S。
将 realview-pbx-a9 目录下的 board.ld 和 liteos.ld 中内容合并到 Raspberry_Pi2B 目录下 liteos.ld 文件中。
拷贝 realview-pbx-a9 目录下 include、os_adapt 文件夹到 Raspberry_Pi2B 目录下,并删除不需要的 dma 相关头文件 include/asm/dma.h。
关闭 SMP 和 MMU
在 los_startup_gcc.S 文件中增加关闭 SMP 和 MMU 的代码。
关闭 SMP 功能
上表是 ACTLR(Auxiliary Control Register)寄存器 bit6 功能描述信息,了解更多寄存器相关信息可以参考 Cortex-A7 MPCore Technical Reference Manual。
关闭 MMU 的功能
上表是 SCTLR (System Control Register)寄存器 bit0 功能描述信息,了解更多寄存器相关信息可以参考 Cortex-A7MPCore Technical Reference Manual。
删除调用 SMP 相关函数
删除 los_startup_gcc.S 中的 enable_scu 和 secondary_cpu_start。
使能 FPU/ENON
配置 FPU/NEON:
以上前两行代码用于设置 CP10 和 CP11 的访问权限,后两行用于设置寄存器 FPEXC 的 EN 位来使能 FPU。
注:在 arm 的协处理器设计中,最多可以支持 16 个协处理器,通常被命名为 cp0~cp15。
上表为寄存器 CPACR bit20-23 功能描述信息,了解更多寄存器相关信息可以参考 Cortex-A7 MPCore Technical Reference Manual。
修改链接脚本
树莓派启动时首先加载 SD 卡中的 start.elf 文件,该程序会读取 SD 卡中的 config.txt 文件内容,该文件记录了一些配置信息。如果没有设置启动地址和启动文件,则默认会加载 kernel8.img 文件,该文件是 aarch64 编译的程序,启动地址为 0x80000。如果 SD 卡中无 kernel8.img 镜像文件,则会加载 kernel7.img 镜像文件,该文件是 32 位编译器编译的程序,启动地址为 0x8000。树莓派 2B 的 cpu 是 32 位架构,因此设置 liteos.ld 文件中启动地址为 0x8000。
栈初始化
树莓派 2B 启动文件 los_startup_gcc.S 中只设置了 SVC 模式的 sp 寄存器,新增 cpuInit 函数来初始化其他模式的 sp 指针。如下所示:
配置动态内存地址
以上代码定义 OS_SYS_MEM_ADDR 为动态内存起始地址,LOS_HEAP_ADDR_END 为动态内存结束地址,OS_SYS_MEM_SIZE 为动态内存大小。
串口实现
树莓派 2B 原理图引出了 mini_uart 串口 TXD0、RXD0,对应的引脚为 GPIO14、GPIO15,如下图所示:
创建 usart.c 和 usart.h 文件,在 usart.c 中编写串口初始化函数 UartInit,并实现 uart_debug.c 文件中 uart_getc、uart_hwiCreate、uart_write 接口,实现 printf 函数从串口输出。
适配中断
树莓派 2B 的中断属于 bcm 特定的中断控制器。在 drivers/interrupt 目录下新增 arm_control.c 文件,并在该文件中实现 HwiControllerOps 结构体内的回调函数。
以上表格是 interrupt 寄存器偏移地址,读者想了解详细寄存器相关信息请参考官方芯片手册。
适配 systick
树莓派 2B 通过 Timer(arm side)来触发 systick 中断。具体操作细节请参考文件:drivers\timer\rasp_systick.c。
以上代码配置定时器 Timer 为每 1ms 触发一次 systick 中断。
以上是 Timer 寄存器偏移地址,读者想了解详细寄存器相关信息请参考官方芯片手册。
配置编译
在 targets 目录下新增 kconfig.raspberry 文件:
修改 Makefile 文件
分别修改以下路径 Makefile(详情请参考 gitee 仓库对应文件):driver/timer/Makefiledriver/interrupt/Makefiletargets/Raspberry_Pi2B/Makefile
添加.img 生成指令
在根目录下 Makefile 中添加指令 $(OBJCOPY) -O binary $(OUT)/$@.elf $(OUT)/kernel7.img,用来将生成的 elf 文件转换生成 kernel7.img 文件。
制作启动 SDcard
使用 Raspberry Pi Imager 工具制作 Raspberry Pi 系统。
Raspberry Pi Imager 下载链接:https://www.raspberrypi.org/software/
将编译生成的 kernel7.img 文件替换掉 SDcard 中 kernel7.img 文件。
将写入镜像文件的 SDcard 插入树莓派 2B 中并上电,树莓派 2B 即可运行 LiteOS 系统。运行结果如下:
至此,LiteOS 系统成功启动和运行。该移植工程已经在 Gitee LiteOS 社区上线,相关代码链接地址为:https://gitee.com/LiteOS/LiteOS/tree/master/targets/Raspberry_Pi2B
参考文献链接
[1] Raspberry Pihardware - Raspberry Pi Documentation:https://www.raspberrypi.org/documentation/hardware/raspberrypi/README.md
[2] 树莓派官方芯片手册:
https://datasheets.raspberrypi.org/bcm2835/bcm2835-peripherals.pdf
[3] Cortex-A7 MPCore Technical Reference Manual:
https://developer.arm.com/documentation/ddi0464/f?lang=en
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/a1eafa875cd231d78341b6252】。文章转载请联系作者。
评论