手把手带你做LiteOS的树莓派移植
摘要:树莓派是英国的慈善组织“Raspberry Pi 基金会”开发的一款基于arm的微型电脑主板。本文介绍基于LiteOS的树莓派移植过程。
本文分享自华为云社区《2021 LiteOS树莓派移植指南(一)》,作者: Lionlace 。
树莓派是英国的慈善组织“Raspberry Pi 基金会”开发的一款基于arm的微型电脑主板。本文介绍基于LiteOS的树莓派移植过程。
硬件信息
开发板: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功能
mrc p15, 0, r0, c1, c0, 1
bic r0, r0, #0x40
mcr p15, 0, r0, c1, c0, 1
上表是ACTLR(Auxiliary Control Register)寄存器bit6功能描述信息,了解更多寄存器相关信息可以参考Cortex-A7 MPCore Technical Reference Manual。
- 关闭MMU的功能
mrc p15, #0, r0, c1, c0, #0
bic r0, r0, #1
mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit
上表是SCTLR (System Control Register)寄存器bit0功能描述信息,了解更多寄存器相关信息可以参考Cortex-A7MPCore Technical Reference Manual。
- 删除调用SMP相关函数
删除los_startup_gcc.S中的enable_scu和secondary_cpu_start。
使能FPU/ENON
配置FPU/NEON:
/* enable fpu+neon */
LDR r0, =(0xF << 20)
MCR p15, 0, r0, c1, c0, 2
MOV r3, #0x40000000
VMSR FPEXC, r3
以上前两行代码用于设置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指针。如下所示:
VOID cpuInit(VOID)
{
__asm__ (
"msr cpsr_c, %1\n\t"
"mov sp, %0\n\t"
"msr cpsr_c, %3\n\t"
"mov sp, %2\n\t"
"msr cpsr_c, %5\n\t"
"mov sp, %4\n\t"
"msr cpsr_c, %7\n\t"
"mov sp, %6\n\t"
"msr cpsr_c, %8\n\t"
:
: "r" (__irq_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_IRQ_MODE),
"r" (__abt_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_ABT_MODE),
"r" (__undef_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_UNDEF_MODE),
"r" (__fiq_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_FIQ_MODE),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_SVC_MODE)
: "r14");
}
配置动态内存地址
#define OS_SYS_MEM_ADDR ((void *)(&__bss_end))
#define LOS_HEAP_ADDR_END (void*)(0x0 + 4 * 1024 * 1024)
#define OS_SYS_MEM_SIZE (UINT32)(((UINT32)LOS_HEAP_ADDR_END - (UINT32)OS_SYS_MEM_ADDR + (64 - 1)) & ~(64 - 1))
以上代码定义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结构体内的回调函数。
STATIC const HwiControllerOps g_armControlOps = {
.enableIrq = HalIrqUnmask,
.disableIrq = HalIrqMask,
.getCurIrqNum = HalCurIrqGet,
.getIrqVersion = HalIrqVersion,
.getHandleForm = HalIrqGetHandleForm,
.handleIrq = IrqEntryArmControl,
.clearIrq = HalIrqClear,
.triggerIrq = HalIrqPending,
};
以上表格是interrupt寄存器偏移地址,读者想了解详细寄存器相关信息请参考官方芯片手册。
适配systick
树莓派2B通过Timer(arm side)来触发systick中断。具体操作细节请参考文件:drivers\timer\rasp_systick.c。
/* systime=250000000 */
timer->preDivider = (OS_SYS_CLOCK / OS_SYS_US_PER_SECOND - 1);
timer->reload = 0;
timer->load = 0;
timer->IRQClear = 0;
timer->control = 0;
timer->reload = LOSCFG_BASE_CORE_TICK_PER_SECOND;
timer->load = LOSCFG_BASE_CORE_TICK_PER_SECOND;
/* 23-bit counter, enable interrupt, enable timer */ timer->control = (1 << 1) | (1 << 5) | (1 << 7);
UINT32 ret = LOS_HwiEnable(ARM_TIMER_INI);
以上代码配置定时器Timer为每1ms触发一次systick中断。
以上是Timer寄存器偏移地址,读者想了解详细寄存器相关信息请参考官方芯片手册。
配置编译
在targets目录下新增kconfig.raspberry文件:
ConfigLOSCFG_PLATFORM
config LOSCFG_PLATFORM
string
default "Raspberry_Pi2B" if LOSCFG_PLATFORM_Raspberry_Pi2B
choice
prompt "Board"
depends on LOSCFG_FAMILY_RASPBERRY
default LOSCFG_PLATFORM_Raspberry_Pi2B
help
Raspberry_Pi2B
config LOSCFG_PLATFORM_Raspberry_Pi2B
bool "Raspberry_Pi2B"
select LOSCFG_ARCH_CORTEX_A7
select LOSCFG_USING_BOARD_LD
select LOSCFG_PLATFORM_ARM_CONTROL
select LOSCFG_Raspberry_Pi2B_SYSTICK
endchoice
修改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系统。运行结果如下:
********Hello Huawei LiteOS********
LiteOS Kernel Version : 5.1.0
build data : Jul 13 2021 16:40:42
**********************************
OsAppInit
cpu 0 entering scheduler
app init!
Hello, welcome to liteos demo!
Huawei 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
手把手带你做LiteOS的树莓派移植的更多相关文章
- 手把手带你做一个超炫酷loading成功动画view Android自定义view
写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...
- GitHub 热点速览 Vol.26:手把手带你做数据库
作者:HelloGitHub-小鱼干 摘要:手把手带你学知识,应该是学习新知识最友好的姿势了.toyDB 虽然作为一个"玩具"项目不能应用在实际开发中,但通过它你可以了解到如何制作 ...
- 学就完事了!万星项目带你做 3D 游戏——GitHub 热点速览 v.21.18
本文首发于「HelloGitHub」微信公众号,搜索「HelloGitHub」点击关注解锁更多宝藏! 作者:HelloGitHub-小鱼干 新手开始学习的时候,都会遇到一个问题:如何开始学 xx?Se ...
- UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包
背景 项目上需要做UWP的自动安装包,在以前的公司接触的是TFS来做自动build. 公司要求用Jenkins来做,别笑话我,之前还真不晓得这个东西. 会的同学请看一下指出错误,不会的同学请先自行脑补 ...
- Android:手把手带你深入剖析 Retrofit 2.0 源码
前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将手把手带你深入剖析Retrofit v2.0的源码,希望你们会喜 ...
- [转帖]从零开始入门 K8s | 手把手带你理解 etcd
从零开始入门 K8s | 手把手带你理解 etcd https://zhuanlan.zhihu.com/p/96721097 导读:etcd 是用于共享配置和服务发现的分布式.一致性的 KV 存储系 ...
- R数据分析:跟随top期刊手把手教你做一个临床预测模型
临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...
- HashMap源码深度剖析,手把手带你分析每一行代码,包会!!!
HashMap源码深度剖析,手把手带你分析每一行代码! 在前面的两篇文章哈希表的原理和200行代码带你写自己的HashMap(如果你阅读这篇文章感觉有点困难,可以先阅读这两篇文章)当中我们仔细谈到了哈 ...
- [.Net] 手把手带你将自己打造的类库丢到 NuGet 上
手把手带你将自己打造的类库丢到 NuGet 上 序 我们习惯了对项目右键点击“引用”,选择“管理NuGet 程序包”来下载第三方的类库,可曾想过有一天将自己的打造的类库放到 NuGet 上,让第三者下 ...
- 我和小美的撸码日记(1)之软件也需靠脸吃饭,带您做张明星脸(附后台经典框架 DEMO 下载)
众所周知程序员得靠技术吃饭,但是真的光靠技术就够了吗?Teacher苍,一位德艺双馨的艺术家,论技术她自然是炉火纯青,我觉得她桃李遍天下的原因不仅限于些,试想如果Teacher苍长得跟凤姐一样再带点乡 ...
随机推荐
- codeforces #865 div1A
A. Ian and Array Sorting 思路:首先我们可以从前往后做一遍,把除了最后一个元素其他所有数都变成和第一个数一样的数,然后假如前n-1个数个数为偶数,这样我们分组进行操作,一定可以 ...
- 【Java集合】单列集合Collection常用方法详解
嗨~ 今天的你过得还好吗? 路途漫漫终有一归, 幸与不幸都有尽头. 在上篇文章中,我们简单介绍了下Java 集合家族中的成员,那么本篇文章,我们就来看看 Java在单列集合中,为我们提供的一些方法,以 ...
- JUC并发编程学习笔记(十六)Volatile
Volatile 保证可见性 private volatile static Integer num = 0; 使用了volatile关键字,即可保证它本身可被其他线程的工作内存感知,即变化时也会被同 ...
- 当代免疫学小史-第一章(根据讲谈社Blue Backs系列2009年第一版第三次印刷版本翻译)
作者 -岸本忠三:前大阪大学校长.IL-6发现人 -中嶋彰:科普作家 第1章 石坂往事 巴尔的摩的大雪 1970年匆匆而过,这一年举行了大阪世博会,三岛由纪夫也是在这一年切腹自杀的.1971年新年第一 ...
- Welcome to YARP - 5.压缩、缓存
目录 Welcome to YARP - 1.认识YARP并搭建反向代理服务 Welcome to YARP - 2.配置功能 2.1 - 配置文件(Configuration Files) 2.2 ...
- 递归+DP:爬楼梯问题
一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级.求该青蛙跳上一个n 级的台阶总共有多少种跳法. 输入格式: 首先输入数字n,代表接下来有n组输入,50>=n>=0,然后每行一个 ...
- 用友NC产品接口开发,通过轻易云数据集成平台快速调用
通过用友NC产品的 UAP V63平台.插件相关处理.相关业务逻辑处理课程目标与要求课程内容课程目标与要求业务逻辑处理外部系统信息设置节点新建外部系统默认匹配规则:仅按对照表:外部系统数据与UAP.接 ...
- 聊聊卷积神经网络CNN
卷积神经网络(Convolutional Neural Network,CNN)是一种被广泛应用于图像识别.语音识别和自然语言处理等领域的深度学习模型.与RNN.Transformer模型组成AI的三 ...
- C++ 返回函数指针的函数
目录 0 前言 1 Function Pointer in C/C++ type 1.1 ordinary function Pointer 1.2 non-static member functio ...
- 如何理解微服务体系结构中的 CQRS
本文翻译自 How To Understand CQRS In Microservices Architecture,原作者 OLEKSII. 问题描述 在典型的软件应用程序中,有一个负责写入和读取操 ...