Hi,同学,很遗憾地通知你进入这门课程中最枯燥、最无趣的课时!

虽然我很想将这个课时砍掉,但是显然是不可能的。任何代码都是运行于特定的硬件平台之上,更何况RTOS这种更接近硬件的代码。RTOS要正常工作,必须要使用到CPU的某些特性,所以部分硬件相关的内容是必须了解的。 为了方便学习,我们选取了目前最常用的一种CPU类型Cortex-M3,并且只选择其中与RTOS相关的知识点介绍。尽可能地节省你的学习时间和成本!

注意,以下内容你第一次看可能并不一定能明白。建议在后面学习《内核编程实践》、《任务切换的实现》课时时,再同步观看此部分。

主要内容

本课程主要介绍与RTOS实现相关的Cortex-M3内核知识。由于此部分涉及硬件,所以相对而言比较枯燥。
课程内容不会涉及到具体CPU芯片或者开发板的知识,因为这部分与RTOS的实现关系并不是那么重要。且cortex-M3设计的比较合理,在其中提供了RTOS任务切换、系统时钟节拍所有相关资源,使得我们无需再关注具体的芯片就能够设计出能够运行与所有以Cortex-M3内核为基础的MCU。
以下结合后面讲到的RTOS设计,对该部分内容重新做一下梳理。

存储映射

无论什么程序总是要运行于存储器中,下图给出的是Cortex-M的存储布局规范图。
芯片内核简介 - 图1
注意,这里指的是规范,实际厂家并不一定完全按照这个规范做
在学习中,简单了解即可,并不需要关心。因为在后面课时创建工程时,Keil软件已经自动帮你配置好,不用处理。

工作模式及权限级别分类

硬件开始工作后,CPU会进入特定的工作模式。此小节主要介绍CPU的工作模式及相应模式下的特权级,课程中我们用了一幅图展示如下:
芯片内核简介 - 图2
如果你在学习过程中发现自己不能很好的理解这幅图,没有关系。结合我们在后面的设计中,可以简单地理解为:

  • 默认运行在Thread Mode下;当发生异常/中断发生时,硬件自动切换到Handler Mode模式,执行完相应的异常/中断处理程序后,再切换回线程模式;
  • 我们在课程中只使用了特权级,没有使用到用户级。即设计的RTOS中并没有借助特权级/用户级的划分实现对一些资源/指令的访问控制。

总而言之,在我们的设计中,异常/中断运行于Handler Mode,各个任务的代码运行于Thread Mode,这个过程由硬件自动切换。无论是异常/中断/任务,均运行于特权级下(硬件启动后的缺省级别)。

寄存器组

想必你知道,任务在执行他的代码时,必须要用到这些内核寄存器做一些算术、逻辑等运算处理,这部分寄存器相当于任务运行状态的一部分。在进行任务切换时,我们需要在切换代码中将这部分寄存器的值保存/恢复。
芯片内核简介 - 图3
例如,这些寄存器中:

  • R15指明了当前任务执行的指令位置
  • R13指明当前任务所用的堆栈位置
  • R0~R3主要用于程序调用时,参数的传递;执行程序时局部变量的存储

对于上图,除了简单了解其有R0~R15外,还要特别注意双堆栈寄存器R13,用于实现中断/异常所用的栈与任务所用的栈相分离,互不干扰。简单来说,在我们的设计中,异常/中断发生时,硬件自动切换到MSP指向的堆栈来配合执行相应的处理程序,而退出后,自动切换到PSP指向的堆栈空间再执行任务代码。
无论是哪种堆栈,其均使用下面这幅图的增长模式:每次压栈,堆栈地址递减。且堆栈指针SP(MSP/PSP)。特别注意:SP总是指向最后压栈的单元,不是下一个空闲的堆栈单元。
芯片内核简介 - 图4
至于xPSR寄存器,只需要了解PRIMASK位即可,在后面讲实现关中断时,有借助指令操作这个位。
芯片内核简介 - 图5

PendSVC异常

在执行具体的任务切换时,我们在设计中是通过向PendSVC异常发起请求,然后在PendSVC异常处理程序中具体执行任务切换的操作。
异常处理流程比较复杂,我们只需要记往以下几点:

进入异常

刚进入异常时,硬件自动会将以下寄存器压入当前堆栈(我们当前用的是PSP)。压入哪些内容以及他们的次序非常重要!
芯片内核简介 - 图6
之后硬件自动跳转到PendSVC异常处理程序中运行。

退出异常

退出异常时,硬件会自动出栈,这个次序与进入异常时压栈的顺序刚好相反。可以理解为进入异常时保存了部分寄存器状态,退出时正好恢复。
此外,在退出异常时,我们还会用到EXC_RETURN,其中只用到了0xFFFF_FFFD(即返回异常时进入线程模式,使用PSP堆栈)。

芯片内核简介 - 图7

注意,进入异常和退出异常时自动的出入栈会在后面的课时中视为任务部分状态的保存。

汇编指令

在PendSVC中实现任务切换时,必须要用到一些汇编指令进行状态保存。课程中只介绍了用到的部分指令。
芯片内核简介 - 图8

芯片内核简介 - 图9
在学习时可先简单了解,待后面用到时,再回过头来翻看,这样效果会更好。
课程附带的资料中有完整的指令集参考文档,但我认为并没有必要仔细阅读。

重点难点

该课时的难点在于内容比较枯燥,难于学习。建议先整体了解,待后面学到相应章节时,再回顾。
如需了解更多关于Cortex-M3内核的知识,请查看课程资料手册《Cortex-M3权威指南.pdf》,或者在网易云课堂上搜索“Cortex-M”的视频课程。

注意事项

本课程选用的是Cortex-M3内核,其特性和ARM的Cortex-M0/M1/M4/M7非常相近,略有差别。如果你熟悉这些内核,可以更好地学习这门课程中的内容。

常见问题

芯片内核介绍课时学习方法

注意,在学习本课时,会有较多的关于硬件方面的细节。如果你之前没有接触过Cortex-M内核,可能会觉得有难度。提供以下几点建议:

  • 对整体知识有个了解即可,不必试图记住或理解所有细节。
    请记住,你在本课程中的主要目的是学习RTOS的知识,切勿将太多精力投入到Cortex-M硬件细节,否则就本末倒置了。
  • 课时只讲对本课程有用的硬件知识,其它知识不需要去探究
    Cortex-M硬件细节有很多,不必去专门找本手册详细研究,这会浪费很多时间。优先将用到的先掌握,这样便于快速进入到后面的课程中,避免课程的学习停滞。
  • 听不懂没关系,先进入到下一课时以及《基本任务切换实现》课时的学习
    在这些课时中会用到本课时相关的知识,到时再回去头来翻看,很多地方就会逐渐理解。
  • 内核硬件相关的知识只在学习《基本任务切换实现》有帮助
    所以这是必要的知识,但是不很重要的知识。

【参考资料】

  • Cortex-M3权威指南.pdf
  • Cortex-M3+技术参考手册.pdf
    以上资料,请见QQ群文件共享。

首次打开时简单翻翻即可,以后要用时再去查相关章节。

有没有关于汇编的工具书推荐

Q:我的汇编基础差,有没有相应的工具书推荐一下?
A:课程用到的汇编代码量很少,只有10多行。只要了解下这些指令就可以了。没必要看全面的工具书。为学而学容易忘。
如果确实想了解汇编指令相关的知识,请查阅QQ群的分享:《Cortex-M3权威指南》

有无必要学习其它芯片知识

Q:有没有必要再去学习某种特定型号芯片知识?比如STM32
A:没有必要。本课程只会用到Cortex-M3内核的组件,不依赖于任何特定的芯片

Thumb-2指令与ARM指令差别

Q:Cortex-M3的Thumb-2指令与ARM指令差别大吗?
A:不必担心。二者有些差别,不过很多地方都很相似。如果你熟悉ARM指令,再学Thumb-2指令会比较容易。

芯片内核简介勘误

由于视频课件本身特殊性质,导致一旦录制完成后,后期发现错误很难修改;所以特地增加了该小节用于说明视频课件中存在的小问题。如学习遇到问题,请@lishutong。
感谢同学 @ lmwfanka 的指正
在 课时12:34 有个动画,如下图所示。正确的动画效果应该是0x00000101传递给PC寄存器,而0x20080000传递给R13(MSP/PSP)寄存器。
此处的动画主要是用于大致说明Cortex-M的启动过程,由于这个过程是由硬件自动完成的,且与后面的课时没有太大关系,所以不必在意这个细节。