STM32启动文件详解

STM32启动文件详解
STM32启动文件详解

第1章启动文件详解

本章参考资料《CM3权威指南CnR2》第三章:Cortex-M3基础,第四章:指令集。官方暂时没有《CM4权威指南》,有关内核的部分暂时只能参考CM3,所幸的是CM4跟CM3有非常多的相似之处,资料基本一样。还有一个资料是ARM Development Tools:这个资料主要用来查询ARM的汇编指令。

1.1启动文件简介

启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:

1、初始化堆栈指针SP=_initial_sp

2、初始化PC指针=Reset_Handler

3、初始化中断向量表

4、配置系统时钟

5、调用C库函数_main初始化用户堆栈,从而最终调用main函数去到C的世界

1.2查找ARM汇编指令

在讲解启动代码的时候,会涉及到ARM的汇编指令和Cortex内核的指令,有关Cortex内核的指令我们可以参考CM3权威指南CnR2》第四章:指令集。剩下的ARM的汇编指令我们可以在MDK->Help->Uvision Help中搜索到,以EQU为例,检索如下:

图1ARM汇编指令索引

检索出来的结果会有很多,我们只需要看Assembler User Guide这部分即可。下面列出了启动文件中使用到的ARM汇编指令,该列表的指令全部从ARM Development Tools

这个帮助文档里面检索而来。其中编译器相关的指令WEAK和ALIGN为了方便也放在同一个表格了。

表格1启动文件使用的ARM汇编指令汇总

指令名称作用

EQU给数字常量取一个符号名,相当于C语言中的define

AREA汇编一个新的代码段或者数据段

SPACE分配内存空间

PRESERVE8当前文件堆栈需按照8字节对齐

EXPORT声明一个标号具有全局属性,可被外部的文件使用

DCD以字为单位分配内存,要求4字节对齐,并要求初始化这些内存PROC定义子程序,与ENDP成对使用,表示子程序结束

WEAK弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。要注意的是:这个不是ARM

的指令,是编译器的,这里放在一起只是为了方便。

IMPORT声明标号来自外部文件,跟C语言中的EXTERN关键字类似

B跳转到一个标号

ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示4字节对齐。要注意的是:这个不是ARM的指令,是

编译器的,这里放在一起只是为了方便。

END到达文件的末尾,文件结束

IF,ELSE,ENDIF汇编条件分支语句,跟C语言的类似

1.3启动文件代码讲解

1.Stack—栈

1Stack_Size EQU0x00000400

2

3AREA STACK,NOINIT,READWRITE,ALIGN=3

4Stack_Mem SPACE Stack_Size

5__initial_sp

开辟栈的大小为0X00000400(1KB),名字为STACK,NOINIT即不初始化,可读可写,8(2^3)字节对齐。

栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬fault的时候,这时你就要考虑下是不是栈不够大,溢出了。

EQU:宏定义的伪指令,相当于等于,类似与C中的define。

AREA:告诉汇编器汇编一个新的代码段或者数据段。STACK表示段名,这个可以任意命名;NOINIT表示不初始化;READWRITE表示可读可写,ALIGN=3,表示按照2^3对齐,即8字节对齐。

SPACE:用于分配一定大小的内存空间,单位为字节。这里指定大小等于

Stack_Size。

标号__initial_sp紧挨着SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。

2.Heap堆

1Heap_Size EQU0x00000200

2

3AREA HEAP,NOINIT,READWRITE,ALIGN=3

4__heap_base

5Heap_Mem SPACE Heap_Size

6__heap_limit

开辟堆的大小为0X00000200(512字节),名字为HEAP,NOINIT即不初始化,可读可写,8(2^3)字节对齐。__heap_base表示对的起始地址,__heap_limit表示堆的结束地址。堆是由低向高生长的,跟栈的生长方向相反。

堆主要用来动态内存的分配,像malloc()函数申请的内存就在堆上面。这个在STM32里面用的比较少。

1PRESERVE8

2THUMB

PRESERVE8:指定当前文件的堆栈按照8字节对齐。

THUMB:表示后面指令兼容THUMB指令。THUBM是ARM以前的指令集,16bit,现在Cortex-M系列的都使用THUMB-2指令集,THUMB-2是32位的,兼容16位和32位的指令,是THUMB的超级。

3.向量表

1AREA RESET,DATA,READONLY

2EXPORT__Vectors

3EXPORT__Vectors_End

4EXPORT__Vectors_Size

定义一个数据段,名字为RESET,可读。并声明__Vectors、__Vectors_End和

__Vectors_Size这三个标号可被外部的文件使用。

EXPORT:声明一个标号可被外部的文件使用,使标号具有全局属性。如果是IAR编译器,则使用的是GLOBAL这个指令。

下面这段话引用自《CM3权威指南CnR2》3.5—向量表,因为暂时没有找到关于M4向量表的说明,但是CM4跟CM3差不多,有很大的参考价值。—秉火注

当CM3内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定ESR的入口地址,CM3使用了“向量表查表机制”。这里使用一张向量表。向量表其实是一个WORD(32位整数)数组,每个下标对应一种异常,该下标元素的值则是该ESR的入口地址。向量表在地址空间中的位置是可以设置的,通过NVIC中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为0。因此,在地址0(即FLASH地址0)处必须包含一张向量表,用于初始时的异常分配。

表格2向量表结构

异常类型表项地址偏移量异常向量

00X00MSP的初始化值

10X04复位

20X08NMI

30X0C硬fault

40X10MenManage fault

50X14总线fault

60X18用法fault

7-100X1C-0X28保留

110X2C SVC

120X30调试监视器

130X34保留

140X38PendSV

150X4C SysTick

160X40IRQ#0

170X44IRQ#1

18-2550X48-0X3FF IRQ#2-239

举个例子,如果发生了异常11(SVC),则NVIC会计算出偏移移量是

11x4=0x2C,然后从那里取出服务例程的入口地址并跳入。要注意的是这里有个另类:0号类型并不是什么入口地址,而是给出了复位后MSP的初值。

异常1~15为系统异常,之后的是外部中断,CM3支持240个外部中断,但是具体要使用多少个由芯片设计厂家决定,是STM32F429中,只是使用了一部分,远没有240个外部中断这么多,这里所说的外部是相对应内核而言。

代码1向量表

1__Vectors DCD__initial_sp;栈顶地址

2DCD Reset_Handler;复位程序地址

3DCD NMI_Handler

4DCD HardFault_Handler

5DCD MemManage_Handler

6DCD BusFault_Handler

7DCD UsageFault_Handler

8DCD0;0表示保留

9DCD0

10DCD0

11DCD0

12DCD SVC_Handler

13DCD DebugMon_Handler

14DCD0

15DCD PendSV_Handler

16DCD SysTick_Handler

17

18

19;外部中断开始

20DCD WWDG_IRQHandler

21DCD PVD_IRQHandler

22DCD TAMP_STAMP_IRQHandler

23

24;限于篇幅,中间代码省略

25DCD LTDC_IRQHandler

26DCD LTDC_ER_IRQHandler

27DCD DMA2D_IRQHandler

28__Vectors_End

1__Vectors_Size EQU__Vectors_End-__Vectors

__Vectors为向量表起始地址,__Vectors_End为向量表结束地址,两个相减即可算出向量表大小。

向量表从FLASH的0地址开始放置,以4个字节为一个单位,地址0存放的是栈顶地址,0X04存放的是复位程序的地址,以此类推。从代码上看,向量表中存放的都是中断服务函数的函数名,可我们知道C语言中的函数名就是一个地址。

DCD:分配一个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中,DCD分配了一堆内存,并且以ESR的入口地址初始化它们。

4.复位程序

1AREA|.text|,CODE,READONLY

定义一个名称为.text的代码段,可读。

1Reset_Handler PROC

2EXPORT Reset_Handler[WEAK]

3IMPORT SystemInit

4IMPORT__main

5

6LDR R0,=SystemInit

7BLX R0

8LDR R0,=__main

9BX R0

10ENDP

复位子程序是系统上电后第一个执行的程序,调用SystemInit函数初始化系统时钟,然后调用C库函数_mian,最终调用main函数去到C的世界。

WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以由用户在其他文件重新实现,这里并不是唯一的。

IMPORT:表示该标号来自外部文件,跟C语言中的EXTERN关键字类似。这里表示SystemInit和__main这两个函数均来自外部的文件。

SystemInit()是一个标准的库函数,在system_stm32f4xx.c这个库文件总定义。主要作用是配置系统时钟,这里调用这个函数之后,F429的系统时钟配被配置为

180M。

__main是一个标准的C库函数,主要作用是初始化用户堆栈,最终调用main函数去到C的世界。这就是为什么我们写的程序都有一个main函数的原因。如果我们在这里不调用__main,那么程序最终就不会调用我们C文件里面的main,如果是调皮的用户就可以修改主函数的名称,然后在这里面IMPORT你写的主函数名称即可。

1Reset_Handler PROC

2EXPORT Reset_Handler[WEAK]

3IMPORT SystemInit

4IMPORT user_main

5

6LDR R0,=SystemInit

7BLX R0

8LDR R0,=user_main

9BX R0

10ENDP

这个时候你在C文件里面写的主函数名称就不是main了,而是user_main了。

LDR、BLX、BX是CM4内核的指令,可在《CM3权威指南CnR2》第四章-指令集里面查询到,具体作用见下表:

指令名称作用

LDR从存储器中加载字到一个寄存器中

BL跳转到由寄存器/标号给出的地址,并把跳转前的下条指令地址保存到LR BLX跳转到由寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令地址保存到LR

BX跳转到由寄存器/标号给出的地址,不用返回

5.中断服务程序

在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的C文件里面重新实现,这里只是提前占了一个位置而已。

如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且在这个空函数中无线循环,即程序就死在这里。

1NMI_Handler PROC;系统异常

2EXPORT NMI_Handler[WEAK]

3B.

4ENDP

5

6;限于篇幅,中间代码省略

7SysTick_Handler PROC

8EXPORT SysTick_Handler[WEAK]

9B.

10ENDP

11

12Default_Handler PROC;外部中断

13EXPORT WWDG_IRQHandler[WEAK]

14EXPORT PVD_IRQHandler[WEAK]

15EXPORT TAMP_STAMP_IRQHandler[WEAK]

16

17;限于篇幅,中间代码省略

18LTDC_IRQHandler

19LTDC_ER_IRQHandler

20DMA2D_IRQHandler

21B.

22ENDP

B:跳转到一个标号。这里跳转到一个‘.’,即表示无线循环。

6.用户堆栈初始化

1ALIGN

ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐。

1;用户栈和堆初始化

2IF:DEF:__MICROLIB

3

4EXPORT__initial_sp

5EXPORT__heap_base

6EXPORT__heap_limit

7

8ELSE

9

10IMPORT__use_two_region_memory

11EXPORT__user_initial_stackheap

12

13__user_initial_stackheap

14

15LDR R0,=Heap_Mem

16LDR R1,=(Stack_Mem+Stack_Size)

17LDR R2,=(Heap_Mem+Heap_Size)

18LDR R3,=Stack_Mem

19BX LR

20

21ALIGN

22

23ENDIF

24END

判断是否定义了__MICROLIB,如果定义了则赋予标号__initial_sp(栈顶地址)、

__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用。如果没有定义(实际的情况就是我们没定义__MICROLIB)则使用默认的C库,然后初始化用户堆栈大小,这部分有C库函数__main来完成,当初始化完堆栈之后,就调用main 函数去到C的世界。

IF,ELSE,ENDIF:汇编的条件分支语句,跟C语言的if,else类似

END:文件结束

1.4系统启动流程

下面这段话引用自《CM3权威指南CnR2》3.8—复位序列,CM4的复位序列跟CM3一样。—秉火注。

在离开复位状态后,CM3做的第一件事就是读取下列两个32位整数的值:

1、从地址0x0000,0000处取出MSP的初始值。

2、从地址0x0000,0004处取出PC的初始值——这个值是复位向量,LSB必须是1。然后从这个值所对应的地址处取指。

图2复位序列

请注意,这与传统的ARM架构不同——其实也和绝大多数的其它单片机不同。传统的ARM架构总是从0地址开始执行第一条指令。它们的0地址处总是一条跳转指令。在CM3中,在0地址处提供MSP的初始值,然后紧跟着就是向量表。向量表中的数值是32位的地址,而不是跳转指令。向量表的第一个条目指向复位后应执行的第一条指令,就是我们刚刚分析的Reset_Handler这个函数。

图3初始化MSP和PC的一个范例

因为CM3使用的是向下生长的满栈,所以MSP的初始值必须是堆栈内存的末地址加1。举例来说,如果我们的堆栈区域在0x20007C00-0x20007FFF之间,那么MSP的初始值就必须是0x20008000。

向量表跟随在MSP的初始值之后——也就是第2个表目。要注意因为CM3是在Thumb态下执行,所以向量表中的每个数值都必须把LSB置1(也就是奇数)。正是因为这个原因,图3中使用0x101来表达地址0x100。当0x100处的指令得到执行后,就正式开始了程序的执行(即去到C的世界)。在此之前初始化MSP是必需的,因为可能第1

条指令还没来得及执行,就发生了NMI或是其它fault。MSP初始化好后就已经为它们的服务例程准备好了堆栈。

现在,程序就进入了我们熟悉的C世界,现在我们也应该明白main并不是系统执行的第一个程序了。

1.5每课一问

1、启动文件的主要作用是什么?

2、FLASH地址0存放的是什么?

3、熟悉启动文件里面的ARM汇编指令

STM32启动文件详解

STM32启动文件详解 (2012-07-28 11:22:34) 转载▼ 分类:STM32 标签: stm32 启动 在<>,用的是STM32F103RBT6,所有的例程都采用了一个叫STM32F10x.s的启动文件,里面定义了STM32的堆栈大小以及各种中断的名字及入口函数名称,还有启动相关的汇编代码。STM32F10x.s是MDK提供的启动代码,从其里面的内容看来,它只定义了3个串口,4个定时器。实际上STM32的系列产品有5个串口的型号,也只有有2个串口的型号,定时器也是,做多的有8个定时器。比如,如果你用的 STM32F103ZET6,而启动文件用的是STM32F10x.s的话,你可以正常使用串口1~3的中断,而串口4和5的中断,则无**常使用。又比如,你TIM1~4的中断可以正常使用,而5~8的,则无法使用。 而在固件库里出现3个文件 startup_stm32f10x_ld.s startup_stm32f10x_md.s startup_stm32f10x_hd.s 其中,ld.s适用于小容量产品;md.s适用于中等容量产品;hd适用于大容量产品; 这里的容量是指FLASH的大小.判断方法如下: 小容量:FLASH≤32K 中容量:64K≤FLASH≤128K 大容量:256K≤FLASH ;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** ;* File Name : startup_stm32f10x_hd.s ;* Author : MCD Application Team ;* Version : V3.5.0 ;* Date : 11-March-2011 ;* Description : STM32F10x High Density Devices vector table for MDK-ARM ;* toolchain. ;* This module performs: ;* - Set the initial SP ;* - Set the initial PC == Reset_Handler ;* - Set the vector table entries with the exceptions ISR address ;* - Configure the clock system and also configure the external ;* SRAM mounted on STM3210E-EVAL board to be used as data ;* memory (optional, to be enabled by user) ;* - Branches to __main in the C library (which eventually ;* calls main()). ;* After Reset the CortexM3 processor is in Thread mode,

Keil4 建立STM32工程详解

Keil4 建立STM32工程详解 1:安装mdk412,用注册机注册,这个过程不详细叙述了。 2:在本地某个路径下建立STM32工程文件夹,命名:my_STM32,并在my_STM32下建立rvmdk文件夹,并在rvmdk文件夹内建立 obj,list两个文件夹。 3: 打开Keil4. 4: 选择Project菜单->New uVision Project...,选择.../my_STM32/rvmdk文件夹的路径,并命名工程文件:my_STM32,回车 5:选择器件名称,见图1

图1 单击OK。 6:如图2所示:选择否,不添加Startup.s,以后自己添加。 图2 7:如图3,建立几个Group:startup(即将装入启动文件等),usr(即将装入应用程序文件),FWlib(即将装入库文件的.c文件),doc(即将装入说明文档)

图3 8:右键单击FWlib,Add Files to Group 'FWlib',选择库文件的路径下的src 文件内的所有文件,并点击Add,如图4所示:

图4 9:将cortexm3_macro.s,stm32f10x_vector.s,stm32f10x_it.c, stm32f10x_it.h,stm32f10x_conf.h,main.c,readme.txt拷贝到my_STM32文件夹内。 10:右键单击usr,Add Files to Group 'usr',选择main.c,stm32f10x_it.c,stm32f10x_it.h,stm32f10x_conf.h,并Add,如图5所示

STM32启动文件的选择及宏定义及芯片型号更改IAP总结(精)

STM32启动文件的选择及宏定义及芯片型号更改 IAP总结 startup_stm32f10x_cl.s 互联型的器件,STM32F105xx,STM32F107xx startup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_hd_vl.s 大容量的STM32F100xx startup_stm32f10x_ld.s 小容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_ld_vl.s 小容量的STM32F100xx startup_stm32f10x_md.s 中容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_md_vl.s 中容量的STM32F100xx startup_stm32f10x_xl.s FLASH在512K到1024K字节的STM32F101xx, STM32F102xx,STM32F103xx cl:互联型产品,stm32f105/107系列 vl:超值型产品,stm32f100系列 xl:超高密度产品,stm32f101/103系列 ld:低密度产品,FLASH小于64K md:中等密度产品,FLASH=64 or 128 hd:高密度产品,FLASH大于128 在KEIL下可以在项目的选项C/C++/PREPROMCESSOR symbols的Define栏里定义,比如STM32F10X_CL 也可以在STM32F10X.H里用宏定义 #if !defined (STM32F10X_LD && !defined (STM32F10X_LD_VL && !defined (STM32F10X_MD && !defined (STM32F10X_MD_VL && !defined (STM32F10X_HD && !defined (STM32F10X_XL && !defined (STM32F10X_CL #define STM32F10X_HD #endif

STM32固件库详解42324

STM32固件库详解 最近考试较多,教材编写暂停了一下,之前写了很多,只是每一章都感觉不是特别完整,最近把其中的部分内容贴出来一下,欢迎指正。本文内容基于我对固件库的理解,按照便于理解的顺序进行整理介绍,部分参考了固件库的说明,但是也基本上重新表述并按照我理解的顺序进行重新编写。我的目的很简单,很多人写教程只是告诉你怎么做,不会告诉你为什么这么做,我就尽量吧前因后果都说清楚,这是我的出发点,水平所限,难免有很大的局限性,具体不足欢迎指正。基于标准外设库的软件开发 STM32标准外设库概述 STM32标准外设库之前的版本也称固件函数库或简称固件库,是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。该函数库还包括每一个外设的驱动描述和应用实例,为开发者访问底层硬件提供了一个中间API,通过使用固件函数库,无需深入掌握底层硬件细节,开发者就可以轻松应用每一个外设。因此,使用固态函数库可以大大减少用户的程序编写时间,进而降低开发成本。每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。每个器件的开发都由一个通用API (application programming interface 应用编程界面)驱动,API对该驱动程序的结构,函数和参数名称都进行了标准化。

ST公司2007年10月发布了版本的固件库,MDK 之前的版本均支持该库。2008年6月发布了版的固件库,从2008年9月推出的MDK 版本至今均使用版本的固件库。以后的版本相对之前的版本改动较大,本书使用目前较新的版本。 使用标准外设库开发的优势 简单的说,使用标准外设库进行开发最大的优势就在于可以使开发者不用深入了解底层硬件细节就可以灵活规范的使用每一个外设。标准外设库覆盖了从GPIO到定时器,再到CAN、I2C、SPI、UART和ADC 等等的所有标准外设。对应的C源代码只是用了最基本的C编程的知识,所有代码经过严格测试,易于理解和使用,并且配有完整的文档,非常方便进行二次开发和应用。 STM32F10XXX标准外设库结构与文件描述 1. 标准外设库的文件结构 在上一小节中已经介绍了使用标准外设库的开发的优势,因此对标准外设库的熟悉程度直接影响到程序的编写,下面让我们来认识一下STM32F10XXX的标准外设库。STM32F10XXX的标准外设库经历众多的更新目前已经更新到最新的版本,开发环境中自带的标准外设库为版本,本书中以比较稳定而且较新的版本为基础介绍标准外设库的结构。

STM32F10x 启动代码文件选择

startup_stm32f10x_xx.s 启动代码文件选择startup_stm32f10x_cl.s 互联型的器件,STM32F105xx,STM32F107xx startup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_hd_vl.s 大容量的STM32F100xx startup_stm32f10x_ld.s 小容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_ld_vl.s 小容量的STM32F100xx startup_stm32f10x_md.s 中容量的STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_md_vl.s 中容量的STM32F100xx startup_stm32f10x_xl.s FLASH在512K到1024K字节的STM32F101xx,STM32F102xx,STM32F103xx 固件库中的Release_Notes_for_STM32F10x_CMSIS.html写到: STM32F10x CMSIS Startup files: startup_stm32f10x_xx.s Add new startup files for STM32 Low-density Value line devices: startup_stm32f10x_ld_vl.s Add new startup files for STM32 Medium-density Value line devices: startup_stm32f10x_md_vl.s SystemInit() function is called from startup file (startup_stm32f10x_xx.s) before to branch to applic ation main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f10x.c file GNU startup file for Low density devices (startup_stm32f10x_ld.s) is updated to fix compilation err ors. 例如我用STM32F103RB,那么选启动文件为startup_stm32f10x_md.s

用STM32一步一步点亮led灯

STM32之一步一步点亮led (2011-05-09 19:40) 标签: stm32led v3.4MDK 4.12入门分类:stm32 入手stm32以来,一直想快速上手,所以在各大论坛闲逛,各个达人的blog 上学习,正所谓欲速则不达,心急是吃不了热豆腐的!有木有? 最终决定使用st官网的库开发,据大侠们写道使用库可以快速上手,貌似的确如此,一个个教程写的那么好,直接拿过来用就是了。可是那么多个库,聪明的你请告诉到底选择哪一个啊?My God!实话实说,我被这些库折腾了个够!好吧,我最后还是承认最后用的是v3.4的库,是很方便! 切入正题,点亮LED。 硬件:红牛开发板,STM32F103ZET6(144封装). 软件:RealView MDK 4.12 stm32固件库:v3.4 附上自己整理后的库: V3.4_clean.rar 根据官网库自己整理了下,新建了工程模板如下图:(主要参考文章《在 Keil MDK+环境下使用STM32 V3.4库.pdf》)在KeilMDK+环境下使用STM32V3.4库.pdf 入图所示:新建一个目录01_ProLed,建议放在英文路径下,避免不必要的麻烦。将上面的库v3.4解压到此目录,再新建一个project目录,存放工程。 说明: CMSIS:最底层接口。StartUp:系统启动文件。StdPeriph_Lib:stm32外围设

备驱动文件。Project:工程文件。User:用户文件。新建工程步骤:此处略去300字。 简单说明: 1.core_cm3.c/core_cm3.h 该文件是内核访问层的源文件和头文件,查看其中的代码多半是使用汇编语言编写的。在线不甚了解。--摘自《在Keil MDK+环境下使用STM32 V3.4库》 2.stm32f10x.h 该文件是外设访问层的头文件,该文件是最重要的头文件之一。就像51里面的reg51.h一样。例如定义了 CPU是哪种容量的 CPU,中断向量等等。除了这些该头文件还定义了和外设寄存器相关的结构体,例如: 1.typedef struct

STM32启动概述

STM32启动代码概述 一般嵌入式开发流程就是先建立一个工程,再编写源文件,然后进行编译,把所有的*.s文件和*.c文件编译成一个*.o文件,再对目标文件进行链接和定位,编译成功后会生成一个*.hex文件和调试文件,接下来要进行调试,如果成功的话,就可以将它固化到flash里面去。 启动代码是用来初始化电路以及用来为高级语言写的软件作好运行前准备的一小段汇编语言,是任何处理器上电复位时的程序运行入口点。 比如,刚上电的过程中,PC机会对系统的一个运行频率进行锁定在一个固定的值,这个设计频率的过程就是在汇编源代码中进行的,也就是在启动代码中进行的。与此同时,设置完后,程序开始运行,注意,程序是在内存中运行的。这个时候,就需要把一些源文件从flash里面copy到内存中,又要对它们进行初始化读写,这又有频率的设置。这些都是初始化。 初始化完成后,我们又要设置一些堆栈,要跳到C语言的main函数里面运行。这就需要堆栈。对普通的ARM CPU有这样一个要求:在绝对地址为零的地方要放置一个异常向量表,但并不是所有的ARM CPU都留有这个一个空间,这就需要用到映射的功能。我们可以将其它地方的一些空间映射到绝对地址里面。当发生异常时,ARM核来读取异常中断表的时候,它会使用映射之后的那个表,这个就可以接着往下执行,否则在绝对地址零的地方找不到任何信息,程序就会死掉。这些运行的环境全部建立好后,程序就会跳转到我们的main函数里面。 总之,启动代码,就是对最小系统的初始化。包括晶振,CPU频率等。 启动代码的最小系统是:异常向量表的初始化–存储区分配–初始化堆栈–高级语言入口函数调用– main()函数。 程序的启动过程:

STM32_V3.5的固件库工程模板

准备工作如下: 1:下载STM32_V3.5的固件库去论坛上找,很多 2:准备Keil uVision4 软件,并安装到电脑上。 3:不要带板凳了,带上你的脑袋就行,因为板凳不会思考。 开始: 1:首先解压缩下载的固件库(保留一个备份,你懂的) 里面有, _htmresc : ST的 logo完全无用,不用理会, Libraries:比较重要的文件包含STM32的系统文件和大量头文件,也就是库文件了。 Project:包含大量外设的例程,和各个软件版本的评估版工程模板。 KEIL对应的就是 MDK-ARM 文件下的工程模板。你也可以利用这个工程模板来修改,得到你自己的工程模块,本文不用此法。 Utilities:就是评估版的相关文件:本文也不会用到,无视既可。 这四个文件,(先去掉文件的只读属性吧,相信你会的) 2:安照一般的方法,建立工程模板先建立一些文件夹,比如工程模板要建在D盘,下面的 D:\STM32\PRO1(项目名字,自己随便定)再该文件夹下面新建以下文件夹 Libraries:直接复制上述的的Libraries文件夹,把其中的CMSIS剪切出来,放到PRO1目录下,直接成为另一个文件夹。另外把STM32F10x_StdPeriph_Driver下的inc和src文件夹剪切出来,放在Libraries目录下,STM32F10x_StdPeriph_Driver文件夹就可以删除了。会发现里面就只剩下头文件了。 CMSIS:就是从上面粘贴来的。在CMSIS\CM3\DeviceSupport\ST\STM32F10x目录下直接将Sta rtu p文件剪切出来,放在Libraries目录下,其他的不需要动。里面存放的就是重要的系统文件,先不要理会是什么作用吧,慢慢就明白了。 Startup 就是从上面粘贴来的。我们要用的比如是:STM32F103VC,只要把startup\arm目录下的startup_stm32f10x_hd.s文件剪切出来,放到Startup 下面就好。Startup只要这个文件,

stm32启动文件详解

STM32启动文件详解 一、启动文件的作用 1.初始化堆栈指针SP; 2.初始化程序计数器指针PC; 3.设置堆、栈的大小; 4.设置异常向量表的入口地址; 5.配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM); 6.设置C库的分支入口__main(最终用来调用main函数); 7.在版的启动文件还调用了在文件中的SystemIni()函数配置系统时钟。

二、汇编指令

三、启动代码 ----- 栈 Stack_Size EQU 0x00000400 ; 栈的大小 AREA STACK, NOINIT, READWRITE,ALIGN=3 Stack_Mem SPACE Stack_Size ; 分配栈空间 __initial_sp ; 栈的结束地址(栈顶地址) 分配名为STACK,不初始化,可读可写,8(2^3)字节对齐的1KB空间。 栈:局部变量,函数形参等。栈的大小不能超过内部SRAM大小。 AREA:汇编一个新的代码段或者数据段。STACK段名,任意命名;NOINIT表示不初始化;READWRITE可读可写;ALIGN=3(2^3= 8字节对齐)。 __initial_sp紧挨了SPACE放置,表示栈的结束地址,栈是从高往低生长,结束地址就是栈顶地址。

----- 堆 Heap_Size EQU 0x00000200 ; 堆的大小(512Bytes) AREA HEAP, NOINIT, READWRITE,ALIGN=3 __heap_base ; 堆的起始地址 Heap_Mem SPACE Heap_Size ; 分配堆空间 __heap_limit ; 堆的结束地址 分配名为HEAP,不初始化,可读可写,8(2^3)字节对齐的512字节空间。__heap_base堆的起始地址,__heap_limit堆的结束地址。堆由低向高生长。动态分配内存用到堆。 PRESERVE8 -- 指定当前文件的堆/栈按照8 字节对齐。 THUMB-- 表示后面指令兼容THUMB 指令。THUBM 是ARM 以前的指令集,16bit;现在Cortex-M 系列的都使用THUMB-2 指令集,THUMB-2 是32 位的,兼容16 位和32 位的指令,是THUMB 的超级。 3.向量表 AREA RESET, DATA, READONLY EXPORT __Vectors E XPORT __Vectors_End E XPORT __Vectors_Size 定义一个名为RESET,可读的数据段。并声明__Vectors、__Vectors_End 和__Vectors_Size 这三个标号可被外部的文件使用。 __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler

STM32启动过程分析

STM32启动 ARM7和ARM9启动时从绝对地址0X00000000开始执行复位中断程序,即固定了复位后的起始地址,但中断向量表的位置是可变的。 而STM32则不同,M3内核规定起始地址必须存放栈顶地址,第二个地址必须是复位中断向量的入口地址,这样CPU复位后会自动从下一个32位地址取出复位中断向量的入口地址,PC就跳转到中断服务程序,所以M3是固定了中断向量表的位置而地址是可变的。 M3的中断向量表有三个位置,通过BOOT引脚进行启动设置。 BOOT1=x BOOT0=0 从用户闪存启动,这是正常的工作模式。中断向量表定位于FLASH区,复位后PC=0x80000000. OOT1=0 BOOT0=1 从系统存储器启动(相当于厂家在存储器中固化了BOOTLOADER),这种模式启动的程序功能由厂家设置。 BOOT1=1 BOOT0=1 从内置SRAM启动,这种模式可以用于调试。这种模式下,中断向量表位于SRAM区,起始地址为0x20000000.复位为PC=0x20000000. startup_stm32f10x_XX.s 这个文件里面首先定义了复位中断(复位入口矢量被硬件固定在地址 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,如果重写了,因为是弱别名,所以会被你写的同名函数覆盖。 在中断向量表中第一个存放的是复位中断向量,STM32MDK环境中 Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0

STM32之启动文件详细解析(V3.5.0)讲解

在<>,用的是STM32F103RBT6,所有的例程都采用了一个叫STM32F10x.s的启动文件,里面定义了STM32的堆栈大小以及各种中断的名字及入口函数名称,还有启动相关的汇编代码。STM32F10x.s是MDK提供的启动代码,从其里面的内容看来,它只定义了3个串口,4个定时器。实际上STM32的系列产品有5个串口的型号,也只有有2个串口的型号,定时器也是,做多的有8个定时器。比如,如果你用的STM32F103ZET6,而启动文件用的是STM32F10x.s的话,你可以正常使用串口1~3的中断,而串口4和5的中断,则无**常使用。又比如,你TIM1~4的中断可以正常使用,而5~8的,则无法使用。 而在固件库里出现3个文件 startup_stm32f10x_ld.s startup_stm32f10x_md.s startup_stm32f10x_hd.s 其中,ld.s适用于小容量产品;md.s适用于中等容量产品;hd适用于大容量产品; 这里的容量是指FLASH的大小.判断方法如下: 小容量:FLASH≤32K 中容量:64K≤FLASH≤128K 大容量:256K≤FLASH ;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** ;* File Name : startup_stm32f10x_hd.s ;* Author : MCD Application Team ;* Version : V3.5.0 ;* Date : 11-March-2011 ;* Description : STM32F10x High Density Devices vector table for MDK-ARM ;* toolchain. ;* This module performs: ;* - Set the initial SP ;* - Set the initial PC == Reset_Handler ;* - Set the vector table entries with the exceptions ISR address ;* - Configure the clock system and also configure the external ;* SRAM mounted on STM3210E-EVAL board to be used as data ;* memory (optional, to be enabled by user) ;* - Branches to __main in the C library (which eventually ;* calls main()). ;* After Reset the CortexM3 processor is in Thread mode, ;* priority is Privileged, and the Stack is set to Main. ;* 说明: 此文件为STM32F10x高密度设备的MDK工具链的启动文件 ;* 该模块执行以下操作: ;* -设置初始堆栈指针(SP)

STM32入门C语言详解精编版

阅读flash:芯片内部存储器flash操作函数我的理解——对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。 基础应用1,FLASH时序延迟几个周期,等待总线同步操作。推荐按照单片机系统运行频率,0—24MHz时,取Latency=0;24—48MHz时,取Latency=1;48~72MHz时,取Latency=2。 所有程序中必须的 用法:FLASH_SetLatency(FLASH_Latency_2); 位置:RCC初始化子函数里面,时钟起振之后。 基础应用2,开启FLASH预读缓冲功能,加速FLASH的读取。 所有程序中必须的 用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 位置:RCC初始化子函数里面,时钟起振之后。 3、阅读lib:调试所有外设初始化的函数。 我的理解——不理解,也不需要理解。只要知道所有外设在调试的时候,EWRAM需要从这个函数里面获得调试所需信息的地址或者指针之类的信息。 基础应用1,只有一个函数debug。所有程序中必须的。 用法:#ifdef DEBUG debug(); #endif 位置:main函数开头,声明变量之后。 4、阅读nvic:系统中断管理。 我的理解——管理系统内部的中断,负责打开和关闭中断。 基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。 所有程序中必须的。 用法:void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; //中断管理恢复默认参数 #ifdef VECT_TAB_RAM //如果C/C++ Compiler\Preprocessor\Defined symbols中的定义了 VECT_TAB_RAM(见程序库更改内容的表格) NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //则在RAM调试 #else //如果没有定义VECT_TAB_RAM NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//则在Flash里调试 #endif //结束判断语句 //以下为中断的开启过程,不是所有程序必须的。 //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC优先级分组,方式。 //注:一共16个优先级,分为抢占式和响应式。两种优先级所占的数量由此代码确定, NVIC_PriorityGroup_x可以是0、1、2、3、4,分别代表抢占优先级有1、2、4、8、16个和响应优先级有16、8、4、2、1个。规定两种优先级的数量后,所有的中断级别必须在其中选择,抢占级别高的会打断其他中断优先执行,而响应级别高的会在其他中断执行完优先执行。 //NVIC_InitStructure.NVIC_IRQChannel = 中断通道名; //开中断,中断名称见函数库 //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级

STM32启动代码分析、简化、实战

本文通过对STM32的官方固件库 STM32F10x_StdPeriph_Lib_V3.5.0 里的MDK启动文件分析,简化部分不需要的代码, 并从繁杂的固件库里,精炼出一个类似于“hello world”的入门实战小程序——点亮一个LED。该工程仅仅包含一个启动文件和一个有main函数的C文件。 本文初衷:不用固件库建立自己的工程! 实验软件:Keil uVision4 实验硬件:神舟IV号开发板 芯片型号:STM32F107VC

STM32启动代码分析、简化、实战 汇编基础: 1.伪指令:EQU 语法格式:名称EQU表达式{,类型} EQU伪指令用于为程序中的常量、标号等定义一个等效的字符名称,类似于C语言的#define。其中EQU可以用“*”代替。 名称为EQU伪指令定义的字符名称,当表达式为32位的常量时,可以指定表达式的数据类型,可以有一下三种类型: CODE16、CODE32和DA TA 2.伪指令:AREA 语法格式:AREA段名{,属性1}{,属性2}…… AREA命令指示汇编程序汇编一个新的代码段或数据段。段是独立的、指定的、不可见的代码或数据块,它们由链接程序处理。 段名:可以为段选择任何段名。但是,以一个数字开始的名称必须包含在竖杠号内,否则会产生一个缺失段名错误。例如,|1_DataArea|。 有些名称是习惯性的名称。例如:|.text|用于表示由C编译程序产生的代码段,或用于以某种方式与C库关联的代码段。 属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:——CODE属性:用于定义代码段,默认为READONLY。 ——DA TA属性:用于定义数据段,默认为READWRITE。 ——READONLY属性:指定本段为只读,代码段默认为READONLY。 ——READWRITE属性:指定本段为可读可写,数据段的默认属性为READWRITE。——ALIGN属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。——NOINIT属性:表示数据段是未初始化的或初始化为零。其只包含零初始化的空间保留命令SPACE或DCB、DCD、DCDU、DCQ、DCQU、DCW或DCWU。可以决定在链接时AREA是未初始化的还是零初始化的。 一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。 3.伪指令:SPACE用于分配一片连续的存储单元 启动代码分析: 定义栈段,不初始化 栈名:STACK 大小:Stack_Size 只分配空间不做初始化或者初始化为0:NOINIT 可读可写:READWRITE: 按8字节对齐:ALIGN=3 栈顶地址:__initial_sp Stack_Size EQU0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp

stm32知识点最终版

1.*嵌入式系统:以计算机技术为基础,以应用为中心,软件硬件可剪裁,适合应用系统对功能可靠性、成本、体积、功耗严格要求的专业计算机系统。 2.*嵌入式系统与传统系统等所区分的三个特征:微处理器通常由32位以上的RISC组成;软件通常是以嵌入式操作系统为核心,外加用户应用程序;具有明显的可嵌入性。 3.*嵌入式系统的应用:智能消费电子中;工业控制中;医疗设备中;信息家电及家庭智能管理系统;网络与通信系统中;环境工程;机器人。 4.*ARM定义的三大分工明确的系列:“A”系列面向尖端的基于虚拟内存的操作系统和用户应用(针对日益增长的运行包括linux、Windows、CE和Android在内的消费电子和无线产品);“R”系列针对实时系统(针对需要运行实时操作系统来惊醒控制应用的系统,包括汽车电子、网络和影像系统);“M”系列对胃控制器和点成本应用提供优化(针对开发费用低功耗低,同时针对性能要求不断增加的嵌入式应用而设计,如汽车车身控制系统和各种大型家电)。 5.ARM Cortex处理器系列是基于ARMv7构架的产品,既有ARM Cortex-M系列,也有高性能的A系列。 6.NEON技术是64/128位SIMD指令集,用于新一代媒体和信号处理应用加速。NEON支持8位,16位,32位,64位整数及单精度浮点SIMD操作,以进行音频,视频、图像和游戏的处理。 7.ARM Cortex-M3处理器的特点:性能丰富成本低,低功耗,可配置性能强,丰富的链接。 8.*STM32F10x处理器分为:101,102,103,105,107。 9.*STM32的总线速度:USB接口速度12Mb/s;USART接口速度s;SPI接口速度可达18Mb/s;IC接口速度400kHz。 10.STM32系列处理器的优点:先进的内部结构;三种功耗控制;最大程度集成整合;出众及创新的外设。 11.STM32F10x按性能分为:基本型STM32F101,USB基本型STM32F102,增强型STM32F103,互联网型STM32F105、STM32F107系列。 12.STM32F103RBT6系列的命名规则:R-引脚数量、B-Flash大小、T-封装、6-工作温度。 13.*STM32F103按照引脚功能分为:电源、复位、时钟控制、启动配置、输入输出口。 14.STM32F103总线系统包括:驱动单元、被动单元、总线矩阵。 15.最小系统是指仅包含必须的元器件、仅可运行最基本软件的基本系统。 16.典型的最小系统包括:微控制器芯片、供电电路、时钟电路、复位电路、启动配置电路和程序下载电路。 第三章 标准库命名则:PPP_Init:根据PPP_InitTypeDef中指定的参数初始化外设ppp; PPP_DeInit:将外设PPP寄存器重设为缺省值; PPP_StructInit:将PPP_InitTypeDef结构中的参数设为缺省值; PPP_Cmd:使能或失能PPP外设; PPP_ItConfig:使能或失能PPP外设的中断源; PPP_GetITStatus:判断PPP外设中断发生与否; PPP_ClearITPendingBit:清除PPP外设中断待处理标志位; PPP_DMAConfig:使能或者失能PPP外设的DMA接口; PPP_GetFlagStatus:检查PPP外设的标志位; PPP_ClearFiag:清除PPP外设的标志位。 2.文件结构:每个C程序通常分为两个文件,一个文件用于保存程序的声明,成为头文件,以.h为后缀。另一个用于保存程序的实现,称为源文件,以.c后缀。 3.C语言的关键字有32个,根据作用分为数据类型、控语言、储存类型、其他关键字。 4.指针:是C语言中广泛使用的一种数据类型. 5.指向数组元素的指针 定义一个整形数组和一个指向整型的指针变量: Int a [10]; Int*p=NULL;. }结构变量; 如果去掉结构变量,就成为对结构的说明。 6.CMSIS是独立于供应商处理器硬件抽象层。 7.CMSIS软件架构:用户应用层,操作系统及中间件接口层,CMSIS层和硬件层。

(keil添加文件)建立一个最简单工程

建立一个最简单工程-基于StdPeriph_Lib 第一步: 新建一个工程文件: 并选择CPU型号: 询问是否复制自带的启动文件,选择否即可,我们使用ST固件库中的.

第二步: 对源文件分组管理 新建三个组: user Libraries(ST固件库) CMSIS(CM系列通用库) 分组管理源文件可以使程序结构变成清晰

第三步: 开始添加源文件 User 目录添加main.c it.c(包含最基本的中断处理函数) Libraries 目录添加ST固件库的所有文件(可以只添加需要的,但一起添加比较省事,且链接时并不会链接不使用的函数,所以并不会使目标变大) CMSIS添加CMSIS中STM32需要的部分 Libraries/CMSIS/CM3/CoreSupport/core_cm3.c

Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm/startup_stm32f10x_hd.s (启动文件,但STM32各系列兼容性较好,如果不用特殊功能,各启动文件区别不大)

第四步: 设置项目的头文件搜索目录及目标输出目录 1.设置全局定义: USE_STDPERIPH_DRIVER 用来定义使用ST的固件库 STM32F10X_HD 设置目标芯片的类型 其它的有STM32F10X_MD和STM32F10X_CL有等.与启动文件对应. 同时勾上one elf section per function,即相同的段只链接一次.然后开始设置头文件搜寻目录.

STM32启动文件选用说明

stm32 启动文件的选择 最近在网上看到一些关于STM32启动文件的问题帖,都是类似这样的问题: 随便选两个 “startup_stm32f10x_ld、hd、md这3个启动文件有什么不同???” “官网固件库中的启动文件有啥区别,怎么选择?” 搜索了论坛,也看了一下,有一些回答,但是都不太全或者不甚明了。其实我以前也不清楚,当然我是新手,只不过是个爱折腾的新手,因为我觉得,这个有必要弄清楚。一是启动文件在一个工程中有着不可取代的作用,二是对于STM32这个让人蛋疼而又强大的东东,经常是新手乱添加启动文件或者去找一下工程例子“依葫芦画瓢”的添加,试问你的MCU和人家工程例子的就是一样,换一款型号,要命[夸张的修辞手法,呵呵]?所有说,基于这些,我就说一说我的认识: 注意此处只针对MDK-ARM的IDE,其他的一样,只不过想说明的是对不同的IDE,同一芯片型号的启动文件的“内容”是不一样的,这是因为编译器造成的,意思就是说,启动文件的功能一样,但是指令有所 区别。这个每个启动文件也注释了,如: (原文件名:.s for MDK IAR.JPG) 啰嗦了…… 启动文件的作用: 无论性能高下,结构简繁,价格贵贱,每一种微控制器(处理器)都必须有启动文件,启动文件的作用便是负责执行微控制器从“复位”到“开始执行main函数”中间这段时间(称为启动过程)所必须进行的工作。最为常见的51,AVR或MSP430等微控制器当然也有对应启动文件,但开发环境往往自动完整地提供了这个启动文件,不需要开发人员再行干预启动过程,只需要从main函数开始进行应用程序的设计即可。[来 自网上] 我的理解,说白了,大家常说,程序执行都从main函数开始,是的,没错,但是在这之前是谁来完成了这一个繁琐而又复杂的启动过程呢?就是它。(看来.s尽干脏活苦活,就像“活雷锋一样,做了好事有不 留名”) 具体的启动过程论坛里有,想了解的可以去细看。

STM32建工程详细方法步骤

1、首先找到ST官方最新版本的固件库:STM32F10x_StdPeriph_Lib_V3.5.0 2、新建一个工程文件夹:比如led工程文件夹 3、在led工程文件夹中新建5个文件夹:CORE、HARDWARE、 STM32F10x_FWLib、SYSTEM、USER

CORE用来存放启动文件等 HARDWARE用来存放各种硬件驱动代码 STM32F10x_FWLib文件夹顾名思义用来存放ST官方提供的库函数源码文件SYSTEM文件夹下包含了delay、sys、usart等三个文件夹。分别包含了delay.c、sys.c、usart.c及其头文件delay.h、sys.h、usart.h USER用来存放我们主函数文件main.c,以及其他包括system_stm32f10x.c 等等。 4、将固件库包里面相关的启动文件复制到我们的工程目录CORE之下 打开固件库STM32F10x_StdPeriph_Lib_V3.5.0文件夹,定位到目录 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport下面,将文件core_cm3.c和文件core_cm3.h 复制到CORE下面去。然后定位到目录 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ ST\STM32F10x\startup\arm下面,将里面startup_stm32f10x_md.s、

startup_stm32f10x_ld.s、startup_stm32f10x_hd复制到CORE下面。这里我们解释一下,其实我们只用到arm目录下面的startup_stm32f10x_md.s文件,这个文件是针对中等容量芯片的启动文件。其他两个主要的为 startup_stm32f10x_ld.s为小容量,startup_stm32f10x_hd.s为大容量芯片的启动文件。这里copy进来是方便其他开发者使用小容量或者大容量芯片的用户。现在看看我们的CORE 文件夹下面的文件: 5、将官方的固件库包里的源码文件复制到我们的工程目录STM32F10x_FWLib 之下。 打开固件库STM32F10x_StdPeriph_Lib_V3.5.0文件夹,定位到目录 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Drive r下面,将目录下面的src,inc文件夹copy到我们刚才建立的 STM32F10x_FWLib文件夹下面。src存放的是固件库的.c文件,inc存放的是对应的.h文件,您不妨打开这两个文件目录过目一下里面的文件,每个外设对应一个.c文件和一个.h头文件。

相关文档
最新文档