前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >构建RTOS Kernel指南 (上)

构建RTOS Kernel指南 (上)

作者头像
刘盼
发布2023-08-22 16:13:07
2860
发布2023-08-22 16:13:07
举报
文章被收录于专栏:人人都是极客人人都是极客

1前言

试想与我们相伴的MCU如若只存在裸机程序,那么运行到一个包含延时的线程时,我们的CPU就开始“摸鱼”了。为了最大化运行CPU,就需要用到RTOS(Real Time Operating System). 简单来说,RTOS是一个调度一切可利用的资源完成实时任务,并控制所有实时任务协调一致运行的操作系统,或者说,其内核是一个任务管理的框架。

市面上已存有许多优秀的RTOS,如FreeRTOS、Zephyr、RT-Thread等。许多小伙伴可能在最初接触RTOS时怯于其超厚的配套书籍或其庞大的代码,但不用害怕,像小编一样庖丁解牛般边学习边构建一个自己的RTOS是一个很好的学习方法,让我们踏上RTOS的学习之旅!

图1 RTOS版本

就好像要盖一座高楼,必然先得考察地势地貌,地基稳固,才能逐渐添砖加瓦。构建一个RTOS也是同样道理,需要知道它运行在一个怎样的架构上,以NXP的RT系列芯片为例,我们需要了解学习ARM Cortex-M系列的架构内容。这是一个非常庞大的体系,这里推荐《ARM Cortex-M3 Cortex-M4权威指南》,是一本不错的参考书籍。下文将列举构建一个RTOS所需要的最为核心的内容。

图2《ARM 图2 Cortex-M3 Cortex-M4权威指南》

2ARM处理器架构相关内容

2.1 操作模式和状态

图3操作模式和状态

Cortex-M系列有两种操作状态和两种模式,并可以区分特权和非特权访问等级。其中调试状态只在连接调试器的时候起作用,若处理器在执行程序代码,则处于Thumb状态,Cortex-M处理器不支持ARM状态,所以ARM状态不存在。

两种模式为处理模式线程模式:处理模式用作异常处理,并总具有特权访问等级;在执行普通的应用程序代码时,处理器处于线程模式,此时可能处于特权访问等级也可能处于非特权访问等级,前者可向后者切换,但是后者向前者切换则需要借用异常机制。

2.2 寄存器

Cortex-M处理器在内核中具有多个执行数据处理和控制的寄存器,这些寄存器大都以寄存器组的形式进行了分组。以cortex-M4处理器为例,寄存器组中有16个寄存器。

图4 寄存器组中寄存器

其中R0-R12为通用寄存器,R13为栈指针,用于实现栈存储的访问。物理上存在两个栈指针:主栈指针(MSP)用于处理模式,以及进程栈指针(PSP)只能用于线程模式。R14也被称为链接寄存器,用于函数或子程序调用时返回地址的保存。R15为程序计数器。除了寄存器组中的寄存器之外,处理器中还存在多个特殊的寄存器。下面为几个较为典型的特殊寄存器:

图5 特殊寄存器

其中,程序状态寄存器包含三个状态寄存器,用于保存处理的状态信息。PRIMASK、FAULTMASK、BASEPRI寄存器都用于异常或中断屏蔽,CONTROL寄存器则用于栈指针的选择和线程模式的访问等级。

2.3 向量表和系统控制块

当Cortex-M处理器接受了某种异常请求后,处理器需要确定该异常处理的起始地址,该信息位于存储器内的向量表中。构建RTOS用到的最为核心的异常为PendSV,其优先级最低,可以被其他中断打断,因此通常用作上下文的切换,也就是任务的切换。

图6 中断向量表

系统控制块(SCB)中包含了若干用于中断控制的寄存器,其中有一个与RTOS密切相关的为中断控制和状态寄存器(ICSR),通过将第28位进行使能操作,可以触发我们需要的PendSV中断异常。

图7 中断控制和状态寄存器(ICSR)

3任务切换的实现

上述背景知识是为构建RTOS而提炼的内容,作者在这里建议在开发学习过程中带着疑问前进,边学习边扩展。下面就可以对RTOS的最基本功能——任务切换进行实现。首先我们需要知道,不同于裸机程序,RTOS的每个任务都有独立的上下文环境,在发生任务切换时,需对每个任务的状态数据进行保存,那么需要为每个任务配备有独立的栈空间。

当触发任务切换时,需要首先暂停当前任务的执行,并保存当前任务的状态数据到任务对应的栈空间,再将栈指针更新到切换的目标任务的栈空间,最后从该栈空间中恢复其状态数据,至此完成了任务的切换。

图8 任务切换的步骤

需要注意的是,当PendSV异常触发时,硬件系统会自动保存xPSR、LC、R12、R3-R0寄存器,R11-R4的压栈需要代码实现。除此之外,在任务初始化的时候,也需要对栈空间进行初始化,并且在系统运行第一个任务时,无需进行压栈的操作,因此需要判断任务是否为初始任务,一个较为简单的办法是在运行初始任务之前将PSP置0用于判断,但这样对系统的运行效率有一定影响,较为成熟的RTOS中有更为巧妙的处理办法,有兴趣的读者可以自行查阅。

图9 上下文切换的流程

实现到这里,一个RTOS的地基已经铸成,请继续翻看下集学习:

优先级查找,优先级反转,临界区保护和线程同步功能的详细介绍哦!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人人都是极客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档