stm32f0 cortex m0 做bootloader中断向量表重映射

stm32f0 cortex m0 做bootloader中断向量表重映射

环境

  • MDK5

  • STM32F042K6Tx

  • Cortex-M0

问题

使用了一款Cortex-M0内核的芯片STM32F042K6Tx,发现它中断向量表的重映射方法与STM32F10x不同

STM32F10x HAL库使用

 NVIC_SetVectorTable
 或
 void SystemInit (void)
 {
     SCB->VTOR = 0x08003800;
 }

但是STM32F042K6Tx对应M0并没有SCB->VTOR

如何确定M0没有呢?

库中没有

Drivers\CMSIS\Include\core_cm0.h

 typedef struct
 {
   __IM  uint32_t CPUID;                  /*!< Offset: 0x000 (R/ )  CPUID Base Register */
   __IOM uint32_t ICSR;                   /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register */
         uint32_t RESERVED0;
   __IOM uint32_t AIRCR;                  /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register */
   __IOM uint32_t SCR;                    /*!< Offset: 0x010 (R/W)  System Control Register */
   __IOM uint32_t CCR;                    /*!< Offset: 0x014 (R/W)  Configuration Control Register */
         uint32_t RESERVED1;
   __IOM uint32_t SHP[2U];                /*!< Offset: 0x01C (R/W)  System Handlers Priority Registers. [0] is RESERVED */
   __IOM uint32_t SHCSR;                  /*!< Offset: 0x024 (R/W)  System Handler Control and State Register */
 } SCB_Type;
 ​

M0手册中没有

https://www.st.com/resource/en/reference_manual/DM00091010-.pdf

STM32F0X2参考手册中

https://www.st.com/resource/en/reference_manual/dm00031936-stm32f0x1stm32f0x2stm32f0x8-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

 Physical remap
 Once the boot mode is selected, the application software can modify the memory accessible
 in the code area. This modification is performed by programming the MEM_MODE bits in
 the SYSCFG configuration register 1 (SYSCFG_CFGR1). Unlike Cortex® M3 and M4, the
 M0 CPU does not support the vector table relocation. For application code which is located
 in a different address than 0x0800 0000, some additional code must be added in order to be
 able to serve the application interrupts. A solution will be to relocate by software the vector
 table to the internal SRAM:
 • Copy the vector table from the Flash (mapped at the base of the application load
 address) to the base address of the SRAM at 0x2000 0000.
 • Remap SRAM at address 0x0000 0000, using SYSCFG configuration register 1.
 • Then once an interrupt occurs, the Cortex®-M0 processor will fetch the interrupt
 handler start address from the relocated vector table in SRAM, then it will jump to
 execute the interrupt handler located in the Flash.
 This operation should be done at the initialization phase of the application. Please refer to
 AN4065 and attached IAP code from www.st.com for more details. 

解决方法(把中断向量表拷贝到sram)

代码添加位置

可以在app也可以在bootloader但是要保证在boot关总中断后app打开中断之前

HAL库

 memcpy((void *)0x20000000, (void *)0x08002800, VECTOR_SIZE);
 LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);

标准库

 memcpy((void*)0x20000000, (void*)0x08002800, VECTOR_SIZE);
 /*/Libraries/STM32F0xx_StdPeriph_Driver/src/stm32f0xx_syscfg.c*/
 SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
 /*0x2000 0000是SRAM的起始地址*/
 /*0x08002800是应用程序的起址地址*/
 /*VECTOR_SIZE是指中断向量表的大小*/

本次使用HAL库

bootloader

 #define FLASH_START                     0x08000000  
 #define IAP_SIZE                          (10*1024) 
 #define ApplicationAddress          (FLASH_START+IAP_SIZE) //0x08002800
 ​
 void JumpToApp(void)
 {
   /* Check if valid stack address (RAM address) then jump to user application */
   if (((* (volatile unsigned long*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
   {
     HAL_NVIC_DisableIRQ(USART1_IRQn);
     HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);
     __disable_irq();
     /* Jump to user application */
     JumpAddress = *(volatile unsigned long*) (ApplicationAddress + 4);
     Jump_To_Application = (pFunction) JumpAddress;
 ​
     // memcpy((void *)RAM_START_ADDR, (void *)ApplicationAddress, VECTOR_SIZE);
     // LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);
 ​
     /* Initialize user application's Stack Pointer */
     __set_MSP(*(volatile unsigned long*) ApplicationAddress);
 ​
     //NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x08003800);
     Jump_To_Application();
   }
 ​
 }

APP

 int main(void)
 {
 ​
   /* USER CODE BEGIN 1 */
 ​
   /* USER CODE END 1 */
 ​
   /* MCU Configuration----------------------------------------------------------*/
 ​
   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
   HAL_Init();
 ​
   /* USER CODE BEGIN Init */
     memcpy((void *)RAM_START_ADDR, (void *)ApplicationAddress, 0xc0);
     LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);
   /* USER CODE END Init */
     __enable_irq();//使能中断
   /* Configure the system clock */
   SystemClock_Config();
 }

 

如何确定VECTOR_SIZE大小

MDK-ARM\startup_stm32f042x6.s

 Stack_Size      EQU     0x400
 ​
                 AREA    STACK, NOINIT, READWRITE, ALIGN=3
 Stack_Mem       SPACE   Stack_Size
 __initial_sp
 ​
 ​
 ; <h> Heap Configuration
 ;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
 ; </h>
 ​
 Heap_Size      EQU     0x200
 ​
                 AREA    HEAP, NOINIT, READWRITE, ALIGN=3
 __heap_base
 Heap_Mem        SPACE   Heap_Size
 __heap_limit
 ​
                 PRESERVE8
                 THUMB
 ​
 ​
 ; Vector Table Mapped to Address 0 at Reset
                 AREA    RESET, DATA, READONLY
                 EXPORT  __Vectors
                 EXPORT  __Vectors_End
                 EXPORT  __Vectors_Size
 ​
 __Vectors       DCD     __initial_sp                   ; Top of Stack
                 DCD     Reset_Handler                  ; Reset Handler
                 DCD     NMI_Handler                    ; NMI Handler
                 DCD     HardFault_Handler              ; Hard Fault Handler
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     SVC_Handler                    ; SVCall Handler
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     PendSV_Handler                 ; PendSV Handler
                 DCD     SysTick_Handler                ; SysTick Handler
 ​
                 ; External Interrupts
                 DCD     WWDG_IRQHandler                ; Window Watchdog
                 DCD     PVD_VDDIO2_IRQHandler          ; PVD through EXTI Line detect
                 DCD     RTC_IRQHandler                 ; RTC through EXTI Line
                 DCD     FLASH_IRQHandler               ; FLASH
                 DCD     RCC_CRS_IRQHandler             ; RCC and CRS
                 DCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1
                 DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3
                 DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15
                 DCD     TSC_IRQHandler                 ; TS
                 DCD     DMA1_Channel1_IRQHandler       ; DMA1 Channel 1
                 DCD     DMA1_Channel2_3_IRQHandler     ; DMA1 Channel 2 and Channel 3
                 DCD     DMA1_Channel4_5_IRQHandler     ; DMA1 Channel 4 and Channel 5
                 DCD     ADC1_IRQHandler                ; ADC1 
                 DCD     TIM1_BRK_UP_TRG_COM_IRQHandler ; TIM1 Break, Update, Trigger and Commutation
                 DCD     TIM1_CC_IRQHandler             ; TIM1 Capture Compare
                 DCD     TIM2_IRQHandler                ; TIM2
                 DCD     TIM3_IRQHandler                ; TIM3
                 DCD     0                              ; Reserved
                 DCD     0                              ; Reserved
                 DCD     TIM14_IRQHandler               ; TIM14
                 DCD     0                              ; Reserved
                 DCD     TIM16_IRQHandler               ; TIM16
                 DCD     TIM17_IRQHandler               ; TIM17
                 DCD     I2C1_IRQHandler                ; I2C1
                 DCD     0                              ; Reserved
                 DCD     SPI1_IRQHandler                ; SPI1
                 DCD     SPI2_IRQHandler                ; SPI2
                 DCD     USART1_IRQHandler              ; USART1
                 DCD     USART2_IRQHandler              ; USART2
                 DCD     0                              ; Reserved
                 DCD     CEC_CAN_IRQHandler             ; CEC and CAN
                 DCD     USB_IRQHandler                 ; USB
 ​
 __Vectors_End
 ​
 __Vectors_Size  EQU  __Vectors_End - __Vectors
 ​
                 AREA    |.text|, CODE, READONLY
 ​
 ; Reset handler routine
 Reset_Handler    PROC
                  EXPORT  Reset_Handler                 [WEAK]
         IMPORT  __main
         IMPORT  SystemInit  
 ​
 ​
 ​
         LDR     R0, =__initial_sp          ; set stack pointer 
         MSR     MSP, R0  
 ​
 ;;Check if boot space corresponds to test memory 
 ​
         LDR R0,=0x00000004
         LDR R1, [R0]
         LSRS R1, R1, #24
         LDR R2,=0x1F
         CMP R1, R2
         
         BNE ApplicationStart  
      
 ;; SYSCFG clock enable    
      
         LDR R0,=0x40021018 
         LDR R1,=0x00000001
         STR R1, [R0]
         
 ;; Set CFGR1 register with flash memory remap at address 0
 ​
         LDR R0,=0x40010000 
         LDR R1,=0x00000000
         STR R1, [R0]
 ApplicationStart
                  LDR     R0, =SystemInit
                  BLX     R0
                  LDR     R0, =__main
                  BX      R0
                  ENDP
 ​
 ; Dummy Exception Handlers (infinite loops which can be modified)
 ​
 NMI_Handler     PROC
                 EXPORT  NMI_Handler                    [WEAK]
                 B       .
                 ENDP
 HardFault_Handler\
                 PROC
                 EXPORT  HardFault_Handler              [WEAK]
                 B       .
                 ENDP
 SVC_Handler     PROC
                 EXPORT  SVC_Handler                    [WEAK]
                 B       .
                 ENDP
 PendSV_Handler  PROC
                 EXPORT  PendSV_Handler                 [WEAK]
                 B       .
                 ENDP
 SysTick_Handler PROC
                 EXPORT  SysTick_Handler                [WEAK]
                 B       .
                 ENDP
 ​
 Default_Handler PROC
 ​
                 EXPORT  WWDG_IRQHandler                [WEAK]
                 EXPORT  PVD_VDDIO2_IRQHandler          [WEAK]
                 EXPORT  RTC_IRQHandler                 [WEAK]
                 EXPORT  FLASH_IRQHandler               [WEAK]
                 EXPORT  RCC_CRS_IRQHandler             [WEAK]
                 EXPORT  EXTI0_1_IRQHandler             [WEAK]
                 EXPORT  EXTI2_3_IRQHandler             [WEAK]
                 EXPORT  EXTI4_15_IRQHandler            [WEAK]
                 EXPORT  TSC_IRQHandler                 [WEAK]
                 EXPORT  DMA1_Channel1_IRQHandler       [WEAK]
                 EXPORT  DMA1_Channel2_3_IRQHandler     [WEAK]
                 EXPORT  DMA1_Channel4_5_IRQHandler [WEAK]
                 EXPORT  ADC1_IRQHandler           [WEAK]
                 EXPORT  TIM1_BRK_UP_TRG_COM_IRQHandler [WEAK]
                 EXPORT  TIM1_CC_IRQHandler             [WEAK]
                 EXPORT  TIM2_IRQHandler                [WEAK]
                 EXPORT  TIM3_IRQHandler                [WEAK]
                 EXPORT  TIM14_IRQHandler               [WEAK]
                 EXPORT  TIM16_IRQHandler               [WEAK]
                 EXPORT  TIM17_IRQHandler               [WEAK]
                 EXPORT  I2C1_IRQHandler                [WEAK]
                 EXPORT  SPI1_IRQHandler                [WEAK]
                 EXPORT  SPI2_IRQHandler                [WEAK]
                 EXPORT  USART1_IRQHandler              [WEAK]
                 EXPORT  USART2_IRQHandler              [WEAK]
                 EXPORT  CEC_CAN_IRQHandler             [WEAK]
                 EXPORT  USB_IRQHandler                 [WEAK]
 ​
 ​
 WWDG_IRQHandler
 PVD_VDDIO2_IRQHandler
 RTC_IRQHandler
 FLASH_IRQHandler
 RCC_CRS_IRQHandler
 EXTI0_1_IRQHandler
 EXTI2_3_IRQHandler
 EXTI4_15_IRQHandler
 TSC_IRQHandler
 DMA1_Channel1_IRQHandler
 DMA1_Channel2_3_IRQHandler
 DMA1_Channel4_5_IRQHandler
 ADC1_IRQHandler
 TIM1_BRK_UP_TRG_COM_IRQHandler
 TIM1_CC_IRQHandler
 TIM2_IRQHandler
 TIM3_IRQHandler
 TIM14_IRQHandler
 TIM16_IRQHandler
 TIM17_IRQHandler
 I2C1_IRQHandler
 SPI1_IRQHandler
 SPI2_IRQHandler
 USART1_IRQHandler
 USART2_IRQHandler
 CEC_CAN_IRQHandler
 USB_IRQHandler
 ​
                 B       .
 ​
                 ENDP
 ​
                 ALIGN
 ​
 ;*******************************************************************************
 ; User Stack and Heap initialization
 ;*******************************************************************************
                  IF      :DEF:__MICROLIB
 ​
                  EXPORT  __initial_sp
                  EXPORT  __heap_base
                  EXPORT  __heap_limit
 ​
                  ELSE
 ​
                  IMPORT  __use_two_region_memory
                  EXPORT  __user_initial_stackheap
 ​
 __user_initial_stackheap
 ​
                  LDR     R0, =  Heap_Mem
                  LDR     R1, =(Stack_Mem + Stack_Size)
                  LDR     R2, = (Heap_Mem +  Heap_Size)
                  LDR     R3, = Stack_Mem
                  BX      LR
 ​
                  ALIGN
 ​
                  ENDIF
 ​
                  END
 ​
 ;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****
 ​

29行Vectors---到-->80行Vectors_End 每一个DCD都代表一个中断向量 ( 中断服务程序的入口地址 )

例如:

 DCD     USART1_IRQHandler              ; USART1

这里的“USART1_IRQHandler"其实就是UART1中断服务程序USART1_IRQHandler这个函数,同时,它也代表这个函数的入口地址。

因为DCD对应的表示一个表中的元素,每个元素是一个长度为4字节的地址。除了第一个地址是SP(堆栈指针)外,其它的地址都是某个中断服务程序的入口地址。

使用Notepad计数发现有48个

1601196493488

所以:VECTOR_SIZE = 48*4 = 192 = 0xC0(字节)

使用WinHex查看位置(0xc0)

1601202631740

 

APP中RAM偏移

在执行完以上两行代码后,若发生中断,CPU就会去SRAM(即0x2000 0000处)取中断向量了,所以,以0x2000 0000作为起始地址之后的VECTOR_SIZE个字节就不能被改动了。为了达到这VECTOR_SIZE个字节不被修改的目的,如下两种方法可以实现。

1601197358833

总结

boot关闭中断开关---->跳转到app的bin地址+4位置(也就是rest)---->进入app以后把中断向量表拷贝到内存中,并使用LL_SYSCFG_SetRemapMemory告诉芯片到时候去内存0x20000000中找找中断--->打开中断开关

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值