uC/OSIII在Cortex-M3的任务切换和中断退出分析

2023-05-16

    uC/OSIII在任务中执行OSSched相关的函数和在中断退出后都会开始执行调度,这是它的调度机制。而按uC/OSIII书中所讲,普通任务切换和从中断中退出后的任务切换应该是不同的函数,因为普通任务切换时要入栈出栈全部寄存器,而中断进入和退出时处理器会自动入栈出栈一部分寄存器(Cortex-M3 是自动保存xPSR, PC, LR, R12, R0-R3 )。

    但是uC/OSIII在Cortex-M3平台中,这两种任务切换函数却是使用的同一函数,确切的说是使用了同一段代码,如下:
LDR     R0, =NVIC_INT_CTRL         ; Trigger the PendSV exception (causes context switch)
LDR     R1, =NVIC_PENDSVSET
STR     R1, [R0]
BX       LR
(这段代码的作用是写NVIC寄存器,调用PendSV中断。)
    为什么和书上说的不一致呢?两种完全不同的场景居然能使用同一个处理过程?
    机关就在调用PendSV中断这里。uC/OSIII在Cortex-M3平台下使用PendSV中断进行任务的调度切换。而Cortex-M3的中断进入前会自动保存8个寄存器 :xPSR, PC, LR, R12, R0-R3。所以即使是任务中执行的切换,该任务也不需要做寄存器的入栈操作,直接调用PendSV中断就好了。而在中断退出中执行的切换因为本来就在中断中,更不需要再做入栈操作了。
    也就是说,无论是从任务中调用的任务切换还是从中断退出中调用的任务切换,都是调用的PendSV中断。这一点很重要,因此只要是任务切换,结果就是:在进入PendSV处理函数后,肯定有8个寄存器已经保存到原 thread的PSP中了(注意这个thread,uC/OSIII普通任务都是thread模式的,使用PSP。中断进程叫handler模式,使用MSP。这也是Cortex-M3架构决定的)。
    那从任务中调用任务切换和从中断退出中调用的任务切换就没有一点区别吗?还是有一点的,从任务中调用任务切换是直接进入的PendSV中断;从中断退出中调用的任务切换是执行的咬尾中断,先退出原中断,然后进入PendSV中断,具体区别就是:从任务中进入PendSV处理函数,那8个寄存器是PendSV中断自己保存的;从中断退出后进入PendSV处理函数那8个寄存器是原中断保存的,不是PendSV保存的。但对PendSV处理函数而言,两者并无区别,反正给我保存了就行了,不管到底是我自己保存的还是你替我保存的。
    所以uC/OSIII在PendSV处理函数中的过程就是:一进来就保存剩下的8个寄存器:R4-R11。当然,要保存到PSP下面,这是原任务使用的堆栈,保存后就保证了原任务自己堆栈内容的完整,注意千万别弄错了保存到了MSP下面,MSP是中断函数使用的。 然后就进行任务优先级查找,出栈全部寄存器,返回thread模式,执行新任务。
    整个PendSv处理函数用汇编语言写成,在《os_cpu_a.asm》文件中:
OS_CPU_PendSVHandler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                        ; PSP is process stack pointer
    STMFD   R0!, {R4-R11}                             ; Save remaining regs r4-11 on process stack
    MOV32   R5, OSTCBCurPtr                      ; OSTCBCurPtr->OSTCBStkPtr = SP;
    LDR     R6, [R5]
    STR     R0, [R6]                                         ; R0 is SP of process being switched out
                                                                ; At this point, entire context of process has been saved
    MOV     R4, LR                                           ; Save LR exc_return value
    BL      OSTaskSwHook                               ; OSTaskSwHook();
    MOV32   R0, OSPrioCur                            ; OSPrioCur   = OSPrioHighRdy;
    MOV32   R1, OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    MOV32   R1, OSTCBHighRdyPtr              ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R2, [R1]
    STR     R2, [R5]
    ORR     LR, R4, #0xF4                              ; Ensure exception return uses process stack
    LDR     R0, [R2]                                         ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDMFD   R0!, {R4-R11}                             ; Restore r4-11 from new process stack
    MSR     PSP, R0                                        ; Load PSP with new process SP
    CPSIE   I
    BX      LR                                                  ; Exception return will restore remaining context

    可以看到,它明显分为了前后两部分,它的切换过程也很简单,就是先把原来任务的R4-R11保存好,然后找到任务就绪表中的最高已就绪TCB的指针OSTCBHighRdyPtr,读取它的SP和入栈的寄存器,执行出栈,任务切换。
    而值得说明的是,这个OSTCBHighRdyPtr是在调用PendSv进行切换之前准备好的。在任务中切换和在中断退出中切换所做的动作不同,但准备步骤相似。在任务中切换,最终要调用函数OSSched,它在《os_core.c》中,有如下语句:
OSPrioHighRdy   = OS_PrioGetHighest();    /* Find the highest priority ready  */
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
……
OS_TASK_SW();         /* Perform a task level context switch */
这里最后一句OS_TASK_SW函数就是开始调用PendSv进行切换.
    在中断退出中切换,是调用《os_core.c》中的函数OSIntExit,它也有以下语句:
OSPrioHighRdy   = OS_PrioGetHighest();     /* Find highest priority */
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;     /* Get highest priority task ready-to-run */
……
OSIntCtxSw();
最后一句OSIntCtxSw也是开始调用PendSv进行切换。而且,其实它与任务切换的OS_TASK_SW函数最终是完全相同的汇编代码,就是文章一开始提到的那一段,在《os_cpu_a.asm》中:
OSCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR
附PendSV处理函数的注释:
Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the  processor context on any exception, and restores same on return from exception. So only  saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception  this way means that context saving and restoring is identical whether it is initiated from  a thread or occurs due to an interrupt or exception.




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uC/OSIII在Cortex-M3的任务切换和中断退出分析 的相关文章

  • Cortex-M3利用SVC中断调用系统服务的例子

    SVC xff08 系统服务调用 xff0c 亦简称系统调用 xff09 和PendSV xff08 可悬起系统调用 xff09 xff0c 它们多用在上了操作系统的软件开发中 SVC用于产生系统函数的调用请求 例如 xff0c 操作系统通
  • 我想起我当初玩的DE1-SOC不就是双核ARM cortex A9么

    我想起我当初玩的DE1 SOC不就是双核ARM cortex A9么 确实这种A系列的就是跑Linux或者安卓 可惜你当初没有好好弄弄 xff0c 装个Linux就完事了 没有真正深入去学
  • Cortex-A7中断控制器GIC

    Cortex A7中断控制器GIC 中断号 芯片内部的中断都会引起IRQ InterruptGIC将所有的中断源 最多1020个中断ID 分为三类 SPI SharedPeripheralInterrupt 共享中断 xff0c 外部中断都
  • Error: Flash Download failed - “Cortex-M3“错误解决办法

    在使用STM32F103的时候 xff0c 使用DAP仿真器下载程序 xff0c 出现下载不了的情况 xff0c 错误信息如下 xff1a 输出框里打印信息如下 xff1a No Algorithm found for 08000000H
  • Cortex-M芯片低功耗开发

    文章目录 芯片的低功耗1 1 低功耗的测量数据1 2 低功耗的系统特性1 3 低功耗的系统需求1 3 1 Cortex M3和Cortex M4处理器的低功耗特点 1 4 低功耗系统特性1 4 1 休眠模式1 4 2 系统控制寄存器 xff
  • Cortex M4 SVC 中断

    Cortex SVC 中断 SVC 系统管理调用 异常优先级为1 xff0c SVC异常是由SVC指令触发 也可以直接设置NVIC寄存器触发异常 应用程序工作在非特权访问模式 xff0c 当需要特权模式访问系统资源时 xff0c 可以使用S
  • Cortex-M4和Cortex-M7中的SIMD指令

    SIMD指令简介 单指令多数据流 xff0c 即SIMD xff08 Single Instruction xff0c Multiple Data xff09 指一类能够在单个指令周期内同时处理多个数据元素的指令集 xff0c 利用的是数据
  • 集成Cortex-M0内核-- Integration and Implementation Manual手册学习

    根据使用场景 xff0c 配置并集成一个Cortex M0的内核 xff0c 暂时不涉及的实现的部分 目录 阅读手册 Chapter1 Introduction 1 1 About the processor 1 2 About integ
  • 基于Cortex-M的RTOS上下文切换详解及FreeRTOS实例

    文章目录 1 Cortex M MCU特性 1 1 操作模式 1 2 寄存器 1 2 1 核心寄存器 1 2 2 浮点寄存器 Floating Point registers 1 2 3 特殊寄存器 Special Registers 1
  • could not stop cortex-m device 问题

    出现问题原因 xff1a 调试程序过程中mdk突然奔溃 xff0c 之后就再也下载程序失败 xff0c 但是读取swd IDCODE OK 下载程序就报错 个人觉得应该是单片机内部保护了 问题图 问题处理办法 先检查3 3v和GND是否短路
  • 《Cortex-M0权威指南》之Cortex-M0技术综述

    Cortex M0权威指南 之Cortex M0技术综述 转载请注明来源 xff1a cuixiaolei的技术博客 Cortex M0 处理器简介 1 Cortex M0 处理器基于冯诺依曼架构 xff08 单总线接口 xff09 xff
  • ARM Cortex-M4和Cortex-M0+中断优先级及嵌套抢占问题

    转自 xff1a http blog chinaaet com jihceng0622 p 5100001238 坐在上海回北京的高铁上 xff0c 漫长的旅途着实让人感到无聊 xff08 没买到直达的高铁 xff0c 只能慢悠悠的走一站停
  • ARM Cortex M4 SVC指令作用

    xff08 1 xff09 SVC指令 xff1a 摘自 http infocenter arm com help index jsp topic 61 com arm doc dui0203ic Cacdfeci html 与更早版本的
  • IAR ARM Cortex-M3下载程序至RAM中运行

    默认icf文件中ROM地址为0x0800 0000 xff0c 通过修改其中地址可实现将代码下载到RAM中 新建Configuration 新建Configuration用于区分 Project gt Edit Configurations
  • 意外发现,Cortex-M7的性能和诸多关键参数碾压A7和R7

    origin https www amobbs com thread 5676525 1 1 html 之前一直以为ARM A R M M排在最后也最便宜 xff0c 肯定性能最低 xff0c 但最近意外发现并非如此 xff0c M7居然完
  • cortex-m3中寄存器

    简介 Cortex M3 是一个 32 位处理器内核 内部的数据路径是 32 位的 xff0c 寄存器是 32 位的 xff0c 存储器接 口也是 32 位的 CM3 采用了哈佛结构 xff0c 拥有独立的指令总线和数据总线 xff0c 可
  • ARM Cortex-M0+中断机制与中断编程步骤

    中断基础知识 为什么需要使用中断 xff1f 如果通过查询接收标志查看一个字节是否收到 xff0c 则需要时刻花费CPU等资源 但中断机制能够在收到一个字节后 xff0c 通知CPU把收到的字节取走 异常 xff1a CPU强行从正常运行的
  • 关于“ErrorFlash Download failed“Cortex-M3”的解决办法

    首先 xff0c 将仿真器连接电脑 xff0c 然后打开KEIL xff0c 点击FLash gt Erase xff0c 擦除Flash试一下 如果擦除不成功 xff0c 那么应该是的STM32的Flash被锁了 xff0c 要解锁一下
  • 嵌入式平台memcpy实验总结

    1 概述 最近项目中性能比较吃紧 经过跟踪发现 memcpy操作的性能存在一定问题 于是 做了一些尝试去验证一些想法 记录一下 环境 MDK530 Cortex M0芯片 主频80MHz左右 2 优化手段 在优化之前 我们要先确定基本的性能
  • Vscode EIDE+Cortex Debug搭建STM32开发仿真环境

    Embedded IDE 特色 支持8051 AVR STM8 Cortex M 0 0 3 4 7 RISC V Universal Gcc项目开发 支持导入 KEIL 项目 仅限 KEIL 5 及更高版本 支持安装标准 KEIL 芯片支

随机推荐