1、Cortex-M3 的PSP和MSP

曾经在STM32上使用过RT thread和uC/OS,对于任务切换代码一直是一知半解,没有自己手动写出来过,对于任务切换后的ORR   LR, LR, #0x04; Ensure exception return uses process stack也不是很理解,一次偶然的机会,遇到网上有人问这个问题,才去深入研究一下。Cortex‐M3 拥有两个堆栈指针,然而它们是banked,因此任一时刻只能使用其中的一个:

主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程)。

进程堆栈指针(PSP):由用户的应用程序代码使用。堆栈指针的最低两位永远是0,这意味着堆栈总是4 字节对齐的。

由此可以看出,在一个系统里有两大部分,一是操作系统和中断,一是用户用户程序,他们使用的资源是不一样的,在任务调度的时候,中断(任务调度的中断)返回到用户程序所以要使用PSP。

2、Linux系统中断中能否使用Sleep

这个是我一个同学的面试题,说给我的时候我第一反应是可以,在中断中使用Sleep不会使得中断挂起,在任务中使用Sleep会将当前的任务挂起,Sleep的原理是根据Sleep的参数N暂停当前的任务,N个周期(也可能是MS)后将该任务置为就绪态,换言之,Sleep实际上就是一次任务调度,那为什么不可以的,我还进一步解释,在uC/OS中,在中断的结尾都会调用OS_INT_EXIT()函数来进行任务的调度,Sleep与OS_INT_EXIT只是函数名不同,最终都是会调用调度器的。

哈哈,对于正确答案我想大家都猜到了,那就是当然不可以的啦,但是我的解释貌似天衣无缝哦,那是因为我是使用uC/OS来解释的,Linux系统当然和uC/OS不同,回头看看,在Cortex-M3的硬件中有MSP和PSP,那么他的设计初衷是什么,那就是操作系统(包括中断)和用户程序分(隔)离,或者说是保护操作系统,防止遭到破坏,在这种思想下,Linux系统中,对于涉及到系统核心的东西使用保护的,不是所有的地方都是可见的,uC/OS是系统和应用程序一起编译,只要是全局变量都是可以见的,而Linux不同,在中断上下为中,current宏是无效的,所以此时是无法进行任务调度的。

以上是我结合Cortex-M3内核的硬件,从隔离和保护的思想去解释为什么Linux下,中断中不能使用Sleep。下面给出我查阅资料的官方解释,主要是《linux内核设计与实现》上的内容。

1、进程上下文

可执行代码是进程的重要组成部分,这些代码从一个可执行文件载入到进程的地址空间执行。一般的程序在用户空间执行,当一个程序执行了系统调用或者触发了某个异常,它就陷入了内核空间,此时,我们称内核代表进程执行并处于进程上下文中。在此上下文中current宏是有效的。(系统调用和异常处理程序是对内核明确定义的接口,进程只有通过这些接口才能陷入内核执行—对内核的所有访问都必须通过这些接口。

2、中断上下文

当执行一个中断处理程序时,内核处于中断上下文中,中断上下文和进程并没有任何瓜葛。与current宏也是不相干的(尽管它会指向被被中断的进程)。因为没有后备进程,所以中断上下文不可以睡眠,否则又怎能再对它重新调度呢?因此,不能从中断上下文中调用某些函数(就是被中断处理程序限制的函数,Sleep就是其中一个)。

事实上,除了MSP和PSP之外,处理器很多的寄存器都是banked,用户程序和中断程序使用的寄存器是不同的,所以进程上下文和中断上下文环境是不同的,如果在中断上下文中进行任务调度,是没有办法保存进程上下文信息的,所以如果这个时候调度就是有问题的,软件上阻止了该调度——即current宏此时是不可见的,从而无法进行调度。

从Cortex-M3的MSP 和PSP谈Linux能否在中断中使用Sleep的更多相关文章

  1. Cortex-M3双堆栈MSP和PSP+函数栈帧

    为了防止几百年以后找不到该文章,特此转载 ------------------------------------------------开始转载--------------------------- ...

  2. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...

  3. ARM Cortex M3(V7-M架构)硬件启动程序 一

    Cortex-m3启动代码分析笔记 启动代码文件名是STM32F10X.S,它的作用先总结下,然后再分析. 启动代码作用一般是: 1)堆和栈的初始化: 2)中断向量表定义: 3)地址重映射及中断向量表 ...

  4. stm32和cortex M3学习内核简单总结

    1.stm32综述 2.寄存器组 3.操作模式和特权级别 4.存储器映射 5.中断和异常 6.其他 Stm32综述 这可以说是我第一款认真学习的单片机了,学完这个就要开启我通往arm9的大门了,接下来 ...

  5. ARM Cortex M3系列GPIO口介绍(工作方式探讨)

    一.Cortex M3的GPIO口特性    在介绍GPIO口功能前,有必要先说明一下M3的结构框图,这样能够更好理解总线结构和GPIO所处的位置. Cortex M3结构框图     从图中可以看出 ...

  6. ARM 架构、ARM7、ARM9、STM32、Cortex M3 M4 、51、AVR 之间有什么区别和联系?(转载自知乎)

    ARM架构:  由英国ARM公司设计的一系列32位的RISC微处理器架构总称,现有ARMv1~ARMv8种类. ARM7:       一类采用ARMv3或ARMv4架构的,使用冯诺依曼结构的内核. ...

  7. app和bootloader跳转 MSP与PSP

    1.不要把跳转函数放在中断中,如此导致在跳转后的app或者bootloder都是在中断状态,只要你一开启该中断,就可能出现硬件中断了 2.如果你的APP使用了ucos系统,在跳转函数中还需要增加__s ...

  8. STM32学习之路入门篇之指令集及cortex——m3的存储系统

    STM32学习之路入门篇之指令集及cortex——m3的存储系统 一.汇编语言基础 一).汇编语言:基本语法 1.汇编指令最典型的书写模式: 标号 操作码        操作数1, 操作数2,... ...

  9. Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors

    Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...

随机推荐

  1. Vue父组件向子组件传递方法(自定义方法)并且子组件向父组件传递数据

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 支付宝APP支付(基于Java实现支付宝APP支付)

    贴一下支付核心代码,以供后续参考: 业务层 import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; ...

  3. 异常-java.util.concurrent.TimeoutException: Futures timed out after [100000 milliseconds]

    1 详细异常 java.util.concurrent.TimeoutException: Futures timed out after [100000 milliseconds] at scala ...

  4. C++——inline function

    前言 当代码写复杂后,一定会封装出大量的函数,这会导致两个问题: ①函数越多,栈的消耗也越厉害 疑问:为什么代码复杂了.函数变多了,栈消耗的就很厉害? 答:因为这会导致函数的调用深度可能会很深,比如: ...

  5. 动态规划——python

    1.爬楼梯问题一个人爬楼梯,每次只能爬1个或两个台阶,假设有n个台阶,那么这个人有多少种不同的爬楼梯方法 动态规划的状态转移:第 i 个状态的方案数和第 i-1, i-2时候的状态有关,即:dp[i] ...

  6. MySQL进阶14--标识列(自增序列/auto_increment)--设置/展示步长--设置/删除标示列

    /*进阶14 标识列 又称为自增序列; 含义 : 可以不用手动的插入值, 系统提供默认的序列值(1-->n) 特点 : 1.标识列必须和主键搭配? 不一定,但要求是一个key 2.一个表可以有几 ...

  7. jar包中存在包名和类名都相同的情况

    情况: 在maven中引入两个包都有项目的包名和类名,只是jar包的名字不同.两个包的一部分在代码中的不同地方都需要用到. 网上找的大部分都是: 只有改变编译器优先选择的jar顺序(这个顺序是可以改变 ...

  8. C语言入坑指南-缓冲区溢出

    前言 缓冲区溢出通常指的是向缓冲区写入了超过缓冲区所能保存的最大数据量的数据.如果说之前所提到的一些问题可能只是影响部分功能的实现,那么缓冲区溢出将可能会造成程序运行终止,被不安全代码攻击等严重问题, ...

  9. 远程jupyter+pycharm配置

    前言 作为一个数据工程师,最喜欢的事情就是不停的在现实的服务端环境调试代码的参数.我们在本地的环境与生产的状况决然不同,我们一开始在本地写代码测试再部署到服务端的三板斧就不适用了. 最好的方式可以直接 ...

  10. c++ 构造函数执行顺序

    开辟内存空间. 按照成员变量声明的顺序开始构造成员变量. 如果成员变量在初始化列表中, 就会执行该变量类型的拷贝构造函数. 如果成员变量没有在初始化列表中, 就会执行该变量类型的缺省构造函数. 进入函 ...