我试图在Linux的SW4STM32中使用SysTick_Handler
,但是无论何时触发SysTick中断,执行都会跳转到系统内存中的某个位置。根据我的理解,它应该跳到我声明的void SysTick_Handler(void)
或失败的地方,进入定义中断向量表的startup_stm32.s中声明的Default_Handler
。我在SysTick_Handler
中设置了一个断点,但从未达到。在下面的代码中,如果我不按预期包含init_systick()
,它将通过for
并停留在无尽的SysTick_CTRL_TICKINT_Msk
循环中,但是当我包含它时,调试器会告诉我它结束于地址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,它们似乎正常工作: / p>
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) ;
}
-编辑:在注释中请求更多信息-
这是M0内核,因此没有向量表重定位。从参考手册第2.5节(第44页)中:
与Cortex®M3和M4不同,M0 CPU不支持向量表重定位。
地址0x00000000应该映射到0x08000000的FLASH存储器,0x1fffd800的系统存储器或0x20000000的SRAM。即使SYSCFG_CFGR1 MEM_MODE设置为00,地址0x00000000的内存也将与系统内存0x1fffd800的内存匹配,这会将内存映射到那里。地址为0x08000000的主FLASH存储器包含正确的向量表,但是SysTick向量(以及除复位向量为0x1fffdc41以外的所有其他非空向量)的地址0x00000000填充了地址0x1fffd99d。调试器在地址0x00000000处显示的向量与观察到的行为一致。在执行中断之前,所有这些信息都是在地址0x08000298(在FLASH存储器中已加载正确代码的正确位置)的断点处暂停时收集的。
答案 0 :(得分:1)
arm-v6参考手册中引用了VTOR。对此进行检查是个好主意。 https://static.docs.arm.com/ddi0419/d/DDI0419D_armv6m_arm.pdf
0xE000ED08 VTOR RW 0x00000000a向量表偏移量寄存器,VTOR第B3-231页
该参考手册适用于arm-v6M架构,该架构是cortex-m0处理器的架构。这是圣经。 stm系列的大多数通用cortex-m0功能不会在stm refrenece手册中提及,只是在手臂上。
我要重申一下,检查VTOR。
并确保您正在为STM32F030做正确的选择!
STM32F030x4和STM32F030x6微处理器具有与STM32F030x8不同的内存映射。
答案 1 :(得分:0)
听起来链接器文件可能有问题。
您可以验证链接器文件是否具有类似于以下内容的文件? (如果它是默认文件,则可能会复杂得多)。
. = 0;
.text 0 :
{
*(.vector);
crt0*(.text*);
main*(.text*);
*(.text*);
} > flash
基本上,这是指程序的“文本”(代码)从地址0x0开始,首先要放入向量表,然后是启动代码,主代码,然后是其他代码。 / p>
然后,您还需要检查是否有一些文件指定此向量表的内容,并同意该向量表应位于地址0x0处。此示例来自ATSAMD21E18A。
.section .vector, "a", %progbits
.equ stack_base, 0x20004000
.word stack_base
.word reset_handler
.word nmi_handler
.word hardfault_handler
.word 0
// ...
.word 0
.word systick_handler
// ...
重要的是,它被标记为链接器文件将尝试放入0x0的vector
部分。对于具有VTOR的处理器(例如M0 +),此表可能在C中指定,没有任何特殊标记,并且其位置无关紧要,但是由于您没有VTOR,因此需要确保链接器知道放置此部分位于0x0。
答案 2 :(得分:-1)