1. 程式人生 > >【轉】STM32F030Cxxx 沒有SCB->VTOR,如何重定位向量表

【轉】STM32F030Cxxx 沒有SCB->VTOR,如何重定位向量表

原為地址:http://www.51hei.com/bbs/dpj-40235-1.html

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

     由於需要通過IAP進行韌體升級,所以晶片的FLASH裡面要燒錄兩份程式碼:一個Boot loader, 一個使用者應用程式。理所當然的,在使用者應用程式中,必須得重新對映中斷向量表。      可是在ST提供的韌體庫裡,我卻沒有發現類似於stm32f10x韌體庫中的voidNVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)介面。
     瀏覽了一下Cortex-M0的Programmingmanual,原來M0並沒有SCB->VTOR這個暫存器,難怪ST的庫裡沒有提供NVIC_SetVectorTable這個介面。      這下要怎麼辦?在網路上搜索了一下,受到網友findaway123這篇文章的啟發,我在STM32F030CC的Reference manual中找到以下說明:      Physicalremap   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 ableto serve the application interrupts. A solution will be to relocateby software the vector table to the internal SRAM:
  ? Copy the vector table from the Flash (mapped at the base of theapplication load address) to the base address of the SRAM at 0x20000000.   ? 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);


memcpy((void*)0x20000000, (void*)FLASH_MAIN_FW_START_ADDR, 0xB4); 

  __HAL_SYSCFG_REMAPMEMORY_SRAM();

中括號中是我實際使用的code

   其中,0x2000 0000是SRAM的起始地址,這個不需要改動。    而之後的兩個引數需要根據實際情況作出修改。0x08004000是應用程式的起址地址,從這裡開始的VECTOR_SIZE位元組,存放是的應用程式的中斷向量表。VECTOR_SIZE是指中斷向量表的大小,具體多大可以在startup.s檔案裡計算得到。以下以startup_stm32f030.s為例作說明:

  我們只需關注其中的一小部分。從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處)取中斷向量了,所以,以0x20000000作為起始地址之後的VECTOR_SIZE個位元組就不能被改動了。為了達到這VECTOR_SIZE個位元組不被修改的目的,如下兩種方法可以實現。   ?在工程檔案內修改SRAM的起始地址及長度,如下圖      ?如果使用了分散載入檔案,則在分散載入檔案中修改SRAM的起始地址及長度也能達到目的。
  至此,STM32F0系列Cortex-M0核心晶片中斷向量表重對映的問題已解決。