爲什麼STM32從Flash地址0x08000000的啓動重映射

在初寫STM32程序時,遇到一個困惑,STM32的Flash在MDK裏被設置爲起始地址0x0800 0000,而CM3手冊規定芯片復位時要從0x0000 0000地址開始取出中斷向量 ,那STM32怎麼樣執行代碼呢?地址重映射?或者在0x0000 0000裏有對應有實際存儲器?

仔細閱讀手冊,發現這件事是因爲STM32設計的Flash起始地址是在0x0800 0000位置開始的。全部代碼都只能從這裏開始存儲。詳見STM32 referenc manual手冊第54頁。

那既然從這裏才能存儲代碼,就必須在MDK裏設置Flash地址爲0x0800 0000,下面是MDK設置頁面,這個應該都看到過。

這樣就還有一個問題,理論上,CM3中規定上電後CPU是從0地址開始執行,但是這裏中斷向量表卻被燒寫在0x0800 0000地址裏,那啓動時不就找不到中斷向量表了?既然CM3定下的規矩是從0地址啓動,SMT32當然不能破壞ARM定下的“規矩”,所以它做了一個啓動映射的過程,就是和芯片上總能見到的BOOT0和BOOT1有關了,當選擇從主Flash啓動模式後,芯片一上電,Flash的0x0800 0000地址被映射到0地址處,不影響CM3內核的讀取,所以這時的CM3既可以在0地址處訪問中斷向量表,也可以在0x0800 0000地址處訪問中斷向量表,而代碼還是在0x0800 0000地址處存儲的。這就是最難理解的地方,其實,這是基本上所有ARM芯片採用的啓動映射方法。ARM7,ARM9沒有內部Flash的通常都是這樣做的。這個過程出自STM32 referenc manual手冊,裏面是有說明的。

還要注意,這個中斷向量表是可以在程序中再次被映射的。控制它的就是CM3已經規定的NVIC寄存器SCB->VTOR。在STM32庫中給出的啓動代碼裏,startup_stm32f10x_hd.s文件裏,第146行,是上電後讀取中斷向量表中的復位中斷位置,並執行復位中斷處理代碼,代碼如下:

; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP

 注意復位後第一個被執行的是SystemInit代碼,這個代碼在庫目錄下的system_stm32f10x.c文件裏,它初始化了時鐘,NVIC等一系列操作,這裏摘要與中斷向量有關的代碼:

void SystemInit (void)

{

......

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

可以看出中斷向量重映射是一個選擇性編譯,通常宏定義VECT_TAB_SRAM都沒有被定義,所以這裏執行結束後,SCB->VTOR就是FLASH_BASE了,值爲0x0800 0000。以後CM3再取中斷向量裏,就會根據SCB->VTOR的設置,從這裏取向量執行了。中斷向量自此終於轉正。

注意這時連__main函數都還沒進,看起來中斷向量的重映射位置還是夠早的。

發佈了10 篇原創文章 · 獲贊 214 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章