目 录
一、 工程目录结构...................................................................................................... 1 二、 启动代码分析...................................................................................................... 1
1、启动模式的选择............................................................................................... 1 2、 启动文件分析................................................................................................. 2
1) 定义栈、堆及其初始化.......................................................................... 2 2) 定义复位向量.......................................................................................... 2 3) 其他中断向量及服务子程序.................................................................. 3 4) 拓展:_main()与main()区别 ................................................................. 3 3、 我司启动文件情况:..................................................................................... 4 三、 时钟资源分析...................................................................................................... 4
1、时钟源............................................................................................................... 4 2、 时钟源输出..................................................................................................... 6 3、 SystemInit函数分析.................................................................................... 7
1) SystemInit().......................................................................................... 7 2) SetSysClock()........................................................................................ 8 3) SetSysClockTo72()................................................................................ 8
四、 Cotex-M3异常与中断 ...................................................................................... 10
1、 异常类型....................................................................................................... 10 2、 优先级定义................................................................................................... 10 3、 NVIC概述...................................................................................................... 10 4、 InterruptVector.c文件分析 ........................................................................ 11
1) RegisterInterrupt() ............................................................................ 11 2) NVIC_Init()............................................................................................ 12
五、 项目实例............................................................................................................ 13
1、文件夹建立 .................................................................................................... 13 2、工程结构建立 ................................................................................................ 14
一、工程目录结构
结合公司工程文件格式及自身习惯,建立的常用基础工程目录结构如下:
Project子文件下用来存在工程文件。 OBJ是用来存放编译过程文件以及hex文件。 USER用来存放主函数及一些临时编写的应用函数。
FWLib中存放的是ST官方库函数源码文件,包含inc、src文件夹,inc存放的是固件库的.h文件,src存放的是对应的.c文件,每个外设对应一个.c文件及一个.h头文件。
StartUp里面是系统启动文件,我司启动文件有两个(误码仪代码):startup_stm32f10x_cl.s、startup_stm32f10x_hd.s。_cl.s文件是互联型产品的启动文件,_hd.s是大容量产品的启动文件。
CorTex-M3下的core_cm3.c和core_cm3.h是CMSIS核心文件,提供进入M3内核接口,这是
ARM
公司提供,对所有
CM3
内核的芯片都一样。
system_stm32f10x.c,system_stm32f10x.h文件的功能是设置系统以及总线时钟,这个里面有一个非常重要的SystemInit()函数,这个函数在我们系统启动的时候都会调用,用来设置系统的整个时钟系统。stm32f10x.h文件打开可以看到,里面非常多的结构体以及宏定义。这个文件里面主要是系统寄存器定义申明以及包装内存操作。
Driver里面是常用的驱动代码,进行代码移植时可直接调用。
二、启动代码分析
1、启动模式的选择
1
STM32自带的启动模式有3种:
STM32的启动选择,通过设置BOOT1、BOOT0的引脚的高低电平即可选择。其中主闪存启动是将程序下载到内置的Flash进行启动(该flash可运行程序),该程序可以掉电保存,下次开机可自动启动;系统存储器启动是将程序写入到一快特定的区域,一般由厂家直接写入,不能被随意更改或擦除。内置SRAM启动,由于SRAM掉电丢失,不能保存程序,一般只用于程序的调试。
2、启动文件分析
启动文件,总的来说主要做了3个工作:分配和初始化栈、堆;定义复位向量并初始化;中断向量表及相应的异常处理程序,以107器件cl.s文件为例。
1)定义栈、堆及其初始化 定义堆、栈:
Stack_Size EQU 0x400
Heap_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack
SPACE Stack_Size
AREA HEAP, NOINIT, READWRITE, ALIGN=3 Heap
SPACE Heap_Size 堆栈初始化定义:
__user_initial_stackheap //进行栈、堆的赋值,在_main函数执行过程中调用 LDR R0, =Heap
LDR R1, =(Stack + Stack_Size) LDR R2, =(Heap + Heap_Size) LDR R3, =Stack BX LR 2)定义复位向量
Boot引脚的设置不同,复位时,起始地址的位置不同,SRAM的起始地址为0x2000000, flash的起始地址为0x8000000。Cortex-M3内核规定,起始地址必须存放堆定指针,而第二
2
个地址必须存放复位中断入口向量。在系统复位时,内核会自动从其实地址的下一个地址(即32位)空间取出复位中断入口向量,然后跳转到复位中断服务程序,该服务程序就会跳转到main()执行程序。
中断向量表(部分向量):
EXPORT __Vectors
__Vectors DCD Stack + Stack_Size ; Top of Stack DCD Reset_Handler DCD NMIException
DCD HardFaultException DCD MemManageException DCD BusFaultException DCD UsageFaultException
DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved
DCD PendSV_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved
DCD OS_CPU_PendSVHandler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler 复位中断服务程序:
EXPORT Reset_Handler Reset_Handler
IMPORT __main //导入符号,_main为运行时库提供的函数;完成堆、栈的初始化
LDR R0, =__main //等工作,调用定义的__user_initial_stackheap BX R0 //跳到_main,进入C的世界
3)其他中断向量及服务子程序
在启动文件中,只定义了中断向量,它们相应的服务子程序跳转到空操作,为之后扩展中断服务程序做准备。
4)拓展:_main()与main()区别
注意:_main()与main()不是相同函数。_main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境,最后自动跳转到main()。所以说,前者是库函数,后者是我们自己编写的main()主函数。
对含有启动程序的系统来说,执行地址与加载地址相同不容易实现。
3
因为启动程序是要烧到非易失存储器里,用来在上电执行的,而这个程序必定会有RW段,如果RW放在非易失存储器,如FLASH,那就不好实现RW功能了,因此要给RW移动到能够实现RW功能的存储器,如SRAM等.因此,对含有启动程序来说,\执行地址与加载地址相同\就不容易实现。
程序的入口点在C库中的_main处,在该点,库代码执行以下操作: ? 把RO,RW从他们的加载域复制到他们的运行域中去 ? 初始化ZI域 ? 跳到__rt_entry
而库函数__rt_entry()会完成以下工作: ? 调用__rt_stackheap_init()设置stack和heap ? 调用__rt_lib_init()初始化相应的库函数 ? 调用main(),即是我们自己的应用程序了
3、我司启动文件情况:
因公司使用的stm32芯片规格不一,分stm32f103、stm32f107系列等等,在进行程序编程时,为保证程序的可移植性,在InterruptVector.c文件中,通过预定义的方式来切换103/107器件,同时代码在进行编译过程中,需手动选择启动文件类型,不然代码无法编译成功。
图中编译使用的是cl.s文件。
三、时钟资源分析
1、时钟源
4
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库STM32学习总结在线全文阅读。
相关推荐: