2

编码 -

#include<stm32f030x6.h>

void _delay_ms(unsigned int del) {
  //Delay with systick
}

void sys_init() {
  //Set Clock to 6 * 8MHz crystal
}

void TIM14_IRQHandler(void) {
  //If UEV was generated, toggle PA4 (Connected to LED)
  if(TIM14->SR & TIM_SR_UIF) {
    GPIOA->BSRR = (GPIOA->ODR & GPIO_ODR_4)?(GPIO_BSRR_BR_4):(GPIO_BSRR_BS_4);
    TIM14->SR &= ~TIM_SR_UIF;
  }
}


int main(void) {
  sys_init();
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
  RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;

  GPIOA->MODER = 0b1 << GPIO_MODER_MODER4_Pos;
  //GPIOA->AFR[0] = 4 << GPIO_AFRL_AFRL4_Pos;

  //Init timer
  TIM14->ARR = 731;
  TIM14->PSC = 0xffff;
  TIM14->DIER |= TIM_DIER_UIE;
  TIM14->CR1 |= TIM_CR1_CEN;

  NVIC_EnableIRQ(TIM14_IRQn);
  NVIC_SetPriority(TIM14_IRQn, 0);

  while(1);
}

如问题中所述,当我直接从闪存启动(BOOT0 连接到 GND)时,此代码工作得很好,但在使用引导加载程序时它不起作用。一旦引发中断,芯片就会重置并再次返回引导加载程序。我怎样才能解决这个问题?
我应该提到我使用了一个自定义链接器脚本和一个经过大量修改的boot.s

4

2 回答 2

3

您遇到了此微控制器中使用的 Cortex-M0 内核的限制。

Cortex-M0 只能使用映射在地址 0x0 的中断向量表。当微控制器配置为引导至引导加载程序时,系统内存映射到地址 0,因此引导加载程序的向量表用于所有中断。因此,您无法在通过引导加载程序启动的应用程序中安全地使用中断。

在 Cortex-M0+ 和更高版本的部件上,您可以设置SCB->VTOR为使用位于内存中其他位置的向量表。但是,该寄存器在 Cortex-M0 部件(如 STM32F0)上不存在,因此不适合您。

考虑使用 SWD 编程器,如 ST-Link,而不是引导加载程序来编程您的微控制器。这也将允许您调试您的应用程序。

于 2019-02-25T01:52:55.193 回答
2

根据duskwuffs 的评论,并且由于您指向boot.s 和linker.script 的链接可以正常工作,我假设您的向量表仍然是引导加载程序中的一个,并且您的应用程序中断只是跳转到那里。如果您的引导加载程序没有在该向量表上映射 ISR,那么它可能只会发出复位(由于非法地址/指令而导致的陷阱/异常)。您可能能够拥有一个通用向量表来间接跳转到 RAM 提供的向量表,该向量表被您的应用程序在启动代码中覆盖。

于 2019-02-25T09:39:44.310 回答