STM32F0系列MCU中斷向量表的重映射


      最近使用了一款Cortex-M0內核的芯片STM32F030CC,發現它中斷向量表的重映射方法與STM32F10x系列的有所區別,在這里記錄與分享一下。

 

      由於需要通過IAP進行固件升級,所以芯片的FLASH里面要燒錄兩份代碼:一個Boot loader,  一個用戶應用程序。理所當然的,在用戶應用程序中,必須得重新映射中斷向量表。

      可是在ST提供的固件庫里,我卻沒有發現類似於stm32f10x固件庫中的void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)接口。

      瀏覽了一下Cortex-M0的Programming manual,原來M0並沒有SCB->VTOR這個寄存器,難怪ST的庫里沒有提供NVIC_SetVectorTable這個接口。

      這下要怎么辦?在網絡上搜索了一下,受到網友findaway123這篇文章的啟發,我在STM32F030CC的Reference manual中找到以下說明:

      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.

  OK,解決方法找到了!

  

  在用戶應用程序中,按照以上方法,添加以下兩行代碼:

    memcpy((void*)0x20000000, (void*)0x08004000, VECTOR_SIZE);
    SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);

   其中,0x2000 0000是SRAM的起始地址,這個不需要改動。

   而之后的兩個參數需要根據實際情況作出修改。0x0800 4000是應用程序的起址地址,從這里開始的VECTOR_SIZE字節,存放是的應用程序的中斷向量表。VECTOR_SIZE是指中斷向量表的大小,具體多大可以在startup.s文件里計算得到。以下以startup_stm32f030.s為例作說明:

  1 Stack_Size      EQU     0x00000400
  2 
  3                 AREA    STACK, NOINIT, READWRITE, ALIGN=3
  4 Stack_Mem       SPACE   Stack_Size
  5 __initial_sp
  6 
  7 
  8 ; <h> Heap Configuration
  9 ;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
 10 ; </h>
 11 
 12 Heap_Size       EQU     0x00000200
 13 
 14                 AREA    HEAP, NOINIT, READWRITE, ALIGN=3
 15 __heap_base
 16 Heap_Mem        SPACE   Heap_Size
 17 __heap_limit
 18 
 19                 PRESERVE8
 20                 THUMB
 21 
 22 
 23 ; Vector Table Mapped to Address 0 at Reset
 24                 AREA    RESET, DATA, READONLY
 25                 EXPORT  __Vectors
 26                 EXPORT  __Vectors_End
 27                 EXPORT  __Vectors_Size
 28 
 29 __Vectors       DCD     __initial_sp                   ; Top of Stack
 30                 DCD     Reset_Handler                  ; Reset Handler
 31                 DCD     NMI_Handler                    ; NMI Handler
 32                 DCD     HardFault_Handler              ; Hard Fault Handler
 33                 DCD     0                              ; Reserved
 34                 DCD     0                              ; Reserved
 35                 DCD     0                              ; Reserved
 36                 DCD     0                              ; Reserved
 37                 DCD     0                              ; Reserved
 38                 DCD     0                              ; Reserved
 39                 DCD     0                              ; Reserved
 40                 DCD     SVC_Handler                    ; SVCall Handler
 41                 DCD     0                              ; Reserved
 42                 DCD     0                              ; Reserved
 43                 DCD     PendSV_Handler                 ; PendSV Handler
 44                 DCD     SysTick_Handler                ; SysTick Handler
 45 
 46                 ; External Interrupts
 47                 DCD     WWDG_IRQHandler                ; Window Watchdog
 48                 DCD     0                              ; Reserved
 49                 DCD     RTC_IRQHandler                 ; RTC through EXTI Line
 50                 DCD     FLASH_IRQHandler               ; FLASH
 51                 DCD     RCC_IRQHandler                 ; RCC
 52                 DCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1
 53                 DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3
 54                 DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15
 55                 DCD     0                              ; Reserved
 56                 DCD     DMA1_Channel1_IRQHandler       ; DMA1 Channel 1
 57                 DCD     DMA1_Channel2_3_IRQHandler     ; DMA1 Channel 2 and Channel 3
 58                 DCD     DMA1_Channel4_5_IRQHandler     ; DMA1 Channel 4 and Channel 5
 59                 DCD     ADC1_IRQHandler                ; ADC1 
 60                 DCD     TIM1_BRK_UP_TRG_COM_IRQHandler ; TIM1 Break, Update, Trigger and Commutation
 61                 DCD     TIM1_CC_IRQHandler             ; TIM1 Capture Compare
 62                 DCD     0                              ; Reserved
 63                 DCD     TIM3_IRQHandler                ; TIM3
 64                 DCD     0                              ; Reserved
 65                 DCD     0                              ; Reserved
 66                 DCD     TIM14_IRQHandler               ; TIM14
 67                 DCD     TIM15_IRQHandler               ; TIM15
 68                 DCD     TIM16_IRQHandler               ; TIM16
 69                 DCD     TIM17_IRQHandler               ; TIM17
 70                 DCD     I2C1_IRQHandler                ; I2C1
 71                 DCD     I2C2_IRQHandler                ; I2C2
 72                 DCD     SPI1_IRQHandler                ; SPI1
 73                 DCD     SPI2_IRQHandler                ; SPI2
 74                 DCD     USART1_IRQHandler              ; USART1
 75                 DCD     USART2_IRQHandler              ; USART2
 76                 
 77 __Vectors_End
 78 
 79 __Vectors_Size  EQU  __Vectors_End - __Vectors
 80 
 81                 AREA    |.text|, CODE, READONLY
 82 
 83 ; Reset handler routine
 84 Reset_Handler    PROC
 85                  EXPORT  Reset_Handler                 [WEAK]
 86         IMPORT  __main
 87         IMPORT  SystemInit
 88 
 89 
 90 
 91         LDR     R0, =__initial_sp          ; set stack pointer 
 92         MSR     MSP, R0  
 93 

  我們只需關注其中的一小部分。從29行開始,直到75行,每一個DCD都代表一個中斷向量(所謂中斷向量,說得明白點,其實就是某個中斷服務程序的入口地址)。例如第74行的:

  DCD     USART1_IRQHandler              ; USART1

  這里的“USART1_IRQHandler"其實就是UART1中斷服務程序USART1_IRQHandler這個函數,同時,它也代表這個函數的入口地址。

  以上代碼即定義了這樣一張表,這張表包括45個元素,每個元素是一個長度為4字節的地址。除了第一個地址是SP(堆棧指針)外,其它的地址都是某個中斷服務程序的入口地址。

  那么,回到我們要解決的問題上來,之前memcpy函數中的第三個參數VECTOR_SIZE,針對本例,就應該是45*4=180(0xB4)個字節。

  

  在執行完以上兩行代碼后,若發生中斷,CPU就會去SRAM(即0x2000 0000處)取中斷向量了,所以,以0x2000 0000作為起始地址之后的VECTOR_SIZE個字節就不能被改動了。為了達到這VECTOR_SIZE個字節不被修改的目的,如下兩種方法可以實現。

  •在工程文件內修改SRAM的起始地址及長度,如下圖

  

  •如果使用了分散加載文件,則在分散加載文件中修改SRAM的起始地址及長度也能達到目的。

  

  至此,STM32F0系列Cortex-M0內核芯片中斷向量表重映射的問題已解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM