RISC-V MCU开发实战 (三):移植鸿蒙OS项目

简介: ARM上移植实时操作系统大家可能比较熟悉,对于RISC-V内核的MCU,可能相对比较陌生。下面结合WCH的CH32V103和CH32V307两款芯片来详细说下针对RISC-V平台,移植实时操作系统的注意点。

软件平台:MounRiver Studio( MRS);硬件平台: CH32V307开发板
先去码云上将源码克隆下来:
https://gitee.com/openharmony/kernel_liteos_m
新建一个CH32V307的工程,将源码直接拖到工程中,就添加进来了,然后去添加头文件路径即可
1.png

源码中包含比较全面,我们可以选择不需要的部分将其排除在编译之外,
2.png

操作方法为右键目录或文件,点击Include/Exclude From Build菜单项恢复编译,同样的方法再选一遍即可。
下面说些移植操作系统的注意事项
ARM上移植实时操作系统大家可能比较熟悉,对于RISC-V内核的MCU,可能相对比较陌生。下面结合WCH的CH32V103和CH32V307两款芯片来详细说下针对RISC-V平台,移植实时操作系统的注意点。
在移植前,有必要对RISC-V的一些基本知识点有一定的了解,这里对RISC-V的概况,发展,指令集,特权模式等不作详述,仅结合WCH的RISC-V内核的MCU,简单介绍我们移植实时操作系统有可能遇到的关键点做一下描述。这里之所以选取V103和V307两款芯片,主要其极具代表性:

首先,直观上其外设的使用方法和我们之前熟悉的F103,F107等是兼容的,这样降低了我们使用和移植时的难度,基于WCH提供的外设库,我们以前上层的代码甚至于不用修改可直接使用。其次,V103是WCH RISC-V内核家族中的V3内核,V307为V4内核,V3内核支持RV32IMAC指令集,即除支持RISC-V基本的32位整数指令集外,还支持硬件乘除法,原子指令,压缩指令。V4在V3的基础上增加了单精度硬件浮点,并且其性能也比V3高。
除上述之外,虽然两者的中断控制器(PFIC)相较于现行的PLIC均不同,均不是统一入口,而是采用中断向量表寻址的方式,但是V3的中断向量表处存放是一条指令,而V4的向量表既可以存放指令,也可以存放中断处理函数的地址。两者均支持中断嵌套和硬件压栈,区别在于V3最大嵌套两级,V4最大可达八级,同时V3的硬件压栈深度两级,V4的硬件压栈深度为三级。这里需要注意的是,移植实时操作系统时需要关闭硬件压栈,在切换任务时所有寄存器,我们希望是由我们自己控制其压栈和出栈的内容。

RISC-V寄存器如下图所示,其中x0-x31为整形寄存器,f0-f31为浮点寄存器(V3没有浮点寄存器)。所有带caller的寄存器,当发生中断时需要保存,值得注意的是,WCH的硬件压栈保存的寄存器仅仅保存整数的16个caller saved 寄存器。正常一个中断函数的寄存器保存我们不用关心,编译器会帮我们做的很好。但是当我们从一个汇编入口进中断函数的时候这些过程就不得不由我们自己来实现。寄存器中几个相对特殊的x0恒为0,x1是返回地址寄存器ra,函数调用时用来存放返回地址,x2为堆栈指针sp,x3为gp全局指针,用来寻址全局变量。对于一个正常运行的程序,除了x0,gp两个初始值固定的外,其余的均会是不确定的,所有在进行上下文保护时,均需要保存。用到硬件浮点的时候,更是要保存32个浮点寄存器。
3.png

除了上述的寄存器,移植还要关心的是几个csr寄存器mstatus,mepc。正常情况下大部分csr只能在机器模式下操作(WCH的v3和v4内核支持机器模式和用户模式)。mstatus中,MIE为中断使能,当进中断时MPIE更新为MIE,返回时MIE更新为MPIE。MPP用于保存进中断之前的特权模式,如果我们设置其为MPP=0b11,那么将一直处于机器模式,其mret返回后还是处于机器模式。mepc是机器模式下异常程序指针,其只会在发生异常是被更新(中断也是一类异常),进异常时我们可以从另外两个csr寄存器mcause来看引起异常原因通过mtval查看引起异常时的值。当从异常返回时mepc的值被更新给pc。我们正是通过进中断修改mepc来实现任务的切换的,后面会详细说明这个过程。

实时操作系统大家应该不陌生,常见的uCOS,FreeRTOS,RT-Thread,LiteOS-M等等,其基本的思路都是一样的,需要一个定时器用于系统时间片的实现,一个中断用于任务切换。想要其能够在一个MCU上成功的跑起来,需要弄清除一下几个事情:
(1)进中断需要保存哪些内容。
从之前的描述中,应该知道,对于risc-v内核来说其进中断压栈的是caller saved的寄存器。从下图一可以看出,进Systick中断函数,先进行寄存器保存,退出中断时进行寄存器恢复,如果开启硬件浮点,同时还会对浮点寄存器进行保存和恢复。这个过程是编译器帮我们实现,有一点需要注意的是我们移植的代码里面进中断后获取了中断的堆栈“csrrw sp,mscratch,sp”,返回时恢复了线程的堆栈指针“csrrw sp,mscratch,sp”中断堆栈指针初始值是在任务开始时存入mscratch寄存器的,如果采用C形式中断函数,中断堆栈的获取会在压栈操作之后,中断压入的堆栈是当前运行任务的任务堆栈区域,如果想要中断函数压栈时压入的自己的堆栈区域,可以使用汇编入口,进中断后先修改sp,然后压栈,再调用中断处理函数,如图二所示。
4.png

图1
5.png

图2
(2)任务栈需要保存哪些内容。
前文说过对于一个正常运行的程序,切换任务前,除了x0恒0,x3 gp指针外,其余的寄存器均需要保存,每个RTOS中都会定义一个上下文保存相关的结构体,这里我们以华为鸿蒙LiteOS_M为例,看一下这个结构体:
6.png

图3
在创建任务的时候均会为一个任务分配一个id和堆栈大小并对这个堆栈做初始化:
7.png

图4
8.png

图5
任务创建好了后会关联一个根据任务id关联一个任务控制块taskCB,总的任务个数是在头文件中配置的(target_config.h)总的任务块的初始化也是在LOS_KernelInit被初始化。
9.png

图6
从上面可以看出来,task--->taskCB--->sp指针--->memory这样的路线,而这片memory开始位置用于上下文保存。
这样的方式在其他RTOS中也可以看到,例如RT-Thread中用于上下文保存的结构体rt_hw_stack_frame,和taskCB类似的结构体rt_thread等。
10.png

图7
11.png

图8

(3)如何开启任务调度。
前面看了每个任务上下文保存位置,注意到堆栈初始化的时候把任务的入口地址给了context->epc。同时LiteOS_M源码中定义了一个LosTask类型的全局变量g_losTask,其内部只有两个任务控制块指针,一个指向当前运行的任务,一个指向新任务,即要切换至的任务。
12.png

图9
当做好一系列初始化后,LiteOS会调用HalStartSchedule来初始化系统节拍定时器,并注册系统定时器的中断处理函数,然后开始转向执行第一个任务,如下图所示:
13.png

图10
其中OsSchedStart函数从任务列表中获取第一个任务,并赋值给g_losTask里面的runTask和newTask。然后调用HalStartToRun转向执行runTask所指示的任务。HalStartToRun是一段汇编代码,下面就具体看其如何切换至runTask,具体如下图的注释:
14.png

图11
这样mret之后就转向去执行第一个任务,并且不会再有返回,因为每个任务本身会是个循环,这里也就能理解其源码注释 never return的含义。
15.png

图12
其他操作系统中也有类似的操作,例如RT-Thread中有个rt_hw_context_switch_to函数,其也是汇编代码实现,它是一个带参数的函数,其传入的参数为(&to_thread->sp),如下图:
16.png

图13
从名字就可以看出,传递的参数为启动执行的第一个线程的控制块的堆栈指针sp的值,后面赋值mepc,mstatus,其他寄存器等等都是和LiteOS_M一致的。
(4)如何进行任务切换。
了解了如何切换至第一个任务,那么如何实现不同任务之间的切换呢,在这之前我们应该都有了解,RTOS是根据任务的优先级和时间片进行轮转的,每个任务执行一段时间,然后切换至下一个任务执行。每次切换前我们需要把当前任务的运行状态进行保存,然后切换至新任务,对其运行状态进行恢复,如此循环反复,实现任务调度。时间片实现使用的是内核的SysTick定时器,LiteOS_M是在los_timer.c中实现的,这个只需要根据实际硬件的进行初始化就行。其他操作系统也是类似,像RT-Thread源码中我们根据硬件完成board.c。对于任务切换,我们利用内核的软中断,只要使能该中断,并且当需要切换任务时,把中断控制器的对应的pendset位置1,即可触发该中断进行任务切换。下图是liteOS_M切换过程:
17.png

图14

18.png

图15
其他操作系统也是大同小异,具体的区别仅仅是在切换新任务时,新任务如何获取的问题,上图可以看到LiteOS_M是通过g_losTask来管理,RT-Thread中定义了from_thread,to_thread,顾名思义从一个线程切换至另外一个线程。
弄清楚以上的问题,对于某一个RTOS的基本移植来说应该就比较明了。
最后移植好的鸿蒙os,RT-Thread等实时操作系统的代码均已在MRS上线,可以直接创建,开发相关应用
19.png

相关文章
|
27天前
|
JavaScript 安全 前端开发
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
291 4
|
28天前
|
API
HarmonyOS 3.1/4项目在DevEco Studio 5.0(HarmonyOS NEXT)版本下使用的问题
有读者在使用《鸿蒙HarmonyOS应用开发入门》书中的源码时遇到问题,主要原因是使用的DevEco Studio版本不同所致。本文提供了三种解决方案:1) 降级DevEco Studio至3.1版本;2) 按照5.0版本修改书中示例;3) 等待并使用《鸿蒙之光HarmonyOS NEXT原生应用开发入门》升级版书籍。
149 1
|
1天前
|
数据管理 API 调度
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
HarmonyOS Next 是华为新一代操作系统,专注于分布式技术的深度应用与生态融合。本文通过技术特点、应用场景及实战案例,全面解析其核心技术架构与开发流程。重点介绍分布式软总线2.0、数据管理、任务调度等升级特性,并提供基于 ArkTS 的原生开发支持。通过开发跨设备协同音乐播放应用,展示分布式能力的实际应用,涵盖项目配置、主界面设计、分布式服务实现及部署调试步骤。此外,深入分析分布式数据同步原理、任务调度优化及常见问题解决方案,帮助开发者掌握 HarmonyOS Next 的核心技术和实战技巧。
107 76
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
|
1天前
|
开发框架 人工智能 安全
鸿蒙HarmonyOS应用开发 | 「鸿蒙技术分享」HarmonyOS NEXT元服务卡片实战体验
HarmonyOS NEXT的发布对华为及整个行业都产生了深远的影响。它不仅展示了华为的技术实力,还敏锐地把握了市场需求。同时,吸引了更多的开发者和合作伙伴加入鸿蒙生态体系,共同推动鸿蒙生态的繁荣发展。
159 19
鸿蒙HarmonyOS应用开发 | 「鸿蒙技术分享」HarmonyOS NEXT元服务卡片实战体验
|
1天前
|
物联网 调度 vr&ar
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
鸿蒙技术分享:HarmonyOS Next 深度解析 随着万物互联时代的到来,华为发布的 HarmonyOS Next 在技术架构和生态体验上实现了重大升级。本文从技术架构、生态优势和开发实践三方面深入探讨其特点,并通过跨设备笔记应用实战案例,展示其强大的分布式能力和多设备协作功能。核心亮点包括新一代微内核架构、统一开发语言 ArkTS 和多模态交互支持。开发者可借助 DevEco Studio 4.0 快速上手,体验高效、灵活的开发过程。 239个字符
132 13
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
|
3天前
|
索引
鸿蒙开发:ForEach中为什么键值生成函数很重要
在列表组件使用的时候,如List、Grid、WaterFlow等,循环渲染时都会使用到ForEach或者LazyForEach,当然了,也有单独使用的场景,如下,一个很简单的列表组件使用,这种使用方式,在官方的很多案例中也多次出现,相信在实际的开发中多多少少也会存在。
鸿蒙开发:ForEach中为什么键值生成函数很重要
|
26天前
|
存储 数据安全/隐私保护
鸿蒙开发:自定义一个动态输入框
在鸿蒙开发中,如何实现这一效果呢,最重要的解决两个问题,第一个问题是,如何在上一个输入框输入完之后,焦点切换至下一个输入框中,第二个问题是,如何禁止已经输入的输入框的焦点,两个问题解决完之后,其他的就很是简单了。
48 13
鸿蒙开发:自定义一个动态输入框
|
29天前
|
小程序 测试技术 API
鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
本文详细介绍元服务的开发及上架全流程,涵盖元服务的特点、创建项目、服务卡片、签名打包、开发测试及上架审核等环节,帮助开发者轻松掌握从零开始开发并发布元服务的全过程。元服务以其轻量、免安装、易于使用等特点,成为未来服务提供的重要形式。
74 13
鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
|
27天前
|
UED
「Mac畅玩鸿蒙与硬件24」UI互动应用篇1 - 灯光控制小项目
本篇将带领你实现一个互动性十足的灯光控制小项目,用户可以通过点击按钮来控制灯光的开关。该项目将涉及状态管理、动态图片加载以及按钮交互,是学习鸿蒙应用开发的重要基础。
38 5
「Mac畅玩鸿蒙与硬件24」UI互动应用篇1 - 灯光控制小项目
|
17天前
|
安全 前端开发 Android开发
探索移动应用与系统:从开发到操作系统的深度解析
在数字化时代的浪潮中,移动应用和操作系统成为了我们日常生活的重要组成部分。本文将深入探讨移动应用的开发流程、关键技术和最佳实践,同时分析移动操作系统的核心功能、架构和安全性。通过实际案例和代码示例,我们将揭示如何构建高效、安全且用户友好的移动应用,并理解不同操作系统之间的差异及其对应用开发的影响。无论你是开发者还是对移动技术感兴趣的读者,这篇文章都将为你提供宝贵的见解和知识。