SysTick的优先级是高还是低

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优先级高于任合外部中断的效果,此时延时会更少被其它中断干扰,会更加精准。

转载于:https://my.oschina.net/oceanstack/blog/371413

<think>好的,我现在需要帮助用户了解STM32的SysTick中断优先级默认值、设置方法以及相关的NVIC配置。首先,我得回忆一下SysTick在STM32中的位置和作用。SysTick是Cortex-M内核的一个系统定时器,属于NVIC的一部分,通常用于操作系统的时基或生成周期性中断。 根据引用[1],NVIC的中断优先级由4位寄存器决定,可以分成抢占优先级和响应优先级。用户可能想知道SysTick默认的优先级是多少,以及如何修改它。默认情况下,SysTick的中断优先级可能在芯片厂商的启动文件中已经设置好了,但需要确认具体数值。比如,某些STM32型号可能默认设置为最低优先级,但需要查证。 接下来,设置方法方面,通常通过NVIC的初始化函数来配置优先级。根据引用[1],提到的函数如NVIC_PriorityGroupConfig和NVIC_Init可能需要用到。不过SysTick可能还有特定的配置函数,比如SysTick_CLKSourceConfig,但优先级设置可能需要通过NVIC的相关函数。此外,引用[5]提到SysTick属于NVIC的一部分,所以其优先级设置应该遵循NVIC的分组规则。 用户的问题还提到默认值。根据引用[2],在UCOSIII移植中没有显式中断分组,但优先级设置函数仍然有效。这可能意味着如果未显式设置分组,系统可能使用默认分组方式,比如分组0,即所有4位用于抢占优先级。此时SysTick的默认优先级数值可能为0或其他值,需要参考具体芯片手册或启动代码。 然后,我需要确认SysTick的中断号。SysTick的中断异常号为15,对应的是SysTick_Handler。优先级寄存器的位置需要根据分组方式来确定,例如分组2时,抢占占2位,响应占2位。如果默认分组未设置,可能使用复位后的默认分组,通常是分组0,但不同型号可能不同,可能需要查阅参考手册。 另外,引用[5]提到SysTick的工作原理,但未直接涉及优先级设置,不过说明SysTick是内核的一部分,因此其优先级设置应通过NVIC进行。设置步骤可能包括:中断分组确定抢占和响应位数,然后使用NVIC_Init或直接写寄存器设置优先级。 可能的误区是SysTick是否属于外部中断,但根据引用[4],外部中断由EXTI管理,而SysTick属于内核中断,所以设置方式不同。SysTick优先级应通过内核NVIC相关寄存器配置。 最后,需要总结默认值的可能情况,比如STM32CubeMX生成的代码可能默认设置SysTick优先级最低,或者中等,但需要具体例子。同时,设置方法包括使用HAL库函数或直接操作寄存器,如NVIC_SetPriority(SysTick_IRQn, priority)。 总结步骤:1. 确定中断分组;2. 根据分组计算优先级数值;3. 使用NVIC函数设置SysTick优先级。默认值可能根据启动文件或库的不同而有所差异,需要查看具体实现。</think>### STM32 SysTick中断优先级详解 #### 1. **SysTick中断优先级默认值** SysTick作为Cortex-M内核的系统定时器,其默认中断优先级由芯片厂商在启动代码中设定。通常情况下: - **默认优先级数值为最低**(例如分组0时优先级为15),但具体值需参考芯片数据手册或启动文件(如`startup_stm32fxxx.s`)[^1][^5]。 - 若未显式设置分组,STM32复位后默认使用分组0(4位全为抢占优先级,响应优先级无效),此时SysTick优先级范围为0~15[^1][^2]。 #### 2. **设置方法** 通过NVIC相关函数调整SysTick中断优先级: 1. **设置中断分组**(需在初始化前调用): ```c NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 示例:抢占2位,响应2位 ``` 2. **直接设置SysTick优先级**(数值需根据分组计算): ```c NVIC_SetPriority(SysTick_IRQn, 0x03); // 优先级数值需按分组规则拆分 ``` 或使用HAL库函数: ```c HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); // 抢占优先级=0,响应优先级=0 ``` #### 3. **数值计算规则** 优先级数值需根据分组方式编码为4位二进制,例如: - **分组1**(抢占1位,响应3位): 抢占优先级范围0~1,响应优先级0~7。 数值计算:`优先级数值 = (抢占优先级 << 3) | 响应优先级`[^1]。 #### 4. **验证方法** 通过调试查看寄存器: - **SysTick优先级寄存器地址**:`0xE000ED20`(SHPR3寄存器的第24~31位)。 - 写入值需左移24位对齐,例如优先级3对应`0xE000ED20 = 0x03 << 24`。 #### 5. **注意事项** - **中断嵌套**:若需SysTick支持嵌套,需确保其抢占优先级于其他中断。 - **系统影响**:随意修改SysTick优先级可能导致RTOS调度异常(如FreeRTOS依赖SysTick)[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值