我正在尝试在Linux的SW4STM32中使用 SysTick_Handler
,但每当触发SysTick中断时,执行都会跳转到系统内存中的某个位置 . 根据我的理解,它应该跳转到我声明或未通过的 void SysTick_Handler(void)
中,在startup_stm32中声明的 Default_Handler
中定义了中断向量表 . 我在 SysTick_Handler
中设置了一个断点,但它永远不会到达 . 在下面的代码中,如果我没有按预期包含 SysTick_CTRL_TICKINT_Msk
,它会通过 init_systick()
并保持在无尽的 for
循环中,但是当我确实包含它时,调试器会告诉我它最终会在地址0x1fffda7c附近 .
main.c中:
#include "stm32f0xx.h"
volatile uint32_t ticks = 0;
void SysTick_Handler(void) {
ticks++;
}
void init_systick(void) {
SysTick->LOAD = 43999;
SCB->SHP[1] |= 0x40000000L;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}
int main(void)
{
init_systick();
for(;;);
}
我在 .map
文件中验证了链接器正在使用声明的 SysTick_Handler
而不是 Default_Handler
.
我还尝试了以下变体来使用标准外设库进行设置,以及其他中断优先级值,结果相同:
#include "stm32f0xx.h"
volatile uint32_t ticks = 0;
void SysTick_Handler(void) {
ticks++;
}
void init_systick(void) {
SysTick_Config(44000);
NVIC_EnableIRQ(SysTick_IRQn);
NVIC_SetPriority(SysTick_IRQn, 0);
}
int main(void)
{
init_systick();
for(;;);
}
这不应该有定时晶体,我还修改了system_stm32f0xx.c中的 void SetSysClock(void)
以使用HSI时钟和PLL,它似乎正常工作:
static void SetSysClock(void)
{
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) ;
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
RCC->CR &= ~RCC_CR_PLLON;
while (RCC->CR & RCC_CR_PLLRDY) ;
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLMUL & ~RCC_CFGR_PLLSRC) | RCC_CFGR_PLLMUL11; // PLL takes 8 MHz HSI / 2 as input
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY)) ;
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) ;
}
-- EDIT: More info requested in the comments --
它是M0核心,因此它没有向量表重定位 . 参考手册第2.5节(第44页):
与Cortex®M3和M4不同,M0 CPU不支持向量表重定位 .
地址0x00000000应映射到0x08000000的FLASH存储器,0x1fffd800的系统存储器或0x20000000的SRAM . 地址0x00000000处的存储器与0x1fffd800处的系统存储器匹配,即使SYSCFG_CFGR1 MEM_MODE设置为00,也应将FLASH存储器映射到那里 . 地址0x08000000处的主FLASH存储器包含正确的向量表,但地址0x00000000填充了SysTick向量的地址0x1fffd99d(以及除复位向量之外的所有其他非NULL向量,即0x1fffdc41);调试器在地址0x00000000处显示的向量与观察到的行为一致 . 在执行中断之前,在地址0x08000298(FLASH存储器中已加载正确代码的正确位置)的断点处暂停时收集所有这些信息 .
1 回答
根据datasheet,该区域是系统内存(用于内置引导加载程序) . 你可以尝试两件事:
仔细检查BOOTx引脚,确保MCU加载FLASH而不是系统内存 .
确保已将SCB->VTOR分配给您自己的中断向量表的正确地址 .