在 NVIC 中设置 SysTick 中断和将其用作异常有什么区别?

电器工程 stm32 中断 基尔 皮质-m4
2022-01-12 02:00:05

我正在使用 STM32F303 MCU,我注意到可以设置 SysTick 以导致异常,这似乎在各种用户指南中经常提到。这样,它将具有比常规中断更高的优先级。

另一方面,似乎也可以将 Systick 设置为 NVIC 中的中断。它有自己的中断请求号,似乎可以设置为挂起状态。因为 NVIC 中断具有可编程的优先级,我们也可以这样设置。

我不太确定这两种使用 SysTick 的方法有什么区别。

2个回答

先来几个定义:

在 Cortex-M 编程手册中,异常是任何破坏正常程序流程的事物,并从向量表中调用处理程序,而中断是异常的子集,来自 ARM 内核之外的外围设备。因为 SysTick 是在 Cortex-M 内核中实现的,所以它被认为是一个异常,而不是一个中断。

异常有一个Exception Number,从 0 开始。中断有一个IRQ Number,从 0 开始。因为所有的中断都是异常,所以它们都得到一个 Exception Number,比 IRQ Number 高 16。不是中断的异常(包括 SysTick)的异常编号在 0-15 范围内,小于中断的异常编号。有点令人困惑的是,不是中断的异常也有 IRQ 编号,通过扩展落在 -16 到 -1 的范围内。SysTick 有异常号 15 和 IRQ 号 -1。

我正在使用 STM32F303 MCU,我注意到可以设置 SysTick 以导致异常,这似乎在各种用户指南中经常提到。这样,它将具有比常规中断更高的优先级。

除 Reset、NMI 和 Hardfault 之外的所有异常都具有可配置的优先级。它只是针对中断和其他异常进行了不同的配置。将 CMSIS 实施视为一个明确的示例:

__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if ((int32_t)(IRQn) < 0)
  {
    SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
  else
  {
    NVIC->IP[((uint32_t)(int32_t)IRQn)]               = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
}

您可以直接调用NVIC_SetPriority或操作SCB->SHP以使 SysTick 的优先级低于任何其他中断。

SysTick 确实有一个高于任何中断的默认优先级,但这只是因为在复位时,所有优先级都设置为 0,并且在 tie 的情况下,较低的 IRQ 号获胜,在这种情况下,SysTick 为 -1。

另一方面,似乎也可以将 Systick 设置为 NVIC 中的中断。它有自己的中断请求号,似乎可以设置为挂起状态。因为 NVIC 中断具有可编程的优先级,我们也可以这样设置。

只有中断可以通过 NVIC 寄存器进行配置,而 SysTick 不是中断。NVIC 寄存器在位掩码或其他地方没有负 IRQ 号的位置。

SysTick 确实可以设置为挂起状态,但这是通过 完成的SCB->ICSR,而不是在 NVIC 中。

注意NVIC_SetPriority()NVIC_GetPriority()是 CMSIS 中唯一能正确处理负 IRQ 数的 NVIC_ 函数。其他函数喜欢NVIC_SetPendingIRQ()NVIC_EnableIRQ()只是愉快地接受负 IRQ 号,对它们进行一些洗牌,导致与 NVIC 寄存器的巨大偏移,并乱写一些遥远的内存地址,可能导致 hardfault或其他奇怪的行为。当您在标头中启用时,HAL_NVIC_ 函数会进行一些边界检查USE_FULL_ASSERT,否则它们只会让无效参数通过 CMSIS NVIC 函数。

编辑

有一个巧妙的技巧可以找到使用负参数调用函数的所有位置。将其放入一个通用标题中:

#define NVIC_EnableIRQ(x) ((void)sizeof(char[x]))

每当使用负数调用此构造时,都会出现编译时错误。对除 NVIC_SetPriority()和之外的每个 NVIC 函数重复此操作NVIC_GetPriority()

systick 和外设中断之间的根本区别在于,当 systick 在内核中可用时,ARM 将其指定为 IRQ 6 (0x003C)。
它也是 ARM Cortex 的一部分,由相同的时钟提供时钟,因此是同步的。

其他异常(中断)由制造商决定它们的基本优先级(偏移量)和来源。

来自 ST 编程手册 (PM0056):

SysTick 异常是系统计时器在达到零时生成的异常。软件还可以生成 SysTick 异常。在 OS 环境中,处理器可以将此异常用作系统滴答声。

中断或 IRQ 是由外设发出信号或由软件请求生成的异常。所有中断都与指令执行异步。在系统中