zoukankan      html  css  js  c++  java
  • RT-Thread 之临界段保护

    1、什么是临界段

    临界段就是一段在执行的时候不能被中断的代码段。在RT-Thread里面这个临界段最常出现的就是对全局变量的操作。

      那么什么情况下临界段会被打断? 一个是系统调度,另一个是外部中断。在RT-Thread里面,系统调度,最终也是产生PendSV中断,在PendSV Handler里面实现线程的切换。所以还是可以归结为中断。既然这样,RT-Thread对临界段的保护就处理得很干脆了,直接把中断全部关了,NMIFAULT和硬FAULT除外。

    2、cortex-M 内核快速关中断指令

    为了快速开关中断,cortex-M 内核专门设置了一条CPS指令,有4种用法,具体如下:

    CPSID I ;PRIMASK=1 ; 关中断
    CPSIE I ;PRIMASK=0 ; 开中断
    CPSID F ;FAULTMASK=1; 关异常
    CPSIE F ;FAULTMASK=0; 开异常
    PRIMASK 和 FAULTMASK 是 Cortex-M 内核里面三个中断屏蔽寄存器中的两个,还有一个是 BASEPRI,有关这三个寄存器的详细用法见下表。

     3、关中断

    RT-Thread 关中断的函数在 contex_rvds.s 中定义,在 rthw.h 中声明,具体实现:
    ;/*
    ; * rt_base_t rt_hw_interrupt_disable();
    ; */
    rt_hw_interrupt_disable PROC;         (1)
    EXPORT rt_hw_interrupt_disable;      (2)
    MRS r0, PRIMASK;                      (3)
    CPSID I;                             (4)
    BX LR;                               (5)
    ENDP;                                 (6)    

    (1)关键字PROC表示汇编子程序的开始

    (2)使用EXPORT 关键字导出标号 rt_hw_interrupt_disable,使其具有全局属性,在外部头文件声明后(在rthw.h中声明),就可以在C文件中调用。

    (3)通过MRS指令将特殊寄存器PRIMASK的值存储到通用寄存器r0中,当在C中调用汇编子程序返回时,会将r0作为函数返回值。所以在C中调用rt_hw_interrupt_disable()时,需要事先声明一个变量用来存储rt_hw_interrupt_disable()的返回值,即r0寄存器的值,也就是PRIMASK的值。

    (4)关闭中断,即使用CPS指令将PRIMASK寄存器的值置1,

    在这里,我敢肯定,一定会有人有这样一个疑问:关中断,不就是直接使用 CPSID I 指令就行了嘛,为什么还要第三步,即在执行 CPSIDI 指令前,要先把 PRIMASK 的值保存起来?这个疑问接下来在“临界段代码的应用”这个小结揭晓。

    (5)子程序返回

    (6)ENDP表示汇编子程序结束,与PROC成对使用。

    4、开中断

    RT-Thread 开中断的函数在 contex_rvds.s 中定义,在 rthw.h 中声明,具体实现见:
    ;/*
    ; * void rt_hw_interrupt_enable(rt_base_t level);
    ; */
    rt_hw_interrupt_enable PROC;         (1)
    EXPORT rt_hw_interrupt_enable;       (2)
    MSR PRIMASK, r0                      (3)
    BX LR;                               (4)
    ENDP;                                (5)

     (1)关键字PROC表示汇编子程序开始。

    (2)使用EXPORT导出标号rt_hw_interrupt_disable(),使其具有全局属性,在外部头文件中声明后(在rthw.h中声明),就可以在C文件中调用。

    (3)通过MRS指令将通用寄存器r0的值存储到特殊寄存器PRIMASK中,当在C中调用汇编子程序返回时,会将第一个形参传入到通用寄存器r0。所以在C中调用rt_hw_interrupt_disable()的时候,需要传入一个形参。该形参是进入临界段之前保存的PRIMASK的值。这个时候又有人会问,开中断,不就是使用 CPSIE I 指令就行了

    嘛,为啥跟我等凡人想的不一样?其中奥妙将在接下来“临界段代码的应用”这个小结揭晓。
    (4)子程序返回
    (5)ENDP汇编子程序结束,与PROC成对使用。
  • 相关阅读:
    asp.net实现页面的一般处理程序(CGI)学习笔记
    .NET下的状态(State)模式 行为型模式
    (插件Plugin)AssemblyLoader解决方案(插件开发)
    SQL基础编写基本的SQL SELECT 语句
    在查询语句中使用NOLOCK和READPAST(ZT)
    C# 3.0语言增强学习笔记(一)
    ram,rom,flash
    自动激活你的ActiveX控件
    用C#编写ActiveX控件(二)
    用C#编写ActiveX控件(一)
  • 原文地址:https://www.cnblogs.com/tansuoxinweilai/p/14956689.html
Copyright © 2011-2022 走看看