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

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

3天内不再提示

关于SYSTICK的COUNTFLAG标志的小疑惑

茶话MCU 来源:茶话MCU 2023-03-26 14:48 次阅读

前不久在研究SYSTICK有关问题阅读相关技术资料时,无意间产生了个小疑惑。

问题是这样的,我们知道SYSTICK定时器是个24位向下计数器,每当发生从1记到0时会让一个名为COUNTFLAG的标志位置1,如果此时SYSTICK的滴答中断请求使能了的话,可以对CPU发起中断请求。

543c497a-cba0-11ed-bfe3-dac502259ad0.png

根据我们平常STM32的开发经验,通常各种外设事件发起中断请求时,往往有相应的事件标志跟中断响应关联,在中断服务程序里并将相关事件标志做清零操作,否则它会没完没了地发起中断请求。基于这点,我想这个COUNTFLAG标志应该也是跟SYSTICK中断密切相关,溢出时被置位,在SYSTICK中断服务程序里将其清零。

可是,我们平常的SYSTICK的中断服务程序里根本没看到哪里有对COUNTFLAG标志做清零。ARM Cortex内核手册针对COUNTFLAG标志的描述中涉及它可以清零的地方有两处:

5470fa08-cba0-11ed-bfe3-dac502259ad0.png

第一个地方是在SYSTICK控制寄存器【SYST_CSR】里有介绍,读它可以清零。说实在的,这点我是通过咨询ARM公司才理解到位的。第二个地方是在介绍SYSTCIK的当前计数器寄存器时提到,即对当前计数器寄存器进行写操作时也会将COUNTFLAG标志清零。

问题是平常的SYSTICK的中断服务程序里根本就没有涉及到上面提到的可能对COUNTFLAG标志清零的操作啊?!既没有读SYSTICK控制寄存器,也没有对计数器做写操作。那这个标志啥时候被清零的呢?如果不清零的话,难道不会没完没了地申请中断,可现在的实践结果又不是这样的!

后来,找同事咨询、讨论,有同事说他印象中计数器重装时会将该标志清零。如果说重装可以清COUNTFLAG的话,这样可以很好地解释目前的结果。因为既然每次重装可以清零,自然用不着到中断服务程序里再做清零,那么在中断服务程序里见不到对COUNTFLAG的清零操作也就再正常不过了。也因此一时以为找到了答案。可后来一想,还是有些不对劲的地方。至少有2点说不通。

第一、如果是重装时清零,该标志是溢出时被置1的,而溢出和重装两个动作可以看成同一时刻完成,即置位后马上被清零。这样的话,用户永远没有机会见到该标志为1的时候。何时能被软件用得上呢?定义这个标志意义何在呢?

第二、关于这个标志,在ARM 内核手册里还说了下面一句话:

54890b5c-cba0-11ed-bfe3-dac502259ad0.png

意思就是说用户软件可以通过查看COUNTFLAG标志来确认SYSTICK之前有发生过溢出。如果重装可以清零的话,用户软件是不可能有机会读到该标志为1的时候。也就是说重装清零结论跟这句话是矛盾的。

经过与同事的来回讨论,以及查找其它相关信息,后来认为这个标志可能跟中断没有必然关系。这个过程中我也意识到我提出这个标志哪里清零的问题,可能是先入为主的惯性思维在作怪。具体点说,我们认为这个COUNTFLAG标志在发生溢出时置位没问题,前面提到的两种情形下会被清零也没问题。但是,SYSTICK的滴答中断不跟这个标志位关联,它只与计数器发生从1计到0的事件有关,即手册中下面绿色方框框住的这句话。

54b1a2a6-cba0-11ed-bfe3-dac502259ad0.png

说实在的,这句话我老早就看到了,只是觉得溢出做为中断触发条件没错,但一门心思老纠结着哪个地方对COUNTFLAG清零了。

如果说COUNTFLAG只是个溢出事件标志,滴答中断不跟它关联也是可以理解和接受的。首先,根据ARM手册描述来理解这个结论没有问题,没有说不通的地方,然后,实现逻辑上也没啥问题,反正溢出一次就申请一次中断。

聊到这里,很多STM32用户【包括本人在内】可能会觉得有点别扭或不习惯,这点我们下面继续聊。我就我们针对COUNTFLAG标志跟SYSTICK中断的关系的理解,说得直白点就是SYSTICK中断跟COUNTFLAG有无关系、服务程序里要不要清零再次找ARM公司做了确认,他们完全认同我们的理解。即COUNTFLAG只是个溢出事件标志,SYSTICK中断不跟它关联,只与计数器溢出事件本身关联,并不关心COUNTFLAG的值是0还是1。到此,关于COUNTFLAG要不要在服务程序里清零的疑惑算是尘埃落定。

但是------

用过STM32外设事件申请中断的人应该很清晰地知道,要想各个外设事件中断申请能得到响应的话,除了NVIC端接受响应、外设端允许申请中断外,还得有相应的事件发生【包括软件方式】以及对应的事件标志被置位【或者说应该有效】,中断服务程序跟相应事件标志直接相关,即发生中断响应时中断事件标志必须有效,并需在中断服务程序里对标志清零,否则会没完没了地申请中断、响应中断。显然,这个过程跟前面SYSTICK中断有点不一样。SYSTICK中断虽然设置了溢出事件标志,但其中断并没有跟该标志关联起来。事实上这样运行起来也没有任何问题,那么ST设计的外设申请中断怎么非要跟标志位关联在一起呢?我们平常做STM32开发时,有时因为疏忽或原理不够清晰,没及时清零中断请求标志让CPU没完没了地进中断而陷入异常。

why?

整体上,STM32微控制器是由ARM处理器和ST外设集成而来,ARM 处理器又包括内核、核外设【以示区别于ST公司设计的外设】。其中SYSTICK、FPU、MPU、NVIC等均属于核外设。也就是说,SYSTICK是ARM的外设,不是ST设计的。既然这样,难道只是设计思路上的差异?但是,SYSTICK中断可以不跟事件标志关联起来,可以行得通,为什么ST不也这样设计呢?

一起来看看,尝试找找原因。

原因在于SYSTICK外设就一个溢出事件可以申请中断,在NVIC那边独立对应一个中断请求号【IRQ#],所以CPU在响应SYSTICK中断时根本无需关注那个溢出标志,有那个溢出事件就够了,因为除了这个溢出事件没别的事件来申请TICK中断。

【下图是来自STM32G4参考手册里有关中断矢量表的部分截图】

54fdd7f2-cba0-11ed-bfe3-dac502259ad0.png

而ST的外设申请中断时就没有SYSTICK那么好的福分了。往往是一个外设的多个事件共用1个中断请求。比方以上面STM32G4系列ADC3的中断来看,因为它只有1个中断申请号,在CPU看来就一个中断入口,即所有ADC3相关事件触发的中断共用一个中断服务程序入口,但可以申请中断的事件可多了,见下图【我后面把能触发同一中断请求的事件称之为兄弟事件】:

55265970-cba0-11ed-bfe3-dac502259ad0.png

再以SPI3和LPTIM1的中断为例,它俩也各只有一个中断请求号,同样可以申请中断的事件也不少,分别见下面两幅图。

55387524-cba0-11ed-bfe3-dac502259ad0.png

554f0adc-cba0-11ed-bfe3-dac502259ad0.png

显然,ST设计的外设不能照搬SYSTICK的玩法。如果中断服务程序不跟触发事件标志关联起来,进了中断就不知该基于哪个事件来运行程序;基于某个事件运行了中断服务程序若不对它清零【包括读清零、写清零等】,等兄弟事件触发再进来时如何分得清哪是过时事件、哪是新触发的即时事件?

或许有人会说,为什么不给每个ST外设事件都安排一个中断请求号呢?这要考虑到必要性和中断请求号的有限性。不难理解必要性并不强,目前ST的设计其实没有啥不合理的地方。另外,内核开放的中断请求号数目是也有限的,视不同内核而定。

今天的话题就聊到这里,该问题属于好奇型的,即使不知道问题原因,一般也不会影响到我们平常的STM32开发。探究下也就是满足下好奇心,让内心偶尔掀起一阵涟漪,给生活增添一抹色彩。

审核编辑:汤梓红

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

    关注

    68

    文章

    10832

    浏览量

    211302
  • STM32
    +关注

    关注

    2266

    文章

    10880

    浏览量

    355085
  • 计数器
    +关注

    关注

    32

    文章

    2255

    浏览量

    94396
  • 中断
    +关注

    关注

    5

    文章

    895

    浏览量

    41419
  • Systick
    +关注

    关注

    0

    文章

    62

    浏览量

    13048

原文标题:关于SYSTICK的COUNTFLAG标志的小疑惑

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

收藏 人收藏

    评论

    相关推荐

    使用RTOS还能调用LL_mDelay延时函数吗?

    如题,未学习研究过RTOS,不太清楚调用滴答定时器的情况,是不是不能判断到SysTick_CTRL_COUNTFLAG_Msk标志? void LL_mDelay(uint32_t Delay
    发表于 03-14 07:08

    求助,关于systick_ctrl寄存器设置与COUNTFLAG标志位使用关系的疑问求解

    ,bit0位为011,也就是8分频,开中断,开始计数,那么我在主函数里面使用的采用判断标志COUNTFLAG=1写的那个while函数就进不去里面那个等于1这个判断函数,就是我图中的if函数,如果把ctrl寄存器设置成为0x01也就是8分频,不开中断,开始计数,那就能进
    发表于 04-29 06:00

    求助关于SysTick程序的疑惑求解

    关于SysTick 程序的疑惑
    发表于 05-16 08:04

    【STM32F411 Nucleo试用体验】+systick定时器

    (0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟) 第3位:COUNTFLAGSystick计数比较标志
    发表于 06-01 18:11

    Systick相关寄存器和库函数的疑惑

    当前值寄存器中CURRENT的描述:写它则使之清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志。那COUNTFALG是在被读取为1后自动清零还是在CURRENT被清零后
    发表于 08-28 10:53

    请问下面A处的SysTick->VAL =0x00; 是否可以不要?

    请教SysTick的几个问题。1.下面A处的SysTick->VAL =0x00;是否可以不要的?不是启动倒数后,VAL的值就变了的吗?至于写VAL时会清COUNTFLAG标志,但这个
    发表于 10-23 03:21

    配置SYSTICK

    SysTick_Handler中也无需对中断标志进行清零(参考exit外部中断服务函数)2.要注意的是关于systick其实有两个关键函数,SyST
    发表于 08-17 06:22

    SysTick计数器有哪些应用呢

    后, 每经过1个系统时钟周期,计数值就减1。计数到0时,SysTick计数器自动重装初值并继续计数,同时内部的 COUNTFLAG 标志会置位,触发中断(如果中断使能)。在 STM32 的应用中,使用 Cortex-M3 内核的
    发表于 12-07 09:37

    Systick寄存器的相关资料下载

    使能(是否启用)TICKINT用来设置当计时到0的时候是否要进入中断如果为0就RELOAD初值不断循环如果为1就进入中断当然,不中断也可以通过标志位来判断第16位的COUNTFLAG就相当于51中的标志位当数到0的时候,这一位会
    发表于 01-05 07:08

    SysTick寄存器介绍

    设置系统时钟SYSCLK 等于72M。当重装载数值寄存器的值递减到0 的时候,系统定时器就产生一次中断,以此循环往复。SysTick 寄存器介绍SysTick—系统定时器有4 个寄存器。1、CTRL SysTick 控制及状态寄
    发表于 01-21 11:37

    SysTick系统定时器相关资料下载

    的24次方。递减计数器在时钟的驱动下,从重装载寄存器的初值开始往下递减计数到0,到0后产生中断,同时置位COUNTFLAG标志位(在STK_CTRL寄存器),然后重装载寄存器重新开始递减计数,如此循环。STK_CTRL寄存器SysTic
    发表于 02-18 06:51

    使用RTOS还能调用LL_mDelay这个延时函数吗?

    如题,未学习研究过RTOS,不太清楚调用滴答定时器的情况,是不是不能判断到SysTick_CTRL_COUNTFLAG_Msk标志? void LL_mDelay(uint32_t Delay
    发表于 08-08 06:36

    STM32—关于SYSTICK系统时钟的详解及学习笔记

    SysTick_Handler中也无需对中断标志进行清零(参考exit外部中断服务函数)2.要注意的是关于systick其实有两个关键函数,SyST
    发表于 11-30 15:51 15次下载
    STM32—<b class='flag-5'>关于</b><b class='flag-5'>SYSTICK</b>系统时钟的详解及学习笔记

    SysTick——系统定时器

    的24次方。递减计数器在时钟的驱动下,从重装载寄存器的初值开始往下递减计数到0,到0后产生中断,同时置位COUNTFLAG标志位(在STK_CTRL寄存器),然后重装载寄存器重新开始递减计数,如此循环。STK_CTRL寄存器SysTic
    发表于 12-23 19:57 1次下载
    <b class='flag-5'>SysTick</b>——系统定时器

    一个有关SYSTICK好奇的问题

    前不久在研究SYSTICK有关问题阅读相关技术资料时,无意间产生了个小疑惑。 问题是这样的,我们知道SYSTICK定时器是个24位向下计数器,每当发生从1记到0时会让一个名为COUNTFLAG
    的头像 发表于 06-21 15:48 699次阅读