玩转嵌入式多任务程序设计笔记一

2019-07-12 19:27发布

  • 内核&CPU
  计算机基本组成:控制器(Controller)、运算器(ALU)、存储器(Memory)、输入设备(Input)和输出设备(Output)。 控制器&运算器->中央处理单元(CPU)。 嵌入式微控制器(MCU)中的运算器和控制器->内核(Core)。  
  • 内核指令执行(三级流水线)
取指(Instruction Fetch)(IF)   解码(Instruction Decoding)(ID) 指令执行(Execution)( EX) 低端的内核比如 Cortex M0 / M0+, M3 和 M4 上, EX 是一个独立的流水线阶段,此时, IF、 ID 和 EX就组成了最基本的三级流水线结构;在追求指令吞吐量的内核流水线上,指令的执行(EX)往往被进一步的拆分以追求流水线的效率。  
  • 哈弗结构和冯诺依曼结构
ARM Cortex M0/M0+和M1都是冯诺依曼结构的内核。
  • 程序分支
程序的顺序执行是指内核 IF 阶段顺着存储器的地址依次读取指令并执行的过程,如果中途因为某些 原因突然跳转到别的地址去执行,这就叫程序的分支(Branch)。 IF 阶段从什么地址读取指令是由 PC 指针控制的,修改其值就可以实现程序的分支。
  • 分支实现
(DE->ID)。 流水线分支指令之后、目标指令执行之前引入额外的两个周期延迟——其实内核从未停歇,只不过排空流水线内已有的内容需要时间而已——三级流水线需要 2 个时钟周期,以此类推, 5 级流水线就需要 4 个时钟周期。
  • 函数调用
函数返回地址的保存: 1. 返回点的地址压栈; 2. 修改 PC 指针,跳转到目标地址执行; 3. 返回时,直接将返回地址从栈中弹出到 PC 指针,实现函数的返回。 叶子函数:一个子函数(subroutine)不再调用别的函数。 热点:指大量占用处理器时间的代码小片段。 LR(Link Register):专门用于保存函数的返回地址。 LR 本质上相当于一个深度为 1 的硬件栈,支持且仅支持 1 级函数调用。 LR 是内核提供的一个辅助寄存器,在函数调用和返回时时是否对其进行压栈和出栈完全由编译器决定。因为只有编译器知道目标函数是叶子函数还是普通函数,所有的调用都是编译器事先计划好的(在“编译时刻”就确定好的)。 内核对叶子函数的调用过程如下: 1. 将返回点的地址放入 LR 中(这是由跳转指令自动完成的); 2. 修改 PC 指针,跳转到目标地址执行(这实际上也是同一条跳转指令完成的); 3. 返回时,直接将 LR 的值赋值给到 PC 指针,实现函数的返回。 在 ARM Cortex M 指令集中, B 表示跳转 branch; BL 表示跳转到固定地址,并自动将返回地址保 存到 LR 寄存器中; BX 表示根据寄存器进行跳转,这里的 X 指代寄存器; BLX 表示跳转到由寄存器指定的地址,并自动将返回地址放入 LR 寄存器。 非叶子函数的调用过程如下: 1. 将当前 LR 的值压栈; 2. 将返回点的地址放入 LR 中(这是由跳转指令自动完成的); 3. 修改 PC 指针,跳转到目标地址执行(这实际上也是同一条跳转指令完成的); 4. 返回时,直接将 LR 的值赋值给到 PC 指针,实现函数的返回; 5. 将先前保存在栈中的 LR 值出栈。
  • 中断/异常处理程序
ARM Cortex M 系列( M0+开始) 权利约束的角度: “特权(Privileged)操作”:拥有最高的自由度,可以访问所有的系统资源; “非特权(Unprivileged)操作” :受到了严格的限制,不仅针对普通地址空间的访问要受到 MPU 的重重审核,针对内核特殊功能寄存器的访问也受到了全面的禁止。 工作模式角度: 异常/中断处理的“(异常)处理模式(Handler Mode)”:所有的操作都是“特权操作” 普通代码执行的“线程模式(Thread Mode)” :操作可以被指定为“特权”或“非特权”。   对于RTOS 的应用场景,“线程模式”用于执行用户任务,通常运行在“非特权”模式下,以确保任务在规定的安全范围内执行,而不会影响其它任务乃至整个系统;“(异常)处理模式”主要提供给 RTOS 的系统代码使用,用于完成上下文切换、调度、资源管理等系统级任务。