如何判断Cortex-M处理器正在执行中断函数?

cathy的头像
cathy 发布于:周四, 08/19/2021 - 14:02 ,关键词:

今天分享一点之前在调试代码过程中遇到的知识点:关于__get_CONTROL的用法,及xQueueSend和xQueueSendFromISR的区别;

1、问题来源

我之前在FreeRTOS系统上移植了部分别人写的代码,移植前仔细看了下源码,确认没问题后,编译,下载,运行,突然“死机了”······

于是,我又再次确认了移植的代码,没有发现Bug所在。此时,我开启了在线调试功能,发现程序死在了“vPortEnterCritical”函数中的断言语句里。如下:

“如何判断Cortex-M处理器正在执行中断函数?"

2、解决问题的过程

我解决问题还是按照常规思维,一步一步跟踪,很多问题其实都是类似道理,有规律可循。

1)查看configASSERT断言做了什么事?

跟踪代码:

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

其中,里面taskDISABLE_ INTERRUPTS();就是关中断的意思。紧跟着后面执行了for( ;; );

看到这里,我明白了一点,就是死在for( ;; );里面了。

2)进一步查找问题

我又开始了思考,为什么会执行到这里来呢? 为什么会执行:

portDISABLE_INTERRUPTS(); uxCriticalNesting++;   if( uxCriticalNesting == 1 )

这些语句呢?

这就是我们常说的“临界段”,这一点我学习RTOS的时候已经明白了,这一个函数肯定会被调用。于是,我把目标锁定了portNVIC_INT_CTRL_REG这个参数:

#define portNVIC_INT_CTRL_REG     ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )

0xe000ed04? 这个地址,相信之前了解过NVIC的都知道,就是Interrupt control state register.即中断控制状态寄存器。

3)确定问题点

从上面的分析,其实问题都已经浮现出来了。于是查看了【Cortex-M3权威指南】中相关的内容。(PS:这本手册真的能解决很多问题,翻译成中文,对大部分朋友来说是一件好事)

其实,有这个一个寄存器:控制寄存器(CONTROL),里面讲述的非常清楚:

“如何判断Cortex-M处理器正在执行中断函数?"

看上图,大概意思就是:在中断模式下,CONTROL[1]为0。于是,又把思路转向了core_cm3.c文件中的源码:

__ASM uint32_t __get_CONTROL(void)
{
  mrs r0, control
  bx lr
}

懂一点汇编的,相信在这里都已经明白,大概意思就是过去控制寄存器状态,这也是我开篇说的,让大家了解的__get_CONTROL。

4)在线调试,分析结论

上面分析出来控制寄存器CONTROL,那么我们需要验证是否符合我们预期的效果,通过在线调试,断电就可得出,如下面两图:

a.在非中断情况下的值0x02

“如何判断Cortex-M处理器正在执行中断函数?"

b.在中断情况下的值0x00

“如何判断Cortex-M处理器正在执行中断函数?"

至此,问题已经查明就是CONTROL。

3、get_CONTROL的应用

一般在RTOS实时操作系统中,常常使用队列来处理我们的数据,也就是常说的FIFO(先入先出)。

比如:我们在FreeRTOS系统中,要将UART发送、或者接收的数据加入队列:在中断里加入队列,在非中断里加入队列。这个时候,就需要使用get_CONTROL来判断当前是否处于中断函数里。

当然,类似的情况很多,像CAN、I2C、SPI等一样的道理。

举例,CAN总线发送数据加入队列:

“如何判断Cortex-M处理器正在执行中断函数?"

以上就是今天的内容,希望对你有所帮助。

来源:嵌入式专栏
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 356