Freertos代码之临界函数

芯    片: STM32F427VITx    
指 令 集: ARMV7、Thumb2
编译环境: arm gcc

FreeRTOS有如下临界节管理的宏定义。

#define portSET_INTERRUPT_MASK_FROM_ISR()        ulPortRaiseBASEPRI()    // 设置中断标志位
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)    vPortSetBASEPRI(x)        // 清除中断标志位
#define portDISABLE_INTERRUPTS()                vPortRaiseBASEPRI()        // 禁止中断
#define portENABLE_INTERRUPTS()                    vPortSetBASEPRI(0)        // 允许中断
#define portENTER_CRITICAL()                    vPortEnterCritical()    // 进入临界
#define portEXIT_CRITICAL()                        vPortExitCritical()        // 退出临界

/*
 * 预备知识:
 */

特殊功能寄存器

    程序状态字寄存器组(PSRs)

    中断屏蔽寄存器组(PRIMASK, FAULTMASK, BASEPRI)

    控制寄存器(CONTROL)


    寄存器            功能

    xPSR            记录 ALU标志(0标志,进位标志,负数标志,溢出标志),执行状态,以及当前正服务的中断号

    PRIMASK            除能所有的中断,但不可屏蔽中断(NMI)无效

    FAULTMASK        除能所有的 fault,但NMI依然不受影响

    BASEPRI            除能所有优先级不高于某个具体数值的中断。

    CONTROL            定义特权状态,并且决定使用哪一个堆栈指针

指令

    MRS   <gp_reg>,    <special_reg>  ; 读特殊功能寄存器的值到通用寄存器

    MSR   <special_reg>,  <gp_reg>    ; 写通用寄存器的值到特殊功能寄存器

    DMB      数据存储器隔离。DMB 指令保证仅当所有在它前面的存储器访问操作都执行完毕后,才提交在它后面的存储器访问操作

    DSB      数据同步隔离。比 DMB 严格,仅当所有在它前面的存储器访问操作都执行完毕后,才执行在它后面的指令

    ISB   指令同步隔离。最严格,它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。


屏蔽寄存器组

    名字        功能描述

    PRIMASK        这是个只有单一比特的寄存器。在它被置 1 后,就关掉所有可屏蔽的异常,只剩下NMI和硬fault可以响应。
                它的缺省值是0,表示没有关中断。

    FAULTMASK    这是个只有1个位的寄存器。当它置1时,只有NMI才能响应,所有其它的异常,甚至是硬fault,也通通闭嘴。
                它的缺省值也是0,表示没有关异常。

    BASEPRI        这个寄存器最多有9位(由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设成某个值后,
                所有优先级号大于等于此值的中断都被关(优先级号越大,优先级越低)。但若被设成0,则不关闭任何中断,
                0也是缺省值。


各函数代码如下

/*
 * portable/gcc/arm_cm4f/portmacro.h
 */

#define configMAX_SYSCALL_INTERRUPT_PRIORITY     ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
                                                        ( 5 << ( 8 - 3)) = 0xA0

portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;

    __asm volatile
    (
        "    mrs %0, basepri        \n" \    ; 把 basepri 值读到ulOriginalBASEPRI.  mrs r0, basepri
        "    mov %1, %2            \n"    \    ; ulNewBASEPRI = 0xA0
        "    msr basepri, %1        \n" \    ; 把0xA0写入basepri
        "    isb                    \n" \
        "    dsb                    \n" \
        :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
    );

    /* This return will not be reached but is necessary to prevent compiler
    warnings. */
    return ulOriginalBASEPRI;
}

portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
    __asm volatile
    (
        "    msr basepri, %0    " :: "r" ( ulNewMaskValue ) : "memory"    ; 给 basepri 设定一个值
    );
}

portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;

    __asm volatile
    (
        "    mov %0, %1            \n"    \    ; ulNewBASEPRI = 0xA0
        "    msr basepri, %0        \n" \    ; basepri = 0xA0
        "    isb                    \n" \
        "    dsb                    \n" \
        :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
    );
}

/*
 * portable/gcc/arm_cm4f/port.c
 */

#define portNVIC_INT_CTRL_REG        ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )    // 中断控制及状态寄存器ICSR
#define portVECTACTIVE_MASK                    ( 0xFFUL )

void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();        // 关中断
    uxCriticalNesting++;            // 临界嵌套计数

    /* 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 )    // 仅当临界嵌套计数为1时才断言,以防止递归调用
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );    // 当前活动的ISR编号,0:无活动ISR    
    }
}

void vPortExitCritical( void )
{
    configASSERT( uxCriticalNesting );    // 临界嵌套计数不为0
    uxCriticalNesting--;
    if( uxCriticalNesting == 0 )
    {
        portENABLE_INTERRUPTS();     // 允许中断
    }
}


/*
 * 进一步封装
 */

#define taskENTER_CRITICAL()        portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()

#define taskEXIT_CRITICAL()            portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )

#define taskDISABLE_INTERRUPTS()    portDISABLE_INTERRUPTS()
#define taskENABLE_INTERRUPTS()        portENABLE_INTERRUPTS()

#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值