硬汉嵌入式论坛

 找回密码
 立即注册
查看: 10645|回复: 9
收起左侧

[μCOS-III] uCOS和FreeRTOS在临界区上处理的不同方式,不过本质上是一样的

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2015-8-19 09:08:49 | 显示全部楼层 |阅读模式
uCOS-II和III主要是下面四种情况:
#define CPU_CRITICAL_METHOD_NONE                        0u  
#define CPU_CRITICAL_METHOD_INT_DIS_EN               1u  
#define CPU_CRITICAL_METHOD_STATUS_STK              2u  
#define CPU_CRITICAL_METHOD_STATUS_LOCAL         3u  

1.    当CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_INT_DIS_EN时
      这种方式最简单,即直接使用处理器的开中断和关中断指令来实现宏。但是不推荐使用这种方式,因为不支持中断嵌套,
      但是考虑到有些处理器或者编译器仅支持这种方式,不得不选择这种方式。
2.    当CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_INT_DIS_EN时
      这种方法稍复杂些,但可使CPU中断使能标志的状态在临界段前和临界段后不发生变化。
         进入临界段前:
     (1) Push/save  中断状态保存到堆栈中
     (2) Disable    关闭中断
         退出临界段:
     (3) Pop/restore  恢复中断标志
3.    当CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL时
      这种方法的前提是,用户使用的C编译器具有扩展功能。用户可获得程序状态字的值,这样就可把该值保存在C函数的局部
      变量中,而不必压到堆栈里。上面的宏定义就是采用的这种方式,也就是(1),(2)注释的地方。
================================================================================
对于FreeRTOS临界区的处理代码有两个,一个是任务里面的临界区处理,另一个是中断里面的临界区处理,下面是任务里面临界区处理
#define portENTER_CRITICAL()              vPortEnterCritical()
#define portEXIT_CRITICAL()                 vPortExitCritical()
================================================================
void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();
   uxCriticalNesting++;
    __dsb( portSY_FULL_READ_WRITE );
    __isb( portSY_FULL_READ_WRITE );

    /* This is not the interrupt safe version of the enter critical function so
    assert() if it is being called from an interrupt context.  Only API
    functions that end in "FromISR" can be used in an interrupt.  Only assert if
    the critical nesting count is 1 to protect against recursive calls if the
    assert function also uses a critical section. */
    if( uxCriticalNesting == 1 )
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}
/*--------------------------------------------------------------------------------------------------------*/
void vPortExitCritical( void )
{
    configASSERT( uxCriticalNesting );
   uxCriticalNesting--;
    if( uxCriticalNesting == 0 )
    {
        portENABLE_INTERRUPTS();
    }
}
=====================================================================
下面是是中断里面的临界区处理,其实这个方式跟uCOS的方式CPU_CRITICAL_METHOD_STATUS_LOCAL 基本一样。
#define portSET_INTERRUPT_MASK_FROM_ISR()                ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)          vPortClearInterruptMask(x)
----------------------------------------------------------------------------------------------
__asm uint32_t ulPortSetInterruptMask( void )
{
    PRESERVE8

    mrs r0, basepri
    mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
    msr basepri, r1
    bx r14
}
/*-----------------------------------------------------------*/
__asm void vPortClearInterruptMask( uint32_t ulNewMask )
{
    PRESERVE8

    msr basepri, r0
    bx r14
}
====================================================================
其实不论是uCOS或者FreeRTOS为什么要采用这种方式处理临界区,直接开关中断不就可以了么,主要还是因为我们
直接的开关中断方式不支持在开关中断之间的代码的里面再次执行开关中断的嵌套处理,假如当前我们的代码是关闭
中断的,嵌套了一个含有开关中断的临界区代码后,退出时中断就成开的了,这样就出问题了。
回复

使用道具 举报

5

主题

578

回帖

593

积分

版主

Rank: 7Rank: 7Rank: 7

积分
593
发表于 2015-8-19 11:14:01 | 显示全部楼层
不会吧。。。我记得rtt在cm系列中就是直接用开关中断的方式,只不过它是用一个中间变量保存标志的,支持嵌套操作,但是没有这种嵌套层数++--做法
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2015-8-19 11:23:20 | 显示全部楼层

回 myxiaonia 的帖子

myxiaonia:不会吧。。。我记得rtt在cm系列中就是直接用开关中断的方式,只不过它是用一个中间变量保存标志的,支持嵌套操作,但是没有这种嵌套层数++--做法 (2015-08-19 11:14) 
最近打算把硬件外设驱动里面的开关中断方式全部改成所用系统的开关中断方式,FreeRTOS的还得中断和任务分开操作,的确有些麻烦。
回复

使用道具 举报

5

主题

578

回帖

593

积分

版主

Rank: 7Rank: 7Rank: 7

积分
593
发表于 2015-8-20 09:21:50 | 显示全部楼层
我把rtt的代码贴过来了
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROC
    EXPORT  rt_hw_interrupt_disable
    MRS     r0, PRIMASK
    CPSID   I
    BX      LR
    ENDP

;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable    PROC
    EXPORT  rt_hw_interrupt_enable
    MSR     PRIMASK, r0
    BX      LR
    ENDP

其实lwip移植也有开关中断代码移植,思路一模一样,用的和它一样的方法
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2015-8-20 09:27:28 | 显示全部楼层

回 myxiaonia 的帖子

myxiaonia:我把rtt的代码贴过来了
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable   &#160ROC
....... (2015-08-20 09:21) 
这个跟UCOS一样的,基本是通用做法。
=================================================
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;********************************************************************************************************

OS_CPU_SR_Save
    MRS     R0, PRIMASK                                         ; Set prio int mask to mask all (except faults)
    CPSID   I
    BX      LR

OS_CPU_SR_Restore
    MSR     PRIMASK, R0
    BX      LR
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2015-8-20 09:29:21 | 显示全部楼层

回 myxiaonia 的帖子

myxiaonia:我把rtt的代码贴过来了
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROC
....... (2015-08-20 09:21)
另外请教你一个问题,用过线程局部变量(TLS  Thread Local Storage)没有,FreeRTOS里面新增了一个功能,网上查了些资料都是基于window的TLS介绍,读起来稍有些吃力。uCOS-II和III里面也有这个机制,只是没有给出代码。
回复

使用道具 举报

5

主题

578

回帖

593

积分

版主

Rank: 7Rank: 7Rank: 7

积分
593
发表于 2015-8-21 08:23:11 | 显示全部楼层

回 eric2013 的帖子

eric2013:另外请教你一个问题,用过线程局部变量(TLS  Thread Local Storage)没有,FreeRTOS里面新增了一个功能,网上查了些资料都是基于window的TLS介绍,读起来稍有些吃力。uCOS-II和III里面也有这个机制,只是没有给出代码。
 (2015-08-20 09:29) 
没听说过这么高级的特征啊  我去学习学习
回复

使用道具 举报

62

主题

77

回帖

263

积分

高级会员

积分
263
发表于 2015-11-20 15:50:33 | 显示全部楼层
怎么没看到哪里发生优先级调度?
回复

使用道具 举报

62

主题

77

回帖

263

积分

高级会员

积分
263
发表于 2015-11-20 15:50:57 | 显示全部楼层
中断处理中怎么没看到哪里发生优先级调度?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2015-11-20 17:51:29 | 显示全部楼层

回 freertos 的帖子

freertos:中断处理中怎么没看到哪里发生优先级调度? (2015-11-20 15:50) 
这个里面没有调度行为的。不过uCOS里面如何设置了OS_CFG_ISR_POST_DEFERRED_EN特性并且发生了中断,可以在重新打开中断时产生一次调度行为。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 16:11 , Processed in 0.198696 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表