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

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

3天内不再提示

为何修改BASEPRI寄存器无效?

茶话MCU 来源:茶话MCU 2023-04-26 09:16 次阅读

STM32用户发现在操作BASEPRI特殊功能寄存器时,根本不起作用。比方,它目前配置了几个中断,优先级各不相同,按照STM32CubeMx里的配置分别为2、3、4不等,当他在BASEPRI寄存器里写这几个数字中的任意一个时,发现BASEPRI的数字始终是0,没有任何效果。

我们知道,通过配置 BASEPRI寄存器非0值来给系统中的中断响应设置门槛,当中断优先级低于某个级别时将不会得到CPU的响应执行,也就是说只有中断优先级高于某个级别时才能得到响应。下面截图是来自ARM CORTEX M4技术手册中有关BASEPRI寄存器的描述。

092c7a46-e3be-11ed-ab56-dac502259ad0.png

从这里可以看到该寄存器的有效配置位有8位,对其写0无意义,或者说放弃设置中断响应门槛功能。在ARMCORTEX-M内核系统里,中断优先级的高低跟表示优先级的数字大小成相反关系,即数字越小的中断优先级配置值所对应的优先级反而越高。

根据BASEPRI寄存器的定义,假设给BASEPRI写数字5,那就意味着只有中断优先级高于5的中断,即中断优先级的数字小于5的中断可以得到响应,而其它低于优先级5的中断将会被屏蔽。【注:这里说的优先级比较最终都体现在抢占优先级上】

另外,在ARM内核里关于每个中断的优先级配置寄存器也是8位,并支持字节访问。

0946b690-e3be-11ed-ab56-dac502259ad0.png

内核里还有跟中断优先级有关的寄存器,它把中断优先级配置位分成2部分,用来分别设置每个中断的组优先级和子优先级,或称抢占优先级和响应优先级,也有称主优先级和子优先级的,意思都一样。个人喜欢中间的术语。

0959b66e-e3be-11ed-ab56-dac502259ad0.png

以上图优先级分组值【PRIGROUP】等于3为例。中断优先级寄存器中的bit0~bit3用作配置该中断的响应优先级,显然,它的值可以是0到15的任一值。bit4~bit7用来配置该中断的强占优先级,同样它的值也可以是0到15的任一值。若以【PRIGROUP】等于7为例,则所有可配置优先级的中断只配置响应优先级,不区分强占优先级,或者说抢占优先级都一样,或者说彼此不发生中断抢占都一个意思。所谓中断抢占即指另一中断事件打断正在执行的中断服务程序而响应更高优先级的程序。

上面都基于ARM Cortex-M内核的最初设计来说的,我们知道,STM32是基于ARM内核添加ST的外设而成,ST在设计芯片的中断优先级这个地方,在AMR核的设计基础上做了些针对性的调整,涉及中断优先级的寄存器的有效控制位由8位变成4位,且仅使用高4位,低4位变成保留位。【下图来自STM32Cortex M4 编程手册。注意红色下划线特别说明。】

097052a2-e3be-11ed-ab56-dac502259ad0.png

不难理解,BASEPRI寄存器也会跟着做了调整,不然没法跟上面调整过的中断优先级寄存器匹配,它也只使用高4位,低4位变保留位。【下图来自STM32F4系列编程手册】

098db784-e3be-11ed-ab56-dac502259ad0.png

当然,关于优先级分组的控制寄存器的内容也做了相应调整,即针对优先级寄存器的高4位来划分抢占优先级和响应优先级的配置。详见下图:

09a0a4fc-e3be-11ed-ab56-dac502259ad0.png

把上图的各种优先级分组配置变得更直观点就是下图的样子。绿色用于配置抢占优先级,黄色用于配置响应优先级,灰色保留位,一共有5种可能的分组情形。

09b7d636-e3be-11ed-ab56-dac502259ad0.png

聊到这里,我们得知每个可配置的STM32片内中断,都有一个8位优先级配置寄存器与之对应,且只用到高4位。我们接着看看开篇的问题。目前STM32的有关中断配置如下图所示【使用STM32CubeMx工具进行】:

09ce2008-e3be-11ed-ab56-dac502259ad0.png

这里优先级分组选择的是将优先级的4位控制位全部用作抢占优先级的配置,响应优先级都一样,即不做特别配置。那么上图中SYSTICK/TIM2/TIM3/TIM4的中断的抢占优先级数据0、2、3、4其实是站在中断优先级寄存器的高4位而言的,那么放到整个8位优先级寄存器来看的话,他们的优先级应该是0x00,0x20,0x30,0x40【其实,低4位值是多少无关紧要,反正无效位】。

前面提过了,现在BASEPRI寄存器也只用到高4位,低4位保留。显然,如果在给BASEPRI寄存器赋值时按照基于高4位得到数字往里面写的话肯定都是无效的。

比方,我们期望在主程序里将上面TIM2/TIM3/TIM4的几个中断都屏蔽掉,若代码像下面截图里这样写肯定达不到目的。我这里开启了TIM2/TIM3/TIM4的周期性更新中断。【本文代码编译、调试基于ARM MDK IDE】

09eb1122-e3be-11ed-ab56-dac502259ad0.png

09f8265a-e3be-11ed-ab56-dac502259ad0.png

经过测试也的确没有达到目的。我写__set_BASEPRI(2)的本意是想屏蔽掉那几个定时器的中断响应,结果发现根本没作用。BASEPRI寄存器也没正确写入,因为数据2只能写到BASEPRI寄存器的低4位,这几位恰好是无效位。不难理解,当我们改写成__set_BASEPRI(0x20)时就可以达到目的了。

0a0b9f0a-e3be-11ed-ab56-dac502259ad0.png

此时,BASEPRI被正确写入,TIM2/TIM3/TIM4的中断不能得到响应,倒是SYSTICK中断可以不被影响地得到响应,因为它的优先级是0,BASEPRI的配置屏蔽不了它。也就是说,通过配置BASEPRI寄存器来设置中断响应门槛的话,是阻止不了优先级为0或更高优先级的中断的响应的。如果对BASEPRI写0表示放弃其设置的中断门槛的功能。

如果希望对包括0优先级在内的所有可配置中断进行关闭或屏蔽,能否做得到呢?若可以,如何操作?

STM32芯片里的中断如果按中断源是来自ST外设还是ARM核处理器可以分为异常和中断,比方下图中灰色部分的就是异常,其它为中断。【截图来自STM32G4系列参考手册】

0a311596-e3be-11ed-ab56-dac502259ad0.png

平常我们统称二者为中断,不做区分。如果说把所有中断按其优先级是否可以配置,又可以将中断分为优先级固定和优先级可配置的中断。其中,优先级固定的中断在上面表格中都明确标示了fixed字样,优先级可配置的都加注了settable字样。结合前面提到的优先级寄存器的特性,可配置的优先级是不会高于0级,即配置的数字不会小于0的。

若我们期望对所有可配置中断进行关闭或屏蔽,可以操作另一个叫PRIMASK的寄存器,它只有1位有效控制位。

0a6a42a8-e3be-11ed-ab56-dac502259ad0.png

我们通过对PARMASK写1,令CPU对所有优先级可配置的中断不做响应;若对其写0表示放弃屏蔽功能。比方,我们还是接着前面的演示代码来看看效果。

0a75ef90-e3be-11ed-ab56-dac502259ad0.png

这时,前面提到的4个定时器中断都不能得到响应了,虽打了断点但过不去。我们还可以借助调试工具看到这几个中断的响应情况【SYSTICK位置离得远,单独截取后插进图中的】。

0a953f1c-e3be-11ed-ab56-dac502259ad0.png

对于上图的部分信息我这里稍微解释下。

图形上方的字母E、P、A是下方Eable/Pending/Active单词的首字母。Enable表示相应中断是否在NVIC端得到响应允许;Pending表示中断等待CPU的执行;Active表示中断服务程序正在被执行。从图中可以看出,SYSTICK/TIM2/TIM3/TIM4的中断响应都虽得到允许,但都处于Pending期待执行状态。既然没有得到执行,Active位自然也是0。

上图中优先级的数字显然是按照高4位结合优先级分组后来看的,那个S表示SubPriority的意思。为了看得更清晰点,我不妨将优先级分组采用下面的做法重新配置下,保持原抢占优先级都不动,增加1位响应优先级【即子优先级】配置。目前4位优先级配置位拆分为3位抢占优先级配置位和1位响应优先级配置位。当前测试代码也保持不动。

0abc04da-e3be-11ed-ab56-dac502259ad0.png

显然,上图中的抢占优先级编号2、3、4是站在分组后的高3位单独来看的,响应优先级是站在分组后剩下的1位单独来看的。如果我们把两类优先级的配置在高4位一起看,优先级数字应该分别是十进制数1、5、6、9。【这个地方要弄清楚,否则下面调试结果看不明白。】

0ae0c8ce-e3be-11ed-ab56-dac502259ad0.png

基于前面测试代码和现有配置,我们看看运行后的中断响应情况。

0aef7446-e3be-11ed-ab56-dac502259ad0.png

刚才虽然调整了优先级的分组配置,但这几个中断的抢占优先级都没改变,所以在PRIMASK为1的情况下都不能得到响应。我们可以发现这几个中断的优先级站在高4位的角度来看而得出的优先级数字跟我上面分析的基本一致,除了SYSTICK的。

按理此时此处SYSTICK的优先级应该是1而不是0。为什么会这样呢?原因就在于我基于CubeMx组织的代码,这个过程中如果使用SYSTICK做库代码的TICK时钟,其中断优先级的配置使用默认配置,没有理睬CubeMx这边针对它子优先级的配置。Cube库在配置SYSTICK优先级时,默认使用全部4位用作抢占优先级的配置,同时将子优先级配置为0。当然,我们可以针对性地调整来适应我们的需求。主要是下面这个weak特性的初始函数,我们可以手动修改这个函数里关于中断优先级的配置。

0b119670-e3be-11ed-ab56-dac502259ad0.png

关于使用PRIMASK屏蔽所有可配置中断的做法还有其它等效动作,比如使用CPSID指令和CPSIE指令或调用相关CMSIS函数。【参见下图】

0b255f20-e3be-11ed-ab56-dac502259ad0.png

它们的作用一样,也就是我们平常所说的开、关总中断,准确点说是屏蔽所有优先级可配置中断的响应或者放弃屏蔽功能。对于开、关总中断的说法,从实现屏蔽效果来看勉强可以说能关总中断。但整体上讲,个人觉得这个说法不太合适,还很容易给人带来误解,颇具误导性。其实,不论是操作PRIMASK还是BASEPRI寄存器,并没有对被屏蔽中断的原有参数和配置做任何改变。即那些暂时被屏蔽的中断的中断响应允许位、中断请求使能位、中断触发事件等都不会因为暂时的被屏蔽而发生改变。打个形象而不是特别贴切的比方。当你开着豪车愉快地跑在某条道上,听着歌哼着曲。突然前方有交警在对道路做临时管制,你和其它一干人车都被拦停下来。原因是有一行高级别的人物要保障优先通行。你等虽被拦停下来,既没人说你无证驾驶、也没人告知你无权走这条道,证照都在,行路权也有,就是此刻级别不够。一旦放行,你依然可以一如既往地行使。

我倒觉得ARM技术手册提到的优先级提升更好理解和接受些。即通过对BASEPRI、PRIMASK这些寄存器编程提升当前执行程序的优先级,使得低于当前优先级的中断暂时得不到响应。适当时候放弃优先级升级功能,恢复原状。

可能有人知道,还有个可以关闭或屏蔽优先级高至-1级的HardFault异常的控制寄存器,就是FAULTMASK,也是1位有效位,操作跟PRIMASK类似。有兴趣的话,可以自行进一步研究下。

审核编辑:汤梓红

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

    关注

    134

    文章

    8653

    浏览量

    361825
  • 寄存器
    +关注

    关注

    30

    文章

    5032

    浏览量

    117745
  • STM32
    +关注

    关注

    2240

    文章

    10674

    浏览量

    348790
  • 中断
    +关注

    关注

    5

    文章

    884

    浏览量

    41026
  • stm32cubemx
    +关注

    关注

    5

    文章

    260

    浏览量

    14448

原文标题:为何修改BASEPRI寄存器无效?

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

收藏 人收藏

    评论

    相关推荐

    解析CPU中的寄存器

    8位寄存器在16位寄存器中,而16位寄存器在32位寄存器中。
    发表于 09-19 10:10 2908次阅读

    怎么修改SPI寄存器

    大家好,我正在研究STM8AL3166并尝试修改SPI寄存器。我的简单代码如下:int main(){ SPI_CR1 | = 0b00100100; / *配置为主设备和500 kHz com速度
    发表于 06-27 08:23

    如何更新这两个不会导致无效PWM周期的寄存器

    PIC处理,即使是16位的品种,持有10位PWM“on”值在两个不同的寄存器。例如,在PIC24F08KL200上,这个值在寄存器中:例如,我想增加或减少PWM“on”时间。如何更新这两个不会导致
    发表于 09-12 08:10

    stm32寄存器问题请教 边界地址和寄存器总数为何不一致?

    32位寄存器,也就是40个byte,还是在列表GPIO寄存器映射的表中查看的地址信息也是40个byte怎么也没有 0x3FF个byte,求教这是为何,边界地址和寄存器总数
    发表于 09-26 01:11

    修改PRIMASK寄存器的值的方法

    除NMI和HardFalut外的所有异常和中断。修改PRIMASK寄存器的值的方法有两种汇编使用CPS指令修改PRIMASKCPSIEI;//清除PRIMASK(使能中断)CPSIDI;//设置PRIMASK(禁止中断)或者 通
    发表于 08-13 07:20

    寄存器与移位寄存器

    寄存器与移位寄存器 寄存器是用来寄存数码的逻辑部件,所以必须具备接收和寄存数码的功能。任何一种触发器都可以构成
    发表于 03-12 15:19 59次下载

    寄存器,寄存器是什么意思

    寄存器,寄存器是什么意思 寄存器定义  寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用
    发表于 03-08 14:26 2.1w次阅读

    数据寄存器,数据寄存器是什么意思

    数据寄存器,数据寄存器是什么意思 数据寄存器数据寄存器包括累加器AX、基址寄存器BX、计数寄存器
    发表于 03-08 14:38 1.2w次阅读

    32位寄存器,32位寄存器是什么意思

    32位寄存器,32位寄存器是什么意思  从X8086开始学了一年,第一个ASM的程序就是变32换16进制的程序,不过现在叫我从新开始写ASM程
    发表于 03-08 17:26 1.7w次阅读

    寄存器与移位寄存器

    寄存器与移位寄存器:介绍寄存器原理和移位寄存器的原理及实现。
    发表于 05-20 11:47 0次下载

    修改寄存器默认值的方法

    寄存器默认值,也叫复位值,是当reset或者set有效时寄存器输出的值。对于一个DFF来说,如下图,当reset为0时,Q输出0;当set为0时,Q输出为1(外部使用时保证reset与set不同时为0)。
    的头像 发表于 09-28 14:13 1051次阅读

    修改寄存器默认值的方法有哪些

    寄存器默认值,也叫复位值,是当reset或者set有效时寄存器输出的值。对于一个DFF来说,如下图,当reset为0时,Q输出0;当set为0时,Q输出为1(外部使用时保证reset与set不同时为0)。
    的头像 发表于 01-30 16:30 1760次阅读
    <b class='flag-5'>修改寄存器</b>默认值的方法有哪些

    操作BASEPRI特殊功能寄存器无效解决方法(上)

    有STM32用户发现在操作BASEPRI特殊功能寄存器时,根本不起作用。比方,它目前配置了几个中断,优先级各不相同,按照STM32CubeMx里的配置分别为2、3、4不等,当他在BASEPRI
    的头像 发表于 06-21 16:04 862次阅读
    操作<b class='flag-5'>BASEPRI</b>特殊功能<b class='flag-5'>寄存器</b>时<b class='flag-5'>无效</b>解决方法(上)

    操作BASEPRI特殊功能寄存器无效解决方法(下)

    站在中断优先级寄存器的高4位而言的,那么放到整个8位优先级寄存器来看的话,他们的优先级应该是0x00,0x20,0x30,0x40【其实,低4位值是多少无关紧要,反正无效位】。 前面提过了,现在
    的头像 发表于 06-21 16:08 562次阅读
    操作<b class='flag-5'>BASEPRI</b>特殊功能<b class='flag-5'>寄存器</b>时<b class='flag-5'>无效</b>解决方法(下)

    直接修改寄存器来输出内部时钟的方法

    电子发烧友网站提供《直接修改寄存器来输出内部时钟的方法.pdf》资料免费下载
    发表于 09-19 15:43 0次下载
    直接<b class='flag-5'>修改寄存器</b>来输出内部时钟的方法