文档章节

SysTick的优先级是高还是低

OceanStack
 OceanStack
发布于 2015/01/24 20:24
字数 1402
阅读 5752
收藏 13

SysTick系统嘀嗒定时器并非STM32独有的,它是Cortex内核的部分,CM3为它专门开出一个异常类型,并且在中断向量表中占有一席之地(异常号15)。这样它可以很方便的移植到不同厂商出CM3内核的芯片上,尤其对于有实时操作系统的软件,它一般会作为整个系统的时基,所以这个对操作系统非常重要。

但在STM32开发手册中对它的介绍却很少,几乎到一笔带过的程度。有关SysTick的详细介绍可参考《Cortex-M3权威指南》第133 页第八章及第179页第十三章。

刚接触SysTick时,因它属于内核中断优先级,我一直有个疑问,它是比所有的可屏蔽中断优先级都高呢还是都低,或是处在等同设置地位 ?
最初我自以为内核中断优先级要比所有可屏蔽中断优先级高,当认真查阅资料与做实验后,发觉并非如此。

SysTick总共有四个寄存器:
1、

此寄存器在系统代码中由 SysTick->CTRL变量表示;

2、

此寄存器在系统代码中由 SysTick-> LOAD变量表示;

3、

此寄存器在系统代码中由 SysTick-> VAL变量表示;

4、

此寄存器在系统代码中由SysTick-> CALIB 变量表示,没有用过,也不常用,暂不作介绍。


这几个寄存器的偏移量如下图所示:


上面寄存器结构体的定义在 \CMSIS\CM3\CoreSupport  core_cm3.h中如下所示:

/
**@addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
  memory mapped structure for SysTick
  @{
  */
typedef struct
{
    __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
    __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
    __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
    __I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;

SysTick 是一个24 位的定时器,即一次最多可以计数 224个时钟脉冲,这个脉冲计数值被保存到SysTick->VAL 当前计数值寄存器中,它只能向下计数,每接收到一个时钟脉冲SysTick->VAL 的值就向下减 1,直至0,然后由硬件自动把重载寄存器SysTick->LOAD 中的值到SysTick->VAL重新计数,并且当SysTick->VAL值计数到0时,触发异常,调用void SysTick_Handler(void)函数,可以在此中断服务函数中处理定时中断事件了,一般是对设定值进行递减计数操作。只要不把它在SysTick控制及状态寄存器SysTick->CTRL中的第0位使能位清除,就永不停息。

它属于系统异常,是内核级中断,并且优先级是可以设置的,具体设置也是在  core_cm3.h中代码如下:

/**
 * @brief Initialize and start the SysTick counter and its interrupt.
 *
 * @param ticks number of ticks between two interrupts
 * @return 1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
    if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
    SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
    SysTick->VAL = 0; 
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 
        SysTick_CTRL_TICKINT_Msk | 
        SysTick_CTRL_ENABLE_Msk; 
    return (0); /* Function successful */
}

在此段代码中,优先级的设置是通过NVIC_SetPriority()函数实现,此函数对内核中断优先级和外部中断优先级设置都可以,比较强大,但需要手动算出来抢占和从优先级,不太方便,当跳进此函数,我们可以算出Systick默认优先是最低的(效果相当于SCB->SHP[11] = 0xF0,如果你推算下,SHP[11] 正好对应于Systick优先级的设置);对于可屏蔽中断,优先级的设置一般通过 NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)函数来实现,具体应用可参考下面的示例代码。

当介绍完了理论后,发现还是没有搞清楚最初的疑惑!现在就做实现来揭示真相。

先设置一事件中断,把优先级设置高一些,

void Exti_Config(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


注:中断分组我在实验中,最初初始化设置为如下:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

设为第二组。

在系统滴答中断里触发外部中断事件,并点亮LED1 :

void SysTick_Handler(void)
{ 
    EXTI_GenerateSWInterrupt(EXTI_SWIER_SWIER1); 
    LED_1 = ON;
    Delay();
}

外部中断处理函数中点亮LED0,如下:

void EXTI1_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line1) != RESET) 
    {
        EXTI_ClearITPendingBit(EXTI_Line1); 
        LED_0 = ON;
        Delay();
    }
}

当外部中断优先级比较高时,它可以抢占Systick中断先执行,以上代码实验结果为,LED0先点亮后,再回到LED1再点亮。

但当把外部中断设置为与systick相同的优先级时,则systick优先级就会相对较高,例如把上面的优先级改为:

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

则会LED1先亮,执行完SysTick_Handle函数后才轮到EXTI1_IRQHandler执行。

由以上实验可得出,当优先级相同时,内核级中断要优先于外部可屏蔽中断执行,但设置外部可屏蔽中断优先级大于内核级中断时,它是可抢占内核中断的。

另外,个人认为,若要实现systick精确延时,最好把systick优先级设置高一些,如 NVIC_SetPriority (SysTick_IRQn, 0);
即把SCB->SHP[11] = 0x00;则可达到systick优先级高于任合外部中断的效果,此时延时会更少被其它中断干扰,会更加精准。

© 著作权归作者所有

下一篇: 物联网概要
OceanStack
粉丝 29
博文 21
码字总数 19858
作品 0
武汉
程序员
私信 提问
Cortex-M0/M0+屏蔽优先级低于BASEPRI设定的中断

Cortex-M3/M4/M7有BASEPRI特殊功能寄存器可以屏蔽优先级低于BASEPRI设定值的中断,但Cortex-M0/M0+没有BASEPRI寄存器,不过仍然可以实现相识的功能。 mingdu.zheng at gmail dot com http:/...

zoomdy
2018/02/12
0
0
STM32系统滴答_及不可不知的延时技巧 - (上)

我想每个单片机爱好者及工程开发设计人员都有过点灯的经历。流水灯是个好东西,尤其是在调试资源有限的环境中,有时会帮上大忙。 然在最初入门时,如何让这些小灯们按照我们的想法欢快地跑起...

小汉憨憨
2014/04/29
9.1K
0
STM32上使用freertos常见问题

STM32上使用freertos常见问题,来自STM32的官方文档,这里把部分摘录在这里。 怎样将 FreeRTOS 移植到不同的 Cortex-M 内核? 若需将 FreeRTOS 移植到正确的 Cortex-M 产品,您必须从正确的目...

u011559046
2018/05/05
0
0
ARM 之 Cortex-M 内核中断/异常系统详解

版权声明:进步始于交流,收获源于分享!转载请保留原文出处,谢谢! https://blog.csdn.net/ZCShouCSDN/article/details/85029696 问题 最近在使用STM32F3芯片的时候,遇到这样一个问题:如...

ZCShouCSDN
2018/12/16
0
0
【转】浅析STM32中SysTick在3.5固件库中的应用

最近一直在忙STM32的学习,在学习中遇到了不少问题,也经过各种尝试解决问题,在这里我通过博文的形式写出来,也希望能够帮到遇见同样问题的人们。对于STM32系列的芯片,有一个好处就是官方给...

jerry2012cn
2013/06/23
2.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

Dubbo-自适应拓展机制

背景 在 Dubbo 中,很多拓展都是通过 SPI 机制进行加载的,比如 Protocol、Cluster、LoadBalance 等,这些都是Dubbo的基础组件。这些基础组件的拓展不是在系统框架启动阶段被加载,而是拓展方...

rock-man
10分钟前
2
0
Kali安装fcitx输入法(五笔)

安装fcitx > sudo apt-get install fcitx-rime fcitx-config-gtk3 重启 > sudo reboot fcitx配置 效果就是这样 配置输入法切换 系统设置...

yeahlife
12分钟前
2
0
IE之css3效果兼容

本文转载于:专业的前端网站▷IE之css3效果兼容 一、兼容css阴影效果(ie滤镜) 1.Shadow,阴影 .shadow { -moz-box-shadow: 3px 3px 4px #000; -webkit-box-shadow: 3px 3px 4px #000; box-sha...

前端老手
15分钟前
2
0
NiushopB2C开源商城功能列表说明:

B2C单商户免费版:PC商城+微商城 B2C单商户标准版:PC商城+微商城组合套餐+阶梯优惠核销功能 B2C单商户企业版:PC商城+微商城拼团+组合套餐阶梯优惠+核销功能 B2C单商户分销版:PC商城+微商城...

niushop-芳
17分钟前
2
0
图片如何转GIF图片呢

如何将生活中拍摄的好玩有趣的图片制作成GIF动图呢?相信很多小伙伴都不知道要如何制作,其实制作方法非常的简单,下面分享一个图片转GIF动图的方法,希望这个方法能够帮助大家在与好友斗图时...

白米稀饭2019
24分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部