我正在使用 STM32F303 MCU,我注意到可以设置 SysTick 以导致异常,这似乎在各种用户指南中经常提到。这样,它将具有比常规中断更高的优先级。
另一方面,似乎也可以将 Systick 设置为 NVIC 中的中断。它有自己的中断请求号,似乎可以设置为挂起状态。因为 NVIC 中断具有可编程的优先级,我们也可以这样设置。
我不太确定这两种使用 SysTick 的方法有什么区别。
我正在使用 STM32F303 MCU,我注意到可以设置 SysTick 以导致异常,这似乎在各种用户指南中经常提到。这样,它将具有比常规中断更高的优先级。
另一方面,似乎也可以将 Systick 设置为 NVIC 中的中断。它有自己的中断请求号,似乎可以设置为挂起状态。因为 NVIC 中断具有可编程的优先级,我们也可以这样设置。
我不太确定这两种使用 SysTick 的方法有什么区别。
先来几个定义:
在 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 是由外设发出信号或由软件请求生成的异常。所有中断都与指令执行异步。在系统中