0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

利用TIMER事件和栈帧体验中断响应

茶话MCU 来源:茶话MCU 2023-11-05 16:45 次阅读

目前STM32芯片都是基于各种ARM Cortex-M内核的芯片,支持可编程中断优先级。支持中断抢占的同时,还中断响应的晚到和咬尾机制。中断抢占不难理解,就是某中断在运行时产生了另外的更高优先级的中断事件,低优先级的中断服务程序被暂停而去执行优先级更高的中断服务程序【后面中断服务程序用ISR表示】。所谓晚到机制,就是中断响应还在压栈阶段但没有正式进入ISR时又来了更高优先级的中断请求,等压栈操作完成后,则立刻执行高优先级的ISR,此时高优先级中断省去压栈操作,它执行完后再返回执行刚才申请压栈的低优先级ISR。而咬尾机制则是指某ISR正在执行过程中产生了新的不高于当前中断优先级的中断事件,一直等到当前中断ISR执行完毕,在退栈之前立即响应处于等待执行的ISR,此时该中断也无须再做压栈。不难理解,不论晚到机制还是咬尾机制都是为了提高中断响应速度,提高芯片性能。

下面是三幅分别代表中断抢占、中断晚到、中断咬尾的示意图。【注:从时间上讲,虽然发生中断晚到、中断咬尾可以显著节省时间,但也不等于从中断申请到进入ISR完全不要时间,下面图中没有体现出来。】

651c51b4-7bb7-11ee-939d-92fbcf53809c.png

6527b1e4-7bb7-11ee-939d-92fbcf53809c.png

653cdd12-7bb7-11ee-939d-92fbcf53809c.png

对于这几个中断响应的概念,我们是否可以比较直观地感受下呢?

或许有人想过一些诸如时间记录、波形输出等方法来感受之。这里,我想从中断响应先后顺序加上栈帧内容变化来体会中断抢占、中断晚到和中断咬尾。

对于Cortex M系列芯片【这里暂时将M33除外,我不知这个地方加上Security是否有很大差异。印象中只是有两套而已】,发生中断需要压栈的话,压栈内容根据是否启用浮点存储来进行。

654a5fd2-7bb7-11ee-939d-92fbcf53809c.png

上图表述了两种压栈格式。这里我们只关注右边的压栈格式,后面试验不使用浮点存储。

我这里借助Cortex-M4内核的STM32G4芯片的TIM1/TIM2的更新中断来完成试验。二者建立主从同步启动关系,TIM1的抢占优先级高于TIM2的,均工作在单脉冲模式,即每次启动后都能且只能产生1次更新中断。通过给二者设置相应的溢出时间参数,来模拟实现上面的三种情形。我们从中关注栈帧和个别特定寄存器的内容。【注:本试验过程中仅开启了TIM1/TIM2更新事件中断,再无其它。】

654e30a8-7bb7-11ee-939d-92fbcf53809c.png

65664b98-7bb7-11ee-939d-92fbcf53809c.png

对于发生抢占情形,我们通过在代码里设置断点,一方面可以看到2个中断的响应先后,另一方面可以看到因抢占动作导致栈帧内容的变动。

对于晚到情形和晚到情形,同样也会通过在代码里设置断点查看中断执行先后顺序。

对于晚到情形,申请压栈的是低优先级中断事件,先得到执行的则是高优先级中断,同时会发现虽然响应了2次中断,却只看到1次压栈,两次ISR运行时维持同一栈内容。对于咬尾情形在栈帧内容变化上跟晚到情形类似,但实现机理不同,它申请压栈的是高优先级或同级中断事件,做咬尾操作的是低优先级或晚发生中断请求的同级中断。

先介绍两个跟中断返回有关的寄存器LR(R14)和EXC_RETURN。纠正下,EXC_RETURN不是寄存器,是微处理器动态生成的跟中断返回有关的一个值。这个值有点神秘,也很重要。神秘的就是这个值怎么产生的、放在哪里的,似乎在ARM相关手册找不到具体说明。另外,这个值本身很特别,大大区别于通用程序运行地址。如果程序里不启用浮点存储,它的值可能是下面三个。

65814524-7bb7-11ee-939d-92fbcf53809c.png

这里我们重点关注图中的前2个,后面试验过程中会见到这两个值。结合图中信息,如果该值等于0xfffffff1,ISR执行完毕后要返回Handle Mode和Main Stack,极大可能地发生了中断嵌套;如果该值等于0xfffffff9,ISR执行完毕后要返回Thread Mode和Main Stack,意味着当前中断是在线程中产生的,不用OS的话,即Main程序被打断。

它很重要,中断返回得仰仗它。没有它,中断返回可能就乱套了。

每当中断压栈申请完成后,这个EXC_RETURN值就被硬件根据中断发生时CPU运行状态、运行模式、所用栈帧模式给生成好了,并在开始运行ISR之前将该值主动赋给LR寄存器。硬件在ISR执行完毕即将退栈返回时又自动将LR的内容提供给PC寄存器。当PC寄存器发现这个特殊的值后会不会一脸懵逼,啥玩意?地址不像地址。我们可以把这个值理解成中断返回告知书,并非程序地址。EXC_RETURN值通过LR寄存器做中间人传达给PC,主要传达下面几个信息:

1、恭喜我们完美地处理了刚才的突发事件,要归队返回了;

2、我们清楚刚才处理事情时的状态和待遇,但更要清楚返回后的状态、模式,不得以刚才的模式或状态来套返回后的模式或状态,不能因出了趟差就不知回家后的姿态和责任;

3、记住上面提到的,具体返回路线会专人提供【即之前压栈的PC值经出栈提供】;

戏说下,知道大意即可,更多细节可以查看相关手册。退一步讲,个中细节我们旁人也真的难以知晓。

铺垫性的话题就聊到这里。下面具体看看针对中断抢占、中断晚到、中断咬尾的试验。

先看中断抢占的情形。下面截图是有关TIM1/TIM2时基参数的配置。

659e4368-7bb7-11ee-939d-92fbcf53809c.png

在前面提到的固定配置前提下,我将TIM2溢出周期比TIM1少21个脉冲【这个地方不是固定的,14~24应该都可以,具体自行验证】,二者同步启动。这样配置的目的就是确保TIM2一定是先进中断但又不至于它执行完毕了TIM1中断还没来,否则就没法看到抢占情形了。下图是TIM2首先进入中断时的情形:

65a6759c-7bb7-11ee-939d-92fbcf53809c.png

从上图可以看出,TIM2首先进入中断,栈帧有新内容放入。LR寄存器为0xfffffff9,表示当前中断ISR是从线程模式下发生的,这里就是main程序被打断了。

下图是TIM1中断抢占TIM2中断的情形。

65d0abfa-7bb7-11ee-939d-92fbcf53809c.png

从上图中,明显看到栈帧内容再次被添加了8个字的内容,内容变多。我们还可以从LR寄存器的内容看出,结尾是F1,说明当前中断是抢占了其它低优先级中断,即发生了中断嵌套,它执行完后返回的还是handle模式,这跟它抢占了TIM2 ISR相吻合。

下图是TIM1 ISR执行完毕CPU再回来执行刚才被打断的TIM2ISR情形。

65eaa8ca-7bb7-11ee-939d-92fbcf53809c.png

从上图可以看出,TIM1中断抢占TIM2中断并完成ISR后,在返回TIM2 ISR之前还做了出栈操作。在当前TIM2 ISR里可以看到栈帧恢复到TIM2中断刚被响应时的情形,内容变少了。同样,我们可以发现LR寄存器内容也恢复到刚被响应时的值。

显然,发生抢占时除了看到ISR执行的顺序外,明显地看到栈帧内容的变化。

接着看看中断晚到的情形。先看TIM1/TIM2基本时基配置。

65f02f0c-7bb7-11ee-939d-92fbcf53809c.png

这样配置的目的,就是让优先级低的TIM2提前一点点发生中断,让它在申请压栈完成附近发生TIM1中断,TIM2 ISR并不能立即执行反而是TIM1抢先【不是抢占】执行ISR,之后再来运行TIM2 ISR。整个过程,只发生1次压栈、出栈操作。TIM1中断事件虽然晚发生,由于其高优先级和卡着点发生而抢先执行其ISR。

开始运行程序后,TIM1 ISR首先得到响应。【参加图中备注说明】

6603cb5c-7bb7-11ee-939d-92fbcf53809c.png

下图是TIM2 ISR得到执行的情形:

6629440e-7bb7-11ee-939d-92fbcf53809c.png

TIM1中断执行完毕后,回头来继续执行TIM2 ISR时,栈帧内容无变化。两次中断得到执行,只看到1次压栈操作。执行顺序靠TIMER时间参数保证TIM2的中断事件先发生并由其申请压栈, TIM1事件虽晚到却因高优先级而被优先执行其ISR。

最后来看看中断咬尾的情形。TIM1/TIM2时基参数配置如下:

66493e26-7bb7-11ee-939d-92fbcf53809c.png

二者设置的时基参数一样,上面TIM1的溢出周期减个1不是必须的,这里主要是为了确保TIM1中断事件不要晚于TIM2的即可,因为TIM1优先级高。二者同时申请中断,自然先响应TIM1的。

下图是TIM1 中断首先得到响应的情形:

664e00f0-7bb7-11ee-939d-92fbcf53809c.png

下图是TIM1 ISR执行完后运行TIM2 ISR的情形:

66713a84-7bb7-11ee-939d-92fbcf53809c.png

TIM2 ISR基于TIM1申请压栈并完成ISR后接着执行,也省去了压栈过程,完成2次中断只见1次压栈。从栈帧内容结果上看,中断晚到和中断咬尾很类似。不过,中断晚到情形下,申请压栈的是低优先级的中断事件,而咬尾中断情形下,申请压栈的是高优先级或者是先申请压栈的同级中断事件。比方以现在讨论的中断咬尾情形为例,如果把TIM1/TIM2的抢占优先级设置一样,其它参数不变。这时玩咬尾动作的就是TIM1中断了,因为二者优先级一样,TIM2先产生溢出中断自然先响应它的,TIM1的中断则等它执行完ISR基于咬尾机制而得以执行。

不难看出,基于晚到机制和咬尾机制而得以执行中断的行为不属于中断抢占。顺便提醒下,如果通过上面方式体验中断响应的话,测试代码尽量简单,尤其中断服务程序,否则若栈帧里压入太多其它信息,观察分析起来可能就不太方便了。


好,今天的分享就聊到这里。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    455

    文章

    50714

    浏览量

    423147
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9084

    浏览量

    367387
  • STM32
    +关注

    关注

    2270

    文章

    10895

    浏览量

    355743
  • Cortex
    +关注

    关注

    2

    文章

    202

    浏览量

    46484
  • 中断响应
    +关注

    关注

    0

    文章

    11

    浏览量

    2957

原文标题:利用TIMER事件和栈帧体验中断响应

文章出处:【微信号:stmcu832,微信公众号:茶话MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C函数调用机制与原理详解

    当一个C函数被调用时,函数的参数如何传递、堆栈指针如何变化、是如何被建立以及如何被消除的,一直缺乏系统性的理解,因此决定花时间学习下函数调用时整个调用机制并总结成文,以便加深理解。本文将从汇编的角度讲解函数调用时,堆栈的变化,参数的传递方式、以及
    发表于 06-08 10:49 1290次阅读
    C函数调用机制与<b class='flag-5'>栈</b><b class='flag-5'>帧</b>原理详解

    如何利用IDLE中断去判断一数据是否结束了呢

    stm32串口空闲中断如何接受完整的不定长的一数据?如何利用IDLE中断去判断一数据是否结束了呢?
    发表于 12-09 06:03

    如何利用STM32F1的串口空闲中断实现不定长的数据断

    常见的数据方式有哪几种?如何利用STM32F1的串口空闲中断实现不定长的数据断呢?
    发表于 12-09 06:10

    利用STM32F1的串口空闲中断实现不定长的数据断

    常见的数据方式有两种,一种是通过固定的协议格式断,另外一个是通过两帧数据的时间断,下面介绍最后一种,利用STM32F1的串口空闲
    发表于 02-17 07:55

    用一个实例展示一下Linux内核的入和退过程

    1、Linux内核调试方法总结之    和指针可以说是C语言的精髓。
    发表于 11-04 15:47

    基于单片机的中断控制程序(蜂铃器_timer1)【C语言】

    基于单片机的中断控制程序(蜂铃器_timer1)【C语言】
    发表于 12-29 18:17 13次下载

    基于单片机的中断控制程序(timer0)【C语言版】

    基于单片机的中断控制程序(timer0)【C语言版】
    发表于 12-29 18:17 0次下载

    基于TIMER3发生捕获中断丢失问题分析与总结

    在一洗衣机MC项目中,客户选择使用STM32F030作为主控芯片。使用TIMER3(CH3)来捕获电机的HALL Sensor的中断,同时使用TIMER3(CH2)的OC功能,在OC match
    的头像 发表于 01-15 15:11 5962次阅读
    基于<b class='flag-5'>TIMER</b>3发生捕获<b class='flag-5'>中断</b>丢失问题分析与总结

    基于51单片机的串口中断发送数据

    很少看到有资料写如何以中断的方式发送一数据,如果以等待的发送 数据 ,对高速运行的 单片机 来说是很浪费时间的,下面就介绍一种使用中断方式发送数据
    的头像 发表于 06-03 09:23 1.1w次阅读

    如何利用利用TimerA及中断实现RTC

    D13x Demo - 利用Timer_A及中断实现RTC,观察LED灯的闪烁频率 // 描述:利用Timer_A及
    发表于 11-26 14:59 1635次阅读
    如何<b class='flag-5'>利用</b><b class='flag-5'>利用</b>TimerA及<b class='flag-5'>中断</b>实现RTC

    什么是单片机的中断响应时间

    中断响应时间:从外部中断请求有效(外部中断请求标志置1)到转向中断入口地址所需要的响应时间。每个
    发表于 12-19 15:57 1w次阅读
    什么是单片机的<b class='flag-5'>中断</b><b class='flag-5'>响应</b>时间

    MPSoC,XEN虚拟机运行裸核的2种中断响应延迟情况

    作者:hankf,Xilinx Employee 修改Xilinx的定时器裸核应用程序(baremetal, standalone)例子xttcps_intr_example.c,可以测量中断响应
    的头像 发表于 12-08 12:29 1252次阅读

    Keil MDK 5.33 运行华大官方示例无法进入 Timer0 中断

    Keil MDK 5.33 运行华大官方示例无法进入 Timer0 中断
    发表于 11-23 18:06 1次下载
    Keil MDK 5.33 运行华大官方示例无法进入 <b class='flag-5'>Timer</b>0 <b class='flag-5'>中断</b>

    微机原理——8086中断类型以及中断向量表、中断响应中断返回

    响应1、外部可屏蔽中断响应2、外部不可屏蔽中断响应3、内部中断
    发表于 11-24 16:51 16次下载
    微机原理——8086<b class='flag-5'>中断</b>类型以及<b class='flag-5'>中断</b>向量表、<b class='flag-5'>中断</b><b class='flag-5'>响应</b>、<b class='flag-5'>中断</b>返回

    什么是中断响应次序?什么是中断处理次序?

    什么是中断响应次序?什么是中断处理次序? 中断响应次序和中断处理次序是计算机系统中非常重要的概念
    的头像 发表于 10-24 11:49 2578次阅读