<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

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

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

          system_stm32f10x.c

          本文引用地址:http://www.ex-cimer.com/article/201611/316896.htm

          SystemInit(): 在"startup_stm32f10x_xx.s"文件中被調(diào)用,功能是設(shè)置系統(tǒng)時鐘(包括時鐘源,PLL系數(shù),AHB/APBx的預(yù)分頻系數(shù)還有 flash的設(shè)定),這個函數(shù)
          會在系統(tǒng)復(fù)位之后首先被執(zhí)行。文件中默認(rèn)的一些設(shè)置:允許HSE(外部時鐘),F(xiàn)LASH(允許預(yù)取緩沖區(qū),設(shè)置2個等待周 期),PLL系數(shù)為9,開啟PLL并選擇PLL
          輸出作為時鐘源(SYSCLK),后續(xù)設(shè)置SYSCLK = HCLK = APB2 = 72MHz,APB1 = HCLK/2 = 36MHz,HCLK即AHB的時鐘。

          SystemCoreClockUpdate():在系統(tǒng)時鐘HCLK變化的時候調(diào)用,以更新一個全局變量SystemCoreClock,這個變量可以為應(yīng)用程序使用,必須保證正確。默認(rèn)不用
          調(diào)用這個函數(shù),因?yàn)镾ystemCoreClock默認(rèn)被設(shè)置為設(shè)定的頻率了(72MHz)

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


          #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:(開發(fā)板的F103RBT6是中容量的產(chǎn)品)

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

          接著定義了Default_Handler, 這個是作為其他所有中斷的默認(rèn)處理函數(shù),作用就是死循環(huán),所以你假如開啟了某個中斷,請按照這里面的中斷函數(shù)名給它寫中斷
          處理函數(shù),例如串口中斷處理函數(shù)名是 USART1_IRQHandler,你開了串口中斷,如果不重寫USART1_IRQHandler,就默認(rèn)執(zhí)行Default_Handler,死循環(huán)了。而如
          果你有重寫,那么中斷向量表中的處理函數(shù)的地址就會更新為你自己寫的那個函數(shù)的地址了。為什么會這樣呢?因?yàn)榇宋募哪┪灿昧祟愃七@樣的語句:

          .weak    USART1_IRQHandler.thumb_set USART1_IRQHandler,Default_Handler

          它給中斷處理函數(shù)提供了弱(weak)別名(Default_Handler),如果不重寫,中斷了默認(rèn)執(zhí)行Default_Handler,如果重寫了,因?yàn)槭侨鮿e名,所以會被你寫的同名
          函數(shù)覆蓋。


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

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

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

          接著定義了堆和棧的大小:

          /* 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 */

          接著聲明了各個內(nèi)存的區(qū)域(定義了幾個代表某個線性空間的名字,如下面的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 }

          接著下面再介紹上面這三個名字里面都放了什么東西,首先是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中定義的這個段.isr_vector確實(shí)放在了最開頭的位置。下面其他的內(nèi)容就不分析了可查看下面地址獲取更多信息
          (http://www.stf12.org/developers/freerots_ec-linker_script.html)。

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

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

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


          關(guān)鍵詞: STM32啟動過程代碼分

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();