Toriyung

导航

中断控制寄存器的说明/临界区的进出

中断控制寄存器

  对中断的屏蔽与否,通过一下控制寄存器决定

 

  简单来说就是PRIMASK只留了个NMI(不可屏蔽异常,一般是系统出错)和硬件异常;FAULTMASK只留了个硬件异常;而BASEPRI可以选择性屏蔽

 

 

 

临界区

  其实就是中断的开关,而开关的中断就是通过对BASEPRI这个中断屏蔽寄存器赋值实现,当优先级低于其设置的中断都被屏蔽。在freertos中定义和实现如下

  无返回

    进临界区

    task.h文件中,宏定义为

#define taskENTER_CRITICAL() portENTER_CRITICAL()

    portmacro.h文件中,宏定义为

#define portENTER_CRITICAL()                vPortEnterCritical()

    port.c文件中,vPortEnterCritical函数的定义

void vPortEnterCritical(void)
{
    /* 进入临界区--不带中断保护 */
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;
    
    if(uxCriticalNesting == 1)
    {
        //configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0);
    }
}

    portmacro.h文件中,宏定义为

#define portDISABLE_INTERRUPTS()                             vPortRaiseBASEPRI()

    同文件中vPortRaiseBASEPRI函数的定义

static portFORCE_INLINE void vPortRaiseBASEPRI(void)
{
    /*无返回关中断*/
    uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; 
    
    __asm
    {
        msr basepri, ulNewBASEPRI    //直接将中断屏蔽值载入
        
        dsb
        isb
    }
}

    出临界区

    基本和进临界区一致,区别在于最后的内联函数,使用的是对BASEPRI寄存器赋值的函数,这里赋值为0即开启中断,后面有返回出临界区还会使用到

static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI)
{
    /* 设置中断寄存器,用来开启中断     */
    __asm
    {
        msr basepri, ulBASEPRI
    }
}  

  

  有返回

    进临界区

    task.h

#define taskENTER_CRITICAL_FROM_ISR()                    portSET_INTERRUPT_MASK_FROM_ISR()    

    portmacro.h

#define portSET_INTERRUPT_MASK_FROM_ISR()             ulPortRaiseBASEPRI()    

    同文件ulPortRaiseBASEPRI函数定义

static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI(void)
{
    /*有返回关中断*/
    uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
    
    __asm
    {
        mrs ulReturn, basepri      //先保存这一层嵌套中断的优先级
        
        msr basepri, ulNewBASEPRI    //新的优先级载入basepri
        
        dsb
        isb
        
    }
    return ulReturn;            //返回这一层的嵌套中断优先级
}

    

    出临界区

    因为是出某一层的临界区回到上一层的嵌套,所以要把上一层嵌套的basepri给回去,所以这里使用和无返回出临界区一样的函数,但传入的参数不再是0,而是上一层嵌套basepri

static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI)
{
    /* 设置中断寄存器,用来开启中断     */
    __asm
    {
        msr basepri, ulBASEPRI
    }
}

    

    

posted on 2022-11-16 21:48  Toriyung  阅读(377)  评论(0编辑  收藏  举报