rtthread开关中断

rtthread开关中断,第1张

1 rtthread开关中断函数(cortex-m)
/*
 * rt_base_t rt_hw_interrupt_disable();
 */
.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
    MRS     r0, PRIMASK
    CPSID   I
    BX      LR

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
    MSR     PRIMASK, r0
    BX      LR
2 中断嵌套

我能看到rtthread中很多地方都会使用,开关中断。但是开关中断是否支持嵌套呢?

int global1;
int global2;
void foo(void)
{
	rt_base_t level = rt_hw_interrupt_disable();
	global1++;
	rt_hw_interrupt_enable(level); //在这个地方开中断,调用后中断一定打开吗?
}

void bar(void)
{
	rt_base_t level = rt_hw_interrupt_disable();
	foo(); //执行后中断会被打开吗?
	global2++; //这段代码安全吗?
	rt_hw_interrupt_enable(level);
}
2.1 rt_hw_interrupt_disable
rt_hw_interrupt_disable:
    MRS     r0, PRIMASK  ;保存PRIMASK到r0中
    CPSID   I            ;关闭中断
    BX      LR           ;返回调用

rt_hw_interrupt_disable()是通过汇编语言实现的。首先将PRIMASK值保存到r0中,然后是关闭中断。最后执行调用返回。根据ARM的调用规范,函数返回后,返回值保存在r0寄存器中。所以rt_hw_interrupt_disable()的返回值就是当前函数调用前的PRIMASK值。那么PRIMASK值跟什么有关系呢?下面是Arm®v7-M Architecture Reference Manual的描述:

也就是说PRIMASK代表着可屏蔽中断的状态。如果是1代表当前中断禁止,如果是0代表当前中断使能。由此可以看出,rt_hw_interrupt_disable()的返回值代表当前的函数调用前的中断状态。之后调用CPSID I来关闭中断,所以rt_hw_interrupt_disable()调用后当前中断一定是关闭的,同时PRIMASK的值也一定是1。接下来继续分析rt_hw_interrupt_enable()函数。

2.2 rt_hw_interrupt_enable
//void rt_hw_interrupt_enable(rt_base_t level);
rt_hw_interrupt_enable:
    MSR     PRIMASK, r0  ;将level的值保存到PRIMASK寄存器
    BX      LR           ;调用返回

根据ARM调用规范, 函数的第一个参数由r0寄存器传递,所以r0中保存的是level的值,rt_hw_interrupt_enable()的功能就是将level值写入到PRIMASK寄存器中。所以rt_hw_interrupt_enable()执行后,开不开中断取决于level的值,开关中断是成对使用的,因为levelrt_hw_interrupt_disable()的返回值。所以这样就实现了中断的嵌套。继续阅读下面示例,来理解嵌套。

3 示例 3.1 test()调用前中断状态是使能的情况
int global_level1;
int global_level2;
int global_level3;

void test(void)
{
	rt_base_t level1 = rt_hw_interrupt_disable(); //此函数执行前中断为使能,所以level1 = 0
	rt_base_t level2 = rt_hw_interrupt_disable(); //此函数执行前中断已经被关闭了,所以level2 = 1
	rt_base_t level3 = rt_hw_interrupt_disable(); //此函数执行前中断已经被关闭了,所以level3 = 1
	global_level3++;
	rt_hw_interrupt_enable(level3);//把level3赋值给PRIMASK后,PRIMASK=1,中断仍然关闭
	
	global_level2++;
	rt_hw_interrupt_enable(level2);//把level2赋值给PRIMASK后,PRIMASK=1,中断仍然关闭
	
	global_level1++;
	rt_hw_interrupt_enable(level1);//把level1赋值给PRIMASK后,PRIMASK=0,中断打开
}
3.2 test()调用前中断状态是关闭的情况
int global_level1;
int global_level2;
int global_level3;

void test(void)
{
	rt_base_t level1 = rt_hw_interrupt_disable(); //此函数执行前中断已经被关闭了,所以level1 = 1
	rt_base_t level2 = rt_hw_interrupt_disable(); //此函数执行前中断已经被关闭了,所以level2 = 1
	rt_base_t level3 = rt_hw_interrupt_disable(); //此函数执行前中断已经被关闭了,所以level3 = 1
	global_level3++;
	rt_hw_interrupt_enable(level3);//把level3赋值给PRIMASK后,PRIMASK=1,中断仍然关闭
	
	global_level2++;
	rt_hw_interrupt_enable(level2);//把level2赋值给PRIMASK后,PRIMASK=1,中断仍然关闭
	
	global_level1++;
	rt_hw_interrupt_enable(level1);//把level1赋值给PRIMASK后,PRIMASK=1,中断仍然关闭
}

以上就把rtthread中断嵌套分析清楚了。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/757669.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-01
下一篇 2022-05-01

发表评论

登录后才能评论

评论列表(0条)

保存