其实很简单:

    临界段就是不可中断的程序段,比如从UART中读取当前传递回来的值,如果有UART中断,此时这个值又会改变。同样临界段就是保护这类全局变量,如在读取时间节拍时,不应该被时钟更新时钟节拍标志。
    实现方法:就是关中断而已。
    关中断有3种情况:
1:虽关了中断还是可以有中断产生,那就是临界段本身开了中断?(自己理解是临界段内部自己又打开中断)这种方法不管他,没有用
2:清全局中断标志,这样是临界段完了后中断也是关的,不能回到临界前的状态
3:关全局中断前,保存全局中断标志,临界段后恢复。与2的区别是如果关全局中断前是开了全局中断的,3就可以恢复,而2不行,如果关全局中断前本身就是关的2,3一样。
注意:STM32有PRIMASK异常全局中断和faults故障全局中断,林阶段不用关faults PRIMASK和faults是程序状态寄存器CPSR的位。因此可以保存CPSR或者保存PRIMASK和faults如下是这两种方法 
  1. OS_cpu_a.asm文件中:
    1. OS_ENTER_CRITICAL
    2. CPSID I ;Disable all the interrupts
    3. PUSH {R1,R2}
    4. LDR R1,=OSInterrputSum;OSInterrputSum++
    5. LDRB R2,[R1]
    6. ADD R2, R2,#
    7. STRB R2,[R1]
    8. POP {R1,R2}
    9. BX LR
    1. ;/***************************************************************************************
    2. ;* 函数名称: OS_EXIT_CRITICAL
    3. ;*
    4. ;* 功能描述: 退出临界区
    5. ;*
    6. ;* 参 数: None
    7. ;*
    8. ;* 返 回 值: None
    9. ;*****************************************************************************************/
    10. OS_EXIT_CRITICAL
    11. PUSH {R1, R2}
    12. LDR R1,=OSInterrputSum;OSInterrputSum--
    13. LDRB R2,[R1]
    14. SUB R2, R2,#
    15. STRB R2,[R1]
    16. MOV R1,#
    17. CMP R2,# ; if OSInterrputSum=0,enable
    18. ; interrupts如果OSInterrputSum=0
    19. MSREQ PRIMASK, R1
    20. POP {R1, R2}
    21. BX LR
  1. #define OS_CRITICAL_METHOD
  2. #if OS_CRITICAL_METHOD ==
  3. #define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
  4. #define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
  5. #endif
  6. ;函数返回值存储在R0
  7. OS_CPU_SR_Save
  8. MRS R0, PRIMASK ;保存全局中断标志 ; Set prio int mask to mask all (except faults除了故障中断)
  9. CPSID I ;关中断
  10. BX LR
  11. ;通过R0传递参数
  12. OS_CPU_SR_Restore
  13. MSR PRIMASK, R0 ;恢复全局中断标志
  14. BX LR
 
UCOS开关中断函数移植
 
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()用来关中断和开中断。在执行临界段代码时要关中断,如果中断打开,临界段代码中的一些全局变量值可能会被中断服务子程序代码改变,或者因为中断引起的任务切换被其它任务函数改变。
 
何谓“临界段”?在网上搜了下:
 
临界段也称为关键代码段,它是指一个小代码段。在它能够执行前,它必须独占对某些共享资源的访问权。一旦线程执行进入了临界段。就意味着它获得了这些共享资源的访问权。那么在该线程处于临界段内的期间,其它同样需要独占这些共享资源的线程就必须等待,直到获得资源的线程离开临界段而释放资源。
 
在LPC2214上移植这两个函数。
在OS_CPU.H中定义采用第三种实现方法:
 
#define  OS_CRITICAL_METHOD    3
定义一个数据类型OS_CPU_SR
typedef unsigned int   OS_CPU_SR;  /* Define size of CPU status register (PSR = 32 bits) */
 
采用第3中方式,需要在UCOS-II函数中定义一个变量:
OS_CPU_SR  cpu_sr;
用来保存CPU的状态寄存器值。
 
定义关中断宏和开中断宏
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
 
函数声明:
#if OS_CRITICAL_METHOD == 3    /* Allocate storage for CPU status register          */    
    OS_CPU_SR  OS_CPU_SR_Save(void);
    void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif
以上都是在OS_CPU.H文件中的。
 
NO_INT      EQU     0xC0        ; Mask used to disable interrupts (Both FIR and IRQ)
OS_CPU_SR_Save()和OS_CPU_SR_Restore()函数用汇编语言编写,在OS_CPU_A.S文件中
OS_CPU_SR_Save
        MRS     R0,CPSR                     1
        ORR     R1,R0,#NO_INT               2
        MSR     CPSR_c,R1                   3
        MRS     R1,CPSR                     4
        AND     R1,R1,#NO_INT               5
        CMP     R1,#NO_INT                  6
        BNE     OS_CPU_SR_Save             7
        MOV     PC,LR                       8
 
1-      读CPSR,把CPSR的值送到R0
2-      把R0和常量#NO_INT相或,结果送给R1,把F和I位置1,禁止IRQ中断和FIQ中断。
3-      把R1的值送给CPSR的低8位,CPSR_c的_c是位域,指CPSR的低8位。
4-      把修改后的CPSR值送到R1
5-      R1的值和#NO_INT相与,结果送到R1
6-      比较R1和#NO_INT是否相等
7-      不相等,跳到OS_CPU_SR_Save重新关中断,直到相等。
8-      LR保存的是在调用OS_CPU_SR_Save函数时的断点地址,把LR的值送到PC,退出OS_CPU_SR_Save函数,开始执行临界段代码。这条命令的功能相当于51中的RET。
   注意:ARM中调用子程序时不会自动保存CPSR的值到SPSR,所以子程序返回时,执行MOV     PC,LR也不会把SPSR的值返回到CPSR。这是ARM种调用子程序和进入中断的区别。
 
   汇编函数的返回值是通过R0返回的,把修改前的CPSR值保存到cpu_sr.
OS_CPU_SR_Restore
        MSR     CPSR_c,R0           1
        MOV     PC,LR               2
1-      把R0的值送到CPSR的低8位。在ARM中用R0传递函数的参数,这句指令就是把保存在cpu_sr中的值送到CPSR低8位。高24位没有修改。为什么不直接用MSR     CPSR,R0呢?因为ARM指令中规定MSR命令中,CPSR必须指定位域。把这句改成MSR     CPSR_cxsf,R0,即把R0的32位都送给CPSR,应该也没问题。不过在OS_CPU_SR_Save函数中,CPSR的高24位并没有改变。所以这里只需要把保存在cpu_sr中的低8位送到CPSR就可以了。
2-退出OS_CPU_SR_Restore函数。

【转载】ucos临界段的更多相关文章

  1. RTX——第11章 临界段,任务锁和中断锁

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 临界段代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被 ...

  2. FreeRTOS 临界段和开关中断

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 临界段代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被中断 ...

  3. μC/OS-Ⅲ中的临界段代码

    临界段代码(critical sections),也叫临界区(critical region),是指那些必须完整连续运行,不可被打断的代码段.μC/OS-Ⅲ系统中存在大量临界段代码.采用两种方式对临界 ...

  4. 临界段CCriticalSection的使用

    类CCriticalSection的对象表示一个“临界区”,它是一个用于同步的对象,同一时刻仅仅同意一个线程存取资源或代码区.临界区在控制一次仅仅有一个线程改动数据或其他的控制资源时很实用.比如,在链 ...

  5. Windows环境下多线程编程原理与应用读书笔记(6)————临界段及其应用

    <一>临界段 临界段对象通过提供所有线程必须共享的对象来控制线程.只有拥有临界段对象的线程才能够访问保护的资源.在另一个线程可以访问该资源之前,前一线程必须释放临界段对象,一遍新的线程可以 ...

  6. RTX临界段,中断锁与任务锁

    临界段         代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被中断,在进入临界段之前须关中断,而临界段代码执行完毕后,要立即开中断.    ...

  7. FreeRTOS不允许在中断服务程序和临界段中执行不确定的性的操作

    举例 等待事件标志组的任务,要是在中断服务程序中设置事件标志组,但不知道当前有多少个任务在等待此事件标志,这个操作即为不确定性操作,为了不在中断服务程序中执行此不确定性操作,只在中断服务程序中给一确定 ...

  8. 8.0-uC/OS-III临界段

    1.临界段 (临界段代码,也叫临界区,是指那些必须完整连续运行,不可被打断的代码段) 锁调度器,可以执行ISR,开启调度器不可执行ISR: (1).临界段代码,也称作临界域,是一段不可分割的代码. u ...

  9. FreeRTOS 中断配置和临界段

    中断屏蔽寄存器 PRIMASK.FAULTMASK和BASEPRI 1.PRIMASK:这是个只有1个位的寄存器.当它置1时, 就关掉所有可屏蔽的异常,只剩下 NMI和硬fault可以响应.它的缺省值 ...

随机推荐

  1. centos7搭建Cisco上网方式

    1.下载脚本 wget https://git.io/vpnsetup-centos -O vpnsetup.sh 2.修改 vi vpnsetup.sh 替换为你自己的值: YOUR_IPSEC_P ...

  2. usb 枚举流程

    Linux-USB总线驱动分析 如下图所示,以windows为例,我们插上一个没有USB设备驱动的USB,就会提示你安装驱动程序 为什么一插上就有会提示信息? 是因为windows自带了USB总线驱动 ...

  3. UEditor可以如何直接复制word的图文内容到编辑器中?

    下载并打开工程: 文档的上传 运行: 复制随便一篇文档,粘贴进去. 通过粘贴后,文档以及图片被粘贴进来了,看看html代码:   图片全部使用img标签统一.传输进度条的效果也不错. 文档图片被放置在 ...

  4. Eclipse搭建服务器,实现与Android的简单通信

    ---恢复内容开始--- 目标:实现客户端(Android App)与服务器(PC)的简单通信 相关准备:eclipse_mars.tomcat8.Android Studio 实现: 1.java环 ...

  5. python之路(十一)-socke开发

    socket简介 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. so ...

  6. Solr Cloud

    bin/solr start -cloud -s example/cloud/node1/solr -p 8983 -z node13:2181,node14:2181,node15:2181/usr ...

  7. cvpr2018(转发一篇头条)

    CVPR 2018:腾讯图像去模糊.自动人像操纵最新研究 新智元 2018-05-29 14:13:04 新智元报道 来源:腾讯优图 编辑:江磊.克雷格 [新智元导读]即将在6月美国盐湖城举行的计算机 ...

  8. iOS TouchID & FaceID

    import UIKit import LocalAuthentication //指纹识别必须用真机测试,并且在iOS8以上系统,如果是FaceID至少IOS11以上. class Authenti ...

  9. linux配置gitlab步骤

    1.安装git命令 yum install -y git 2.查看安装git的版本 git --version 3.创建用于保存项目的文件夹 mkdir 项目文件夹 4.切换目录到项目文件夹 cd 项 ...

  10. 微博第三方登录使用social_django实现显示登陆的用户名

    首先修改social_soce源码,将用户信息添加进cookie 将其修改为:  response =  backend.strategy.redirect(url)    payload = jwt ...