临界段    
    代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断。为确保临界段代码的执行不被中断,在进入临界段之前须关中断,而临界段代码执行完毕后,要立即开中断。 
    由于Cortex-M3/M4的RTX内核库中没有关闭中断的操作,也就是说RTX的源码中不存在临界段。

中断锁
    中断锁就是RTOS提供的开关中断函数,因为Cortex-M3/M4的RTX源码中没有关闭中断的操作,所以也就没有提供开关中断函数。 由于RTX没有提供开关中断函数,如果用户自己的应用代码需要开关中断的话怎么办呢?
    裸机时如何开关中断的,在使用了RTX后仍然使用以前的开关中断函数即可

任务锁
    为了防止当前任务的执行被其它高优先级的任务打断而提供的锁机制就是任务锁。实现任务锁可以通过给调度器加锁或者直接关闭RTOS内核定时器(就是前面一直说的系统滴答定时器)来实现。 
    1.通过给调度器加锁实现 给调度器加锁的话,就无法实现任务切换,高优先级任务也就无法抢占低优先级任务的执行,同时高优先级任务也是无法向低优先级任务切换的。像uCOS-II和uCOS-III是采用的这种方法实现任务锁。特别注意,这种方式只是禁止了调度器工作,并没有关闭任何中断。 
    2.通过关闭RTOS内核定时器实现 关闭了RTOS内核定时器的话,也就关闭了通过RTOS内核定时器中断实现任务切换的功能,因为在退出定时器中断时需要检测当前需要执行的最高优先级任务,如果有高优先级任务就绪的话需要做任务切换。RTX操作系统是采用的这种方式实现任务锁的。

os_resume

  1. #include <rtl.h>
  2. void os_resume (
  3. U32 sleep_time ); /* Number of ticks the system was in sleep mode. */

说明:

    该函数唤醒操作系统调度器. 客户在调用了os_suspend之后必须调用该方法来重新使能调度器.
    sleep_time参数标识系统将在休眠或者掉电模式下呆多久. 以系统周期作为测量依据.

返回值:

    无

注意要点:

    该函数只能在系统空闲任务下调用. 
    单系统处于power_down模式下,tick定时器将不再运行. 

例程:

    The wake-up timer, when expired, generates the interrupt and wakes-up the system. Hence, it must run also in power-down mode. The system resumes operation and needs to call the function os_resume(). This function restores the RTX and re-enables the OS task scheduler
  1. /* After Wake-up */
  2. sleep = (tc - LPC_WWDT->TV) / 250;
  3. }
  4. os_resume(sleep);


os_suspend

  1. #include <rtl.h>
  2. U32 os_suspend (void);

说明:

    该函数挂起操作系统调度器. 该函数将测量需要多久进入掉电模式并关闭操作系统调度器.当函数返回的时候,操作系统调度器就被挂起了
    对于RTX,当调用了os_suspend之后,就必须调用os_resume 来恢复系统调度.

返回值:

    无

注意要点:

    只能在空闲任务中调用该函数. 
    操作系统进入power_down模式.系统tick定时器被禁止. 

例程:

  1. #include <rtl.h>
  2. __task void os_idle_demon (void) {
  3. uint32_t sleep;
  4. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* Configure Cortex-M3 for deep sleep */
  5. PWR->CR &= ~PWR_CR_PDDS; /* Enter Stop mode when in deepsleep */
  6. PWR->CR |= PWR_CR_LPDS; /* Voltage regulator in low-power */
  7. /* Enable LSI clock and wait until ready */
  8. RCC->CSR |= RCC_CSR_LSION;
  9. while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
  10. /* Enable power interface clock */
  11. RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  12. /* Disable backup domain write protection */
  13. PWR->CR |= PWR_CR_DBP;
  14. /* Select LSI as clock source for RTC and enable RTC */
  15. RCC->BDCR &= ~RCC_BDCR_RTCSEL;
  16. RCC->BDCR |= RCC_BDCR_RTCSEL_1;
  17. RCC->BDCR |= RCC_BDCR_RTCEN;
  18. /* Disable the write protection for RTC registers */
  19. RTC->WPR = 0xCA;
  20. RTC->WPR = 0x53;
  21. /* Configure RTC auto-wakeup mode */
  22. RTC->ISR &= ~RTC_ISR_WUTF; /* Clear wakeup timer flag */
  23. RTC->CR &= ~RTC_CR_WUCKSEL; /* Set RTC clock to 2kHz */
  24. RTC->CR |= RTC_CR_WUTIE; /* Enable RTC wakeup timer interrupt */
  25. /* Configure EXTI line 22 for wakeup on rising edge */
  26. EXTI->EMR |= (1 << 22); /* Event request is not masked */
  27. EXTI->RTSR |= (1 << 22); /* Rising trigger enabled */
  28. NVIC_EnableIRQ (RTC_WKUP_IRQn); /* Enable RTC WakeUp IRQ */
  29. for (;;) {
  30. /* HERE: include optional user code to be executed when no task runs. */
  31. sleep = os_suspend (); /* OS Suspend */
  32. if (sleep) {
  33. RTC->ISR &= ~RTC_ISR_WUTF; /* Clear timer wakeup flag */
  34. RTC->CR &= ~RTC_CR_WUTE; /* Disable wakeup timer */
  35. while ((RTC->ISR & RTC_ISR_WUTWF) == 0);
  36. /* RTC clock is @2kHz, set wakeup time for OS_TICK >= 1ms */
  37. RTC->WUTR = (sleep * (OS_TICK / 1000) * 2);
  38. RTC->CR |= RTC_CR_WUTE; /* Enable wakeup timer */
  39. __WFE (); /* Enter STOP mode */
  40. /* After Wake-up */
  41. if ((RTC->ISR & RTC_ISR_WUTF) == 0) {
  42. sleep = 0; /* We didn't enter Stop mode */
  43. }
  44. }
  45. os_resume (sleep); /* OS Resume */
  46. }
  47. }

tsk_lock

  1. #include <rtl.h>
  2. void tsk_lock (void);

说明:

    该函数禁止RTX内核时间中断,也就自然禁止了操作系统调度器.

返回值:

    无

注意要点:

    不能在中断向量中调用该函数. 
    不能在中断处理程序中调用该函数. 
    当禁用了内核时间中断,操作系统时间中断和时间片轮转中断被禁止,超时功能不在工作. 因此,强烈建议关RTX内核定时器中断的时间越短越好. 

例程:

  1. #include <rtl.h>
  2. void protect_critical_op () {
  3. tsk_lock ();
  4. do_critical_op ();
  5. tsk_unlock ();
  6. }

tsk_unlock

  1. #include <rtl.h>
  2. void tsk_unlock (void);

说明:

   函数tsk_unlock用于使能RTX内核定时器中断,因此也就重新开启任务切换。注意tsk_unlock一定要跟tsk_lock配套使用.

返回值:

    无

注意要点:

    函数tsk_lock不支持嵌套调用. 
    不允许在中断服务程序中调用tsk_lock.

例程:

  1. #include <rtl.h>
  2. void protect_critical_op () {
  3. tsk_lock ();
  4. do_critical_op ();
  5. tsk_unlock ();
  6. }

















RTX临界段,中断锁与任务锁的更多相关文章

  1. Linux——临界段,信号量,互斥锁,自旋锁,原子操作

    一. linux为什么需要临界段,信号量,互斥锁,自旋锁,原子操作? 1.1. linux内核后期版本是支持多核CPU以及抢占式调度.这里就存在一个并发,竞争状态(简称竟态). 1.2. 竞态条件 发 ...

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

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

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

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

  4. FreeRTOS 调度锁,任务锁和中断锁

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 调度锁调度锁就是 RTOS 提供的调度器开关函数,如果某个任务调用了调度锁开关函数,处于调度锁开和调度锁关之 ...

  5. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  6. FreeRTOS 临界段和开关中断

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

  7. FreeRTOS 中断配置和临界段

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

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

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

  9. jvm高级特性(6)(线程的种类,调度,状态,安全程度,实现安全的方法,同步种类,锁优化,锁种类)

    JVM高级特性与实践(十三):线程实现 与 Java线程调度 JVM高级特性与实践(十四):线程安全 与 锁优化 一. 线程的实现 线程其实是比进程更轻量级的调度执行单位. 线程的引入,可以把一个检查 ...

随机推荐

  1. swagger常用注解说明

    常用到的注解有: Api ApiModel ApiModelProperty ApiOperation ApiParam ApiResponse ApiResponses ResponseHeader ...

  2. pygame 笔记-7 生命值/血条处理

    通常游戏中的角色都有所谓的生命值,而且头顶上会有一个血条显示.生命值无非就是一个属性而已,很容易在Player.py类中增加,头顶上的血条其实就是绘制二个矩形,叠加在一起. 以上节的Player.py ...

  3. 基于物理的渲染—HDR Tone Mapping

    在游戏引擎渲染管线中,我们对于R.G.B通道颜色信息的数值范围通常设置在[0,1]之间(或者是[0,255]).其中,0代表没有光亮度,1代表显示器能够显示的最大光亮度.这个表示方式虽然直接易懂,但它 ...

  4. Gradle初识

    一.安装配置 gradle官方网站https://gradle.org/,下载下来是一个压缩包,解压到合适的目录即可,然后配置环境变量(GRADLE_HOME,Path),略去. 二.IDEA配置 N ...

  5. 【转】Selenium - 封装WebDrivers (C#)

    本文转载自:http://www.cnblogs.com/qixue/p/3977135.html Web element仍然使用OpenQA.Selenium.IWebElement, 本类库将Se ...

  6. adminlte.js-页面模版

    html页面 使用cdn加速. <!DOCTYPE html> <html lang="en"> <head> <title>Tes ...

  7. Mongodb: Sort operation used more than the maximum 33554432 bytes of RAM

    上线许久的产品突然爆出了一个Mongodb 查询的BUG,错误如下: "exception":"org.springframework.data.mongodb.Unca ...

  8. Android ListView滚动到指定的位置

    这篇文章主要给大家介绍了Android中的ListView如何滚动到指定的位置,文章给出了两种解决的方法,并给出详细的示例代码,相信会对大家的理解和学习很有帮助,有需要的朋友们下面来一起看看吧. 本文 ...

  9. UESTC 1034 AC Milan VS Juventus 分情况讨论

    AC Milan VS Juventus Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Oth ...

  10. php: 统计在线人数

    <?php $filename='online.txt';//数据文件 $cookiename='VGOTCN_OnLineCount';//cookie名称 $onlinetime=60;// ...