STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\TrueSTUDIO途径下的文件进行剖析。对了,我用的库是3.5的。
system_stm32f10x.c
SystemInit(): 在”startup_stm32f10x_xx.s”文件中被调用,功用是设置体系时钟(包含时钟源,PLL系数,AHB/APBx的预分频系数还有 flash的设定),这个函数
会在体系复位之后首要被履行。文件中默许的一些设置:答应HSE(外部时钟),FLASH(答应预取缓冲区,设置2个等候周 期),PLL系数为9,敞开PLL并挑选PLL
输出作为时钟源(SYSCLK),后续设置SYSCLK = HCLK = APB2 = 72MHz,APB1 = HCLK/2 = 36MHz,HCLK即AHB的时钟。
SystemCoreClockUpdate():在体系时钟HCLK改变的时分调用,以更新一个全局变量SystemCoreClock,这个变量可认为应用程序运用,有必要确保正确。默许不必
调用这个函数,由于SystemCoreClock默许被设置为设定的频率了(72MHz)
别的,下面这种设置寄存器的办法值得学习,先用位名铲除相应的位,再进行设置,例如:
#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:(开发板的F103RBT6是中容量的产品)
这个文件里边首要界说了复位中止(复位进口矢量被硬件固定在地址0x0000_0004)的处理函数:Reset_Handler,它的效果便是将保存于flash中的初始化数据复
制到sram中,调用上面提到的SystemInit来初始化时钟,接着跳转到main履行。
接着界说了Default_Handler, 这个是作为其他一切中止的默许处理函数,效果便是死循环,所以你假设敞开了某个中止,请依照这儿边的中止函数名给它写中止
处理函数,例如串口中止处理函数名是 USART1_IRQHandler,你开了串口中止,假如不重写USART1_IRQHandler,就默许履行Default_Handler,死循环了。而如
果你有重写,那么中止向量表中的处理函数的地址就会更新为你自己写的那个函数的地址了。为什么会这样呢?由于此文件的结尾用了相似这样的句子:
.weak USART1_IRQHandler.thumb_set USART1_IRQHandler,Default_Handler
它给中止处理函数供给了弱(weak)别号(Default_Handler),假如不重写,中止了默许履行Default_Handler,假如重写了,由于是弱别号,所以会被你写的同名
函数掩盖。
最终界说了一个中止向量表的段(.section .isr_vector,”a”,%progbits),这个表将会放置在0x0000 0000那里,第二个字(0x0000 0004)是复位向量,复位之后
重这地址所指的函数履行。
那么,怎么确保.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 */
接着声明晰各个内存的区域(界说了几个代表某个线性空间的姓名,如下面的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的确放在了最最初的方位。下面其他的内容就不剖析了可检查下面地址获取更多信息
(http://www.stf12.org/developers/freerots_ec-linker_script.html)。
可是咱们前面说复位向量在0x0000 0004,现在其地址是在flash中,所以地址是0x0800 0004,这个怎么回事呢?本来,stm32能够经过boot0、boot1引脚的装备
将flash映射到0x0000 0000处。详细可参阅stm32的用户手册2.4节:
从主闪存存储器发动(BOOT0 = 0,BOOT1 = X):主闪存存储器被映射到发动空间(0x0000 0000),但仍然能够在它原有的地址(0x0800 0000)拜访它,即闪存存
储器的内容能够在两个地址区域拜访,0x0000 0000或0x0800 0000。
至此,整个STM32的发动进程以及程序结构都能够比较明晰了。至于运用MDK-ARM 环境的状况,也差不多的。