<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > STM32啟動(dòng)過(guò)程相關(guān)代碼分析

STM32啟動(dòng)過(guò)程相關(guān)代碼分析

作者: 時(shí)間:2016-11-11 來(lái)源:網(wǎng)絡(luò ) 收藏
STM32F10x_StdPeriph_Lib_V3.5.0LibrariesCMSISCM3DeviceSupportSTSTM32F10xstartupTrueSTUDIO路徑下的文件進(jìn)行分析。對了,我用的庫是3.5的。

system_stm32f10x.c

本文引用地址:http://dyxdggzs.com/article/201611/316896.htm

SystemInit(): 在"startup_stm32f10x_xx.s"文件中被調用,功能是設置系統時(shí)鐘(包括時(shí)鐘源,PLL系數,AHB/APBx的預分頻系數還有 flash的設定),這個(gè)函數
會(huì )在系統復位之后首先被執行。文件中默認的一些設置:允許HSE(外部時(shí)鐘),FLASH(允許預取緩沖區,設置2個(gè)等待周 期),PLL系數為9,開(kāi)啟PLL并選擇PLL
輸出作為時(shí)鐘源(SYSCLK),后續設置SYSCLK = HCLK = APB2 = 72MHz,APB1 = HCLK/2 = 36MHz,HCLK即AHB的時(shí)鐘。

SystemCoreClockUpdate():在系統時(shí)鐘HCLK變化的時(shí)候調用,以更新一個(gè)全局變量SystemCoreClock,這個(gè)變量可以為應用程序使用,必須保證正確。默認不用
調用這個(gè)函數,因為SystemCoreClock默認被設置為設定的頻率了(72MHz)

另外,下面這種設置寄存器的方法值得借鑒,先用位名清除相應的位,再進(jìn)行設置,例如:


#define  RCC_CFGR_PLLSRC                     ((uint32_t)0x00010000)        /*!< PLL entry clock source */#define  RCC_CFGR_PLLXTPRE                   ((uint32_t)0x00020000)        /*!< HSE divider for PLL entry */#define  RCC_CFGR_PLLMULL                    ((uint32_t)0x003C0000)        /*!< PLLMUL[3:0] bits (PLL multiplication factor) */#define  RCC_CFGR_PLLSRC_HSE                ((uint32_t)0x00010000)        /*!< HSE clock selected as PLL entry clock source */#define  RCC_CFGR_PLLMULL9                  ((uint32_t)0x001C0000)        /*!< PLL input clock*9 *//*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

startup_stm32f10x_md.s:(開(kāi)發(fā)板的F103RBT6是中容量的產(chǎn)品)

這個(gè)文件里面首先定義了復位中斷(復位入口矢量被硬件固定在地址0x0000_0004)的處理函數:Reset_Handler,它的作用就是將保存于flash中的初始化數據復
制到sram中,調用上面說(shuō)到的SystemInit來(lái)初始化時(shí)鐘,接著(zhù)跳轉到main執行。

接著(zhù)定義了Default_Handler, 這個(gè)是作為其他所有中斷的默認處理函數,作用就是死循環(huán),所以你假如開(kāi)啟了某個(gè)中斷,請按照這里面的中斷函數名給它寫(xiě)中斷
處理函數,例如串口中斷處理函數名是 USART1_IRQHandler,你開(kāi)了串口中斷,如果不重寫(xiě)USART1_IRQHandler,就默認執行Default_Handler,死循環(huán)了。而如
果你有重寫(xiě),那么中斷向量表中的處理函數的地址就會(huì )更新為你自己寫(xiě)的那個(gè)函數的地址了。為什么會(huì )這樣呢?因為此文件的末尾用了類(lèi)似這樣的語(yǔ)句:

.weak    USART1_IRQHandler.thumb_set USART1_IRQHandler,Default_Handler

它給中斷處理函數提供了弱(weak)別名(Default_Handler),如果不重寫(xiě),中斷了默認執行Default_Handler,如果重寫(xiě)了,因為是弱別名,所以會(huì )被你寫(xiě)的同名
函數覆蓋。


最后定義了一個(gè)中斷向量表的段(.section .isr_vector,"a",%progbits),這個(gè)表將會(huì )放置在0x0000 0000那里,第二個(gè)字(0x0000 0004)是復位向量,復位之后
重這地址所指的函數執行。

那么,如何保證.isr_vector這個(gè)段將放在flash的最開(kāi)始(0x08000000)呢?這就需要鏈接腳本了,即我們用的那個(gè)stm32_flash.ld文件了,查看一下就知道了,里面
先定義了堆棧的地址:_estack

/* Highest address of the user mode stack */_estack = 0x20005000;    /* end of 20K RAM */

接著(zhù)定義了堆和棧的大?。?/p>

/* Generate a link error if heap and stack dont fit into RAM */_Min_Heap_Size = 0;      /* required amount of heap  */_Min_Stack_Size = 0x100; /* required amount of stack */

接著(zhù)聲明了各個(gè)內存的區域(定義了幾個(gè)代表某個(gè)線(xiàn)性空間的名字,如下面的FLASH):


/* Specify the memory areas */MEMORY{FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 128K   RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K   MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K }

接著(zhù)下面再介紹上面這三個(gè)名字里面都放了什么東西,首先是FLASH的:


/* Define output sections */SECTIONS{/* The startup code goes first into FLASH */.isr_vector :{. = ALIGN(4);    KEEP(*(.isr_vector)) /* Startup code */. = ALIGN(4);  } >FLASH/* The program code and other data goes into FLASH */.text :{. = ALIGN(4);    *(.text)           /* .text sections (code) */*(.text*)          /* .text* sections (code) */*(.rodata)         /* .rodata sections (constants, strings, etc.) */*(.rodata*)        /* .rodata* sections (constants, strings, etc.) */*(.glue_7)         /* glue arm to thumb code */*(.glue_7t)        /* glue thumb to arm code */KEEP (*(.init))KEEP (*(.fini)). = ALIGN(4);    _etext = .;        /* define a global symbols at end of code */   } >FLASH

可以看到startup_stm32f10x_md.s中定義的這個(gè)段.isr_vector確實(shí)放在了最開(kāi)頭的位置。下面其他的內容就不分析了可查看下面地址獲取更多信息
(http://www.stf12.org/developers/freerots_ec-linker_script.html)。

但是我們前面說(shuō)復位向量在0x0000 0004,現在其地址是在flash中,所以地址是0x0800 0004,這個(gè)怎么回事呢?原來(lái),stm32可以通過(guò)boot0、boot1引腳的配置
將flash映射到0x0000 0000處。具體可參考stm32的用戶(hù)手冊2.4節:

從主閃存存儲器啟動(dòng)(BOOT0 = 0,BOOT1 = X):主閃存存儲器被映射到啟動(dòng)空間(0x0000 0000),但仍然能夠在它原有的地址(0x0800 0000)訪(fǎng)問(wèn)它,即閃存存
儲器的內容可以在兩個(gè)地址區域訪(fǎng)問(wèn),0x0000 0000或0x0800 0000。

至此,整個(gè)STM32的啟動(dòng)過(guò)程以及程序結構都可以比較清晰了。至于使用MDK-ARM 環(huán)境的情況,也差不多的。


評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>