Cortex-m0临界代码段

Cortex-m0 临界代码段保护

1. stm32中断

1.1 中断特殊功能寄存器PRIMASK

PRIMASK寄存器用于控制中断的使能和禁止,它只有一个位,即PRIMASK位。当PRIMASK位被设置为1时,所有中断都被禁止,包括NMIHardFault中断。当PRIMASK位被设置为0时,所有中断都被使能。

操作PRIMASK寄存器的方法是使用MSR指令,将1写入PRIMASK位即可禁止中断,将0写入PRIMASK位即可使能中断。要操作中断开关或PRIMASK可以使用以下指令:

//汇编关闭中断

MSR PRIMASK, #1

或使用

CPSID I

//汇编开启中断

MSR PRIMASK, #0

或使用

CPSIE I

1.2 通过开关中断使能寄存器实现临界代码保护

void critical_section(void)
{
    // 关闭中断
    __disable_irq(); //关闭中断 PRIMASK = 1
    {

        // 临界代码段
        // ...
    }
    // 开启中断
    __enable_irq(); //开启中断 PRIMASK = 0
}

这里示例简单的实现了临界代码段的保护,但实际程序在设计是会使用到嵌套中断的情况

1.3 使用中断状态变量保存中断变化(嵌套中断)

void critical_section(void)
{
    // 保存当前中断状态
    uint32_t primask1,primask2;

    primask1 = __get_PRIMASK(); //获取PRIMASK寄存器值
    __disable_irq(); //关闭中断 PRIMASK = 1
    {
        // 临界代码段1
        primask2 = __get_PRIMASK();
        {
            // 临界代码段2
        }
        //恢复中断(primask2接收的变量值为1)
        __set_PRIMASK(primask2);
    }
    // 恢复中断状态
    __set_PRIMASK(primask1); //恢复PRIMASK寄存器值
}

通过接收PRIMASK寄存器值来保存各个临界段的状态,确保每个代码段都会被执行

2 通过定时器来查看关闭中断的实际实现效果

可以通过这篇博文做为参考:STM32定时器中断

3.1 RT_thread临界段保护(基于cortex-m0)

在rt_thread中也是操作PRIMASK寄存器来实现

;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROC
    EXPORT  rt_hw_interrupt_disable
    MRS     r0, PRIMASK             //读取PRIMASK寄存器值到r0中
    CPSID   I                       //关闭中断响应
    BX      LR                      //程序跳转至LR寄存器 (PC)
    ENDP

;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable    PROC
    EXPORT  rt_hw_interrupt_enable
    MSR     PRIMASK, r0             //将r0中的值(level)写入PRIMASK寄存器
    BX      LR                      //程序跳转至LR寄存器
    ENDP

RT_thread代码示例

PRIMASK = 0; /* PRIMASK 初始值为 0,表示没有关中断 */ 
rt_base_t level1; 
rt_base_t level2;

/* 临界段代码 */
{
    /* 临界段 1 开始 */
    level1 = rt_hw_interrupt_disable(); /* 关中断,level1=0,PRIMASK=1 */ 
    {
        /* 临界段 2 */
        level2 = rt_hw_interrupt_disable(); /* 关中断,level2=1,PRIMASK=1 */ 
        {

        }
        rt_hw_interrupt_enable(level2); /* 开中断,level2=1,PRIMASK=1 */ 
    }
    /* 临界段 1 结束 */
    rt_hw_interrupt_enable(level1); /* 开中断,level1=0,PRIMASK=0 */ 
}

posted @ 2024-08-24 10:37  代代代码  阅读(101)  评论(0)    收藏  举报