STM32启动文件详解
stm32启动文件详解及SystemInit函数分析
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
;__main函数由编译器生成,负责初始化栈、堆等,并在最后跳转到用户自定义的main()函数,来到C的世界。
Stack_Size EQU 0x00000400 ;//定义堆栈大小
AREA STACK, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段 按8字节对齐 ;AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0
;链接器检查要求堆栈八字节对齐的任何代码是否仅由保持堆栈八字节对齐的代码直接或间接地调用。
PRESERVE8 ;//指示编译器8字节对齐
Байду номын сангаас THUMB ;//指示编译器以后的指令为THUMB指令
;中断向量表定义
; Vector Table Mapped to Address 0 at Reset
;中断函数仅仅实现了Reset_Handler,其他要么是死循环,要么仅仅定义了函数名称
;STM32被设置为从内部FLASH启动时(这也是最常见的一种情况),当STM32遇到复位信号后,
解析STM32的启动过程
解析STM32的启动过程STM32的启动过程可以分为硬件启动过程和软件启动过程两部分。
硬件启动过程主要是指芯片上电后的初始化阶段,而软件启动过程则是指固定在芯片内的启动程序的执行过程。
硬件启动过程1.上电复位:当STM32芯片上电后,会进行一次复位操作,将片内的所有寄存器初始化为默认值。
2.时钟初始化:芯片复位后,需要初始化芯片的各个时钟源和时钟分频系数。
例如,配置系统时钟、外设时钟和外设时钟的分频。
3.外设初始化:初始化芯片的各个外设,包括GPIO、USART、SPI、I2C等。
外设初始化主要是配置相应的寄存器使它们能够正常工作。
4.中断向量表:中断向量表是储存在芯片中的一系列函数指针,用于响应中断事件。
在硬件启动过程中,需要将中断向量表的地址设定为固定的位置,并将其中各个中断的函数指针初始化为默认的中断服务函数。
5.系统堆栈初始化:系统堆栈是用于存储函数调用时的临时变量和程序返回地址的存储区域。
在硬件启动过程中,需要初始化系统堆栈指针,为后续的函数调用和中断处理做准备。
6. 程序复位:在芯片复位后,可以选择从外部存储器(如Flash)中加载启动程序,或从内部存储器(如内置Bootloader)中加载启动程序。
启动程序一般是一个二进制文件,其中包含了一系列的初始化指令和应用程序的入口点。
软件启动过程1.初始化函数:启动程序首先执行初始化函数,用于初始化C库、变量和硬件资源等。
例如,初始化堆栈指针、启动C库和启用FPU等。
2.系统时钟初始化:启动程序需要初始化系统时钟,以使系统能够正常工作。
这包括设置主时钟源、配置主时钟分频系数和外设时钟分频系数等。
3.初始化其他硬件资源:启动程序会初始化其他的硬件资源,例如外设、存储器、中断控制器等。
4.跳转到主函数入口点:启动程序最后一步是跳转到主函数的入口点,开始执行用户代码。
总结STM32的启动过程可以分为硬件启动过程和软件启动过程。
硬件启动过程包括上电复位、时钟初始化、外设初始化、中断向量表配置和系统堆栈初始化等操作。
解析STM32的启动过程
解析STM32的启动过程当前的嵌入式应用程序开发过程里,并且C语言成为了绝大部分场合的最佳选择。
如此一来main函数似乎成为了理所当然的起点——因为C程序往往从main函数开始执行。
但一个经常会被忽略的问题是:微控制器(单片机)上电后,是如何寻找到并执行main函数的呢?很显然微控制器无法从硬件上定位main函数的入口地址,因为使用C语言作为开发语言后,变量/函数的地址便由编译器在编译时自行分配,这样一来main函数的入口地址在微控制器的内部存储空间中不再是绝对不变的。
相信读者都可以回答这个问题,答案也许大同小异,但肯定都有个关键词,叫“启动文件”,用英文单词来描述是“Bootloader”。
无论性能高下,结构简繁,价格贵贱,每一种微控制器(处理器)都必须有启动文件,启动文件的作用便是负责执行微控制器从“复位”到“开始执行main函数”中间这段时间(称为启动过程)所必须进行的工作。
最为常见的51,AVR或MSP430等微控制器当然也有对应启动文件,但开发环境往往自动完整地提供了这个启动文件,不需要开发人员再行干预启动过程,只需要从main函数开始进行应用程序的设计即可。
话题转到STM32微控制器,无论是keiluvision4还是IAR EWARM开发环境,ST公司都提供了现成的直接可用的启动文件,程序开发人员可以直接引用启动文件后直接进行C应用程序的开发。
这样能大大减小开发人员从其它微控制器平台跳转至STM32平台,也降低了适应STM32微控制器的难度(对于上一代ARM 的当家花旦ARM9,启动文件往往是第一道难啃却又无法逾越的坎)。
相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化。
ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一条指令执行复位中断服务程序的方式启动,即固定了复位后的起始地址为0x000000(PC = 0x000000)同时中断向量表的位置并不是固定的。
stm32启动文件和汇编指令简析
stm32启动⽂件和汇编指令简析
以stm32fxxxx为例
⼀、启动⽂件,startup_stm32f40_41xxx.S
1.定义:启动⽂件由汇编填写,是系统上电复位后第⼀个执⾏的程序。
2.特征
(1)初始化堆栈指针SP=_initial_sp
(2)初始化PC指针=Reset_Handler
(3)初始化中断向量表。
(4)配置系统时钟。
(5)调⽤c库函数_main初始化⽤户堆栈,从⽽最终调⽤main函数去到c的内容。
⼆、汇编指令
启动⽂件使⽤ARM汇编指令汇总
EQU 给数字常量取⼀个符号名,相当于c语⾔define。
AREA 汇编⼀个新的代码段或数据段。
SPACE 分配内存空间。
PRESERVE8 当前⽂件堆栈需按照8字节对齐。
EXPORT 声明⼀个标号具有全局性,可被外部⽂件使⽤。
DCD 以字为单位分配内存,要求4字节对齐,并要求初始化这些内存。
PROC 定义⼦程序,与ENDP成对使⽤,表⽰⼦程序结束。
WEAK 弱定义,如果外部⽂件声明⼀个标号,则优先使⽤外部⽂件定义的标号,如果外部⽂件没有定义也不会出错。
要注意这个不是ARM 指令,是编译器的。
IMPORT 声明标号来⾃外部⽂件,跟c语⾔EXTERN关键字类似。
B 跳转到⼀个标志号。
STM32启动文件的选择及宏定义及芯片型号更改IAP总结
STM32启动文件的选择及宏定义及芯片型号更改IAP总结对于STM32芯片,启动文件主要包括以下几个部分:1.启动向量表:包含中断服务程序的地址信息,用于系统初始化和中断处理等功能。
2.中断服务程序:对中断进行处理的代码,包括系统初始化时的复位中断和其他外部中断。
3.系统初始化代码:完成芯片的初始化工作,包括时钟配置、外设初始化、堆栈初始化等。
在选择启动文件时,需要注意以下几点:1.芯片型号匹配:确保所选择的启动文件与使用的芯片型号兼容,以确保正常的系统初始化和中断处理。
2. 如需使用外部存储器:如果需要使用外部存储器,如外部Flash 或RAM,需要选择支持外部存储器的启动文件。
3. 如需使用操作系统:如果需要在系统中运行操作系统,如FreeRTOS或uc/OS等,需要选择对应操作系统的启动文件。
在启动文件中,还涉及宏定义的使用。
宏定义是一种预处理指令,用于在编译时替换特定的文本字符串。
在启动文件中,通常会使用宏定义来配置系统的时钟频率、中断向量表的起始地址等参数。
在更改芯片型号时1.切换器件描述文件:在工程文件中,需要将所使用的芯片型号对应的器件描述文件进行切换。
这个文件通常在项目设置中进行配置。
2.修改启动文件:将原有的启动文件替换为新的芯片型号所对应的启动文件。
3.更新宏定义:在新的启动文件中,需要确认并更新宏定义,以确保系统的配置和参数正确。
4.复查外设配置:在启动文件中,有可能包含对外设的初始化代码。
在更改芯片型号后,需要复查外设的配置和初始化。
总结起来,选择合适的STM32启动文件,需要根据所使用的芯片型号来进行选择,并注意更改宏定义和复查外设配置。
这样才能确保系统正常初始化和中断处理的功能。
STM32 的三种不同启动模式
STM32 的三种不同启动模式STM32 三种启动模式对应的存储介质均是芯片内置的,它们是:1. 用户闪存:芯片内置的Flash。
2. SRAM:芯片内置的RAM 区,就是内存啦。
3. 系统存储器:芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP 程序。
这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM 区。
在每个STM32 的芯片上都有两个管脚BOOT0 和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表:BOOT1=x BOOT0=0 从用户闪存启动,这是正常的工作模式。
BOOT1=0 BOOT0=1 从系统存储器启动,这种模式启动的程序功能由厂家设置。
BOOT1=1 BOOT0=1 从内置SRAM 启动,这种模式可以用于调试。
要注意的是,一般不使用内置SRAM 启动(BOOT1=1 BOOT0=1),因为SRAM 掉电后数据就丢失。
多数情况下SRAM 只是在调试时使用,也可以做其他一些用途。
如做故障的局部诊断,写一段小程序加载到SRAM 中诊断板上的其他电路,或用此方法读写板上的Flash 或EEPROM 等。
还可以通过这种方法解除内部Flash 的读写保护,当然解除读写保护的同时Flash 的内容也被自动清除,以防止恶意的软件拷贝。
STM32 PB2(BOOT1)使用注意由于STM32 PB2 脚是复用引脚,而且该复用功能是用于启动选择,使用时就要小心了。
-------------------------------------------------------------------------BOOT1 BOOT0 启动模式说明X 0 用户闪存存储器用户闪存存储器被选为启动区域0 1 系统存储器系统存储器被选为启动区域(进入ISP 模式)1 1 内嵌SRAM 内嵌SRAM 被选为启动区域-------------------------------- -----------------------------------------一般来讲我们正常使用是模式1(用户闪存存储。
STM32启动代码分析、简化、实战
本文通过对STM32的官方固件库STM32F10x_StdPeriph_Lib_V3.5.0里的MDK启动文件分析,简化部分不需要的代码,并从繁杂的固件库里,精炼出一个类似于“hello world”的入门实战小程序——点亮一个LED。
该工程仅仅包含一个启动文件和一个有main函数的C文件。
本文初衷:不用固件库建立自己的工程!实验软件:Keil uVision4实验硬件:神舟IV号开发板芯片型号:STM32F107VCSTM32启动代码分析、简化、实战汇编基础:1.伪指令:EQU语法格式:名称EQU表达式{,类型}EQU伪指令用于为程序中的常量、标号等定义一个等效的字符名称,类似于C语言的#define。
其中EQU可以用“*”代替。
名称为EQU伪指令定义的字符名称,当表达式为32位的常量时,可以指定表达式的数据类型,可以有一下三种类型:CODE16、CODE32和DA TA2.伪指令:AREA语法格式:AREA段名{,属性1}{,属性2}……AREA命令指示汇编程序汇编一个新的代码段或数据段。
段是独立的、指定的、不可见的代码或数据块,它们由链接程序处理。
段名:可以为段选择任何段名。
但是,以一个数字开始的名称必须包含在竖杠号内,否则会产生一个缺失段名错误。
例如,|1_DataArea|。
有些名称是习惯性的名称。
例如:|.text|用于表示由C编译程序产生的代码段,或用于以某种方式与C库关联的代码段。
属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。
常用的属性如下:——CODE属性:用于定义代码段,默认为READONLY。
——DA TA属性:用于定义数据段,默认为READWRITE。
——READONLY属性:指定本段为只读,代码段默认为READONLY。
——READWRITE属性:指定本段为可读可写,数据段的默认属性为READWRITE。
——ALIGN属性:使用方式为ALIGN表达式。
一文了解STM32启动过程
一文了解STM32启动过程1 概述说明每一款(芯片)的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道。
通过了解启动文件,我们可以体会到处理器的架构、指令集、中断向量安排等内容,是非常值得玩味的。
(STM32)作为一款高端Cortex-M3系列(单片机),有必要了解它的启动文件。
打好基础,为以后优化程序,写出高质量的代码最准备。
本文以一个实际测试代码--START_(TE)ST为例进行阐述。
整体过程STM32整个启动过程是指从上电开始,一直到运行到main 函数之间的这段过程,步骤为(以使用微库为例):①上电后(硬件)设置SP、PC②设置系统(时钟)③软件设置SP④加载.data、.bss,并初始化栈区⑤跳转到C文件的main函数代码启动过程涉及的文件不仅包含startup_stm32f10x_hd.s,还涉及到了MDK自带的连接库文件entry.o、entry2.o、entry5.o、entry7.o 等(从生成的map文件可以看出来)。
2 程序在Flash上的存储结构在真正讲解启动过程之前,先要讲解程序下载到Flash上的结构和程序运行时(执行到main函数)时的S(RAM)数据结构。
程序在用户Flash上的结构如下图所示。
下图是通过阅读hex文件和在MDK下调试综合提炼出来的。
上图中:MSP初始值由编译器生成,是主堆栈的初始值。
初始化数据段是.data未初始化数据段是.bss.data和.bss是在__main里进行初始化的,对于(ARM)Com (pi)ler,__main主要执行以下函数:其中__scatterlo(ad)会对.data和.bss进行初始化。
加载数据段和初始化栈的参数加载数据段和初始化栈的参数分别有4个,这里只讲解加载数据段的参数,至于初始化栈的参数类似。
0x0800033c Flash上的数据段(初始化数据段和未初始化数据段)起始地址0x20000000加载到SRAM上的目的地址0x0000000c数据段的总大小0x080002f4调用函数_scatterload_copy需要说明的是初始化栈的函数-- 0x08000304与加载数据段的函数不一样,为_scatterload_zeroinit,它的目的就是将栈空间清零。
STM32入门之文件结构
STM32入门之文件结构在开始STM32的开发之前,了解其文件结构对于编写和组织代码非常重要。
文件结构是指将代码和资源组织在文件夹和文件中的方式。
一个良好的文件结构能够提高代码的可维护性、可扩展性和可读性。
下面是一个典型的STM32文件结构示例:1. Core文件夹:这个文件夹包含了一些核心的STM32的系统文件,例如启动文件、链接脚本文件等。
启动文件包含了一些处理器的初始化代码,用于设置操作模式、初始化中断向量表等。
链接脚本文件定义了代码和数据在存储器中的位置和排列方式。
2. Drivers文件夹:这个文件夹包含了所有的外设驱动文件。
每个外设都有对应的C文件和头文件,用于控制和配置外设。
这些外设包括GPIO(通用输入输出)、USART(串行通信)、SPI(串行外设接口)等。
3. Inc文件夹:这个文件夹包含了所有的头文件。
头文件是用于声明和定义变量、函数和数据结构的文件。
每个源文件都应该包含所需的头文件。
4. Src文件夹:这个文件夹包含了所有的源文件。
源文件包含了实际的代码和功能的实现。
这些文件可以包括主函数、外设初始化函数、中断处理函数等。
5. Middlewares文件夹:这个文件夹包含了一些中间件(middleware),用于简化开发过程和提供一些高级功能。
这些中间件可以包括操作系统、文件系统、图形库等。
6. Libraries文件夹:这个文件夹包含了一些标准的STM32库文件,用于提供一些常用的函数和方法。
这些库文件可以包括数学函数、字符串处理函数、操作系统函数等。
7. Tools文件夹:这个文件夹包含了一些用于开发和调试的工具。
这些工具可以包括编译器、调试器、仿真器等。
以上是一个基本的文件结构示例,实际情况中可能会有一些变化和定制。
根据项目的需求,开发者可以在文件夹中添加其他文件夹,例如Tests文件夹用于存放测试代码,Docs文件夹用于存放文档等。
通过使用一个清晰而有组织的文件结构,开发者可以更容易地理解和维护代码。
STM32的启动
STM32的启动1、启动⽂件简介 启动⽂件由汇编编写,是系统上电复位后第⼀个执⾏的程序。
主要做了以下⼯作: (1)初始化堆栈指针 MSP=_initial_sp (2)初始化 PC 指针=Reset_Handler (3)初始化中断向量表 (4)配置系统时钟 (5)调⽤ C 库函数_main 初始化⽤户堆栈,从⽽最终调⽤ main 函数去到 C 的世界2、STM32的启动流程 下⾯这段话引⽤⾃《CM3 权威指南 CnR2》—复位序列, CM4 的复位序列跟 CM3 ⼀样。
在离开复位状态后, CM3 做的第⼀件事就是读取下列两个 32 位整数的值: (1)从地址 0x0000,0000(FLASH 的地址 0x08000000,因为STM32设计的Flash起始地址是在0x0800 0000开始的)处取出 MSP 的初始值。
(2)从地址 0x0000,0004(FLASH 的地址 0x08000004,因为STM32设计的Flash起始地址是在0x0800 0000开始的)处取出 PC 的初始值——这个值是复位向量, LSB 必须是1,然后从这个值所对应的地址处取值。
请注意,这与传统的 ARM 架构不同——其实也和绝⼤多数的其它单⽚机不同。
传统的 ARM 架构总是从 0 地址开始执⾏第⼀条指令。
它们的 0 地址处总是⼀条跳转指令。
在CM3 中,在 0 地址处提供 MSP 的初始值,然后紧跟着就是向量表。
向量表中的数值是 32位的地址,⽽不是跳转指令。
向量表的第⼀个条⽬指向复位后应执⾏的第⼀条指令,就是我们刚刚分析的 Reset_Handler 这个函数。
初始化 MSP 和 PC 的⼀个范例 因为 CM3 使⽤的是向下⽣长的满栈,所以 MSP 的初始值必须是堆栈内存的末地址加1。
举例来说,如果我们的堆栈区域在 0x20007C00-0x20007FFF 之间,那么 MSP 的初始值就必须是 0x20008000。
STM32启动文件的中文解释
**这里是STM32比较重要的头文件我愛你的吻123原創講解QQ:1746430162****************************************************************************** * @file stm32f10x.h ST 标准的头文件* @author MCD Application Team 微控制器开发小组。
* @version V3.5.0 版本* @date 11-March-2011 2011年3月11* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File.(CMSIS:Cortex Microcontroller Software Interface Standard) 是Cortex-M 处理器系列的与供应商无关的硬件抽象层。
* This file contains all the peripheral register's definitions, bits* definitions and memory mapping for STM32F10x Connectivity line,* High density, High density value line, Medium density,* Medium density Value line, Low density, Low density Value line* and XL-density devices.* 这个文件包含了芯片STM32F10X(接口增强型)内部的寄存器定义,位定义,内存地址变换定义,还有一些相应的高密度,低密度产品线的设备。
* The file is the unique include file that the application programmer* is using in the C source code, usually in main.c. This file contains:* - Configuration section that allows to select:* - The device used in the target application* - To use or not the peripherals drivers in application code(i.e.* code will be based on direct access to peripherals registers* rather than drivers API), this option is controlled by* "#define USE_STDPERIPH_DRIVER"* - To change few application-specific parameters such as the HSE* crystal frequency* - Data structures and the address mapping for all peripherals* - Peripheral's registers declarations and bits definition* - Macros to access peripheral registers hardware*这个文件在应用程序中是至关重要的头文件,它是用C代码编写而成。
STM32启动文件详解及SystemInit函数分析
1/6/afeibfp/archive/2013/01/08/2850408.html <2013年1月>日一二三四五六303112345678910111213141516171819202122232425262728293031123456789昵称:afeibfp 园龄:2年5个月粉丝:0关注:0+加关注搜索找找看 谷歌搜索常用链接我的随笔我的评论我的参与最新评论我的标签更多链接我的标签51单片机(2)多字节除法(2)汇编(2)随笔分类(2)转发(2)随笔档案(16)2013年1月 (14)2011年9月 (2)最新评论1. Re:014:针对mdk 中STM32程序无法使用printf ,产生停留BEAB BKPT 0xAB 处问题的解决(转)不点那个MiclroLIB 就行了--blakeliu阅读排行榜1. 001:无符号双字节除以单字节(51单片机,汇编源码)(418)2. 004:STM32启动文件详解及SystemInit 函数分析(转)(389)3. 014:针对mdk 中STM32程序无法使用printf ,产生停留BE AB BKPT 0xAB 处问题的解决(转)(312)4. 010:请教STM32用JLINK V8 SWD 输出调试信息到ITM V iewer 的问题(转)(208)5. 009:semihost/ITM 机制浅析以及使用JLINK 通过ITM 调试stm32单片机(转)(190)评论排行榜1. 014:针对mdk 中STM32程序无法使用printf ,产生停留BE AB BKPT 0xAB 处问题的解决(转)(1)2. 013:ADS semihosting 与硬件重定向(转)(0)3. 012:Keil 调试技术(转)(0)4. 011:Nuvoton(新唐) Cort ex M0 使用semihost 输入输出办法(转)(0)5. 010:请教STM32用JLINK V8 SWD 输出调试信息到ITM V iewer 的问题(转)(0)推荐排行榜博客园首页新随笔联系管理订阅 随笔- 16 文章- 0 评论- 1afeibfp004:STM32启动文件详解及SystemInit 函数分析(转)1 ;先在R A M 中分配系统使用的栈,R A M 的起始地址为0x 2000_00002 ;然后在R A M 中分配变量使用的堆3 ;然后在C O D E 区(f l a s h )分配中断向量表,f l a s h 的起始地址为0x 0800_0000,该中断向量表就从这个起始地址开始分配4 ;分配完成后,再定义和实现相应的中断函数,5 ;所有的中断函数全部带有[w e a k ]特性,即弱定义,如果编译器发现在别处文件中定义了同名函数,在链接时用别处的地址进行链接。
stm32启动文件详解
STM32启动文件详解一、启动文件的作用1.初始化堆栈指针 SP;2.初始化程序计数器指针 PC;3.设置堆、栈的大小;4.设置异常向量表的入口地址;5.配置外部 SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM);6.设置 C库的分支入口__main(最终用来调用 main函数);7.在 3.5版的启动文件还调用了在 system_stm32f10x.c文件中的SystemIni()函数配置系统时钟。
二、汇编指令三、启动代码1.stack ----- 栈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放置,表示栈的结束地址,栈是从高往低生长,结束地址就是栈顶地址。
2.heap ----- 堆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堆的结束地址。
stm32启动文件详解
STM32启动文件详解一、启动文件的作用1. 初始化堆栈指针SP;2. 初始化程序计数器指针PC;3. 设置堆、栈的大小;4. 设置异常向量表的入口地址;5. 配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM);6. 设置C库的分支入口_main (最终用来调用main函数);7. 在3.5版的启动文件还调用了在system_stm32f10x.c文件中的SystemIni()函数配置系统时钟。
、汇编指令;栈的结束地址(栈顶地址)分配名为STACK 不初始化,可读可写,8 (2A 3 )字节对齐的1KB 空间。
栈:局部变量,函数形参等。
栈的大小不能超过内部SRAM 大小。
AREA:汇编一个新的代码段或者数据段。
STACK 段名,任意命名;NOINIT表示不初始化;READWRITEM 读可写;ALIGN=3 (2八3= 8字节对齐)。
__initial_sp 紧挨了 SPACER 置,表示栈的结束地址,栈是从高往低生长,结 束地址就是栈顶地址。
2. heap —— 堆Heap_SizeEQU 0x00000200;堆的大小(512Bytes )AREA HEAP, NOINIT, READWRITE,ALIGN=3;堆的起始地址;堆的结束地址三、启动代码 l.stackStackSizeEQU0x00000400;栈的大小AREASTACK, NOINIT, READWRITE,ALIGN=3 StackMem SPACEStack_Size ;分配栈空间__initial_sp__heap_base Heap_MemSPACE Heap_Size ;分配堆空间__heap_limit分配名为HEAP,不初始化,可读可写,8 (2A3 )字节对齐的512字节空间。
__heap_base堆的起始地址,_heap_limit堆的结束地址。
堆由低向高生长。
动态分配内存用到堆。
STM32的启动文件与BootLoader
STM32的启动⽂件与BootLoader
1 启动设置
BOOT1:x BOOT0:0 使⽤JTAG下载程序;(不需要使⽤BootLoader)
BOOT1:0 BOOT0:1 使⽤串⼝下载程序;(需要使⽤BootLoader引导从串⼝过来的数据)
BOOT1:1 BOOT0:1 从内部SRAM中启动。
2 start_stm32fxxxxx.s⽂件分析
1)分配栈的⼤⼩
2)分配堆的⼤⼩
3)初始化中断向量表(依次存放中断服务⼊⼝函数的地址)
DCD:分配⼀个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。
在向量表中,DCD 分配了⼀堆内存,并且以ESR 的⼊⼝地址初始化它们。
4)执⾏复位中断
系统初始化(在这⾥初始化系统时钟)
跳转⾄main()函数
3 关于堆栈的⽣长⽅向
堆是向上⽣长,栈是向下⽣长。
4 查看map⽂件
在map⽂件中可以看到内存分布情况
参考
STM32的map⽂件学习笔记
STM32的启动⽂件详解
STM32 Bootloader与启动分析
如何判断栈、堆的增长⽅向?。
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开发中startup.s文件中常见的命令功能
stm32开发中startup.s⽂件中常见的命令功能由于C的普及以及编译器的发展,越来越多的软件⼯程师在编程时很少有机会接触到汇编语⾔。
在ARM的开发中,我们不可避免的会遇到启动⽂件的编写,在KEIL环境中⼀般采⽤了startup.s的⽂件作为启动代码,很多⼯程师⼀见到这个⽂件就很头痛,这⾥我简单地介绍⼀些常见的汇编指令、伪指令,希望对⼤家有所帮助,下次见到.s⽂件时也不会觉得那么难以接受。
提醒下⼤家,在汇编代码中是不区分⼤⼩写的,这点和C语⾔不太⼀样,所以⼀下的指令在很多时候是⽤⼩写的。
不过我个⼈意见是汇编最好全部⽤⼤写字母,这样⽅便阅读。
本笔记有很多是基础的知识,适合⼀些初级的⼯程师学习。
很多指令和语法是汇编通⽤的,如果你耐⼼的全部看完,相信⼀定对你的开发⼯作有帮助。
1. REQUIRE8和PRESERVE8在定义堆栈的时候,我们经常会看到REQUIRE8和PRESERVE8伪指令,这两个指令是告诉编译器保证8字节对齐。
因为ARM的编译器默认是4字节对齐的,⽽在堆栈的操作中很多时候我们会⽤到LDRD和STRD这样的双字传送指令,所以这⾥的存储器就要求要8字节对齐。
实际操作中,REQUIRE8和PRESERVE8并不会直接完成对齐的操作,⽽只是更改编译器中的编译属性,真正的对齐操作是由ALIGN来完成的。
2. AREAAREA 伪指令⽤来定义⼀个存储器的区域,⼀般我们把它叫做段(sector).其语法格式如下:AREA 段名称属性1,属性2, ……需要注意的是如果段名称是由数字或者特殊字符开头,则需要⽤||把段名称括起来。
例如 |3_Code| 或者|.code|属性部分⽤来表⽰该存储器段的相关属性,多个属性之间⽤逗号隔开,常⽤的属性如下:- NOINIT : ⾮初始化- CODE :⽤于定义代码段,定义了该属性则默认READONLY属性- DATA : ⽤于定义数据段,定义了该属性则默认READWRITE属性- READWRITE/READONLY : ⽤来标⽰本段是只读还是可读可写- ALIGN :存储器的访问的对齐, ⼀般定义为ALIGN = N,其中N表⽰对齐的字数,例如:ALIGN = 2表⽰对齐⽅式是2的2次⽅,即4字节对齐ALIGN = 3 标⽰对齐⽅式是2的3次⽅, 即8字节对齐- COMMON :该属性⽤来定义⼀个通⽤的存储区,不包含任何代码和数据。
stm32f103ze的启动文件
stm32f103ze的启动文件
启动文件名为“startupstm32f10xhd.s”的文件,它里边使用汇编语言写好了基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起C语言的运行环境,所以我们把这个文件称为启动文件。
startupstm32f10xhd.s文件由官方提供,一般有需要也是在官方的基础上修改,不会自己完全重写。
该文件从ST固件库里面找到,找到该文件后把启动文件添加到工程里面即可。
不同型号的芯片以及不同编译环境下使用的汇编文件是不一样的,但功能相同。
STM32标准外设库可以到ST公司的官方网站下载,需要验证邮箱。
1、htmresc文件夹内是官方Logo图片,可以忽略。
2、Libraries文件夹下面有CMSIS和STM32F4xxStdPeriphDriver 两个目录,这两个目录包
含固件库核心的所有子文件夹和文件,是代码移植的重头戏。
CMSIS 文件夹存放的是符合CMSIS规范的一些文件,Driver文件夹下是STM32F4标准外设固件库源码文件和对应的头文件,说白了就是将寄存器封装好的函数接口。
3、Project文件夹下面有STM32F4xxStdPeriphExamples和
STM32F4xxStdPeriphTemplate两个文件夹,Examples文件夹下是固件示例源码,Template文件夹下是工程模板。
这些源码的学习对以后的开发学习非常重要。
4、Utilities文件夹下就是官方评估板的一些对应源码,可以忽略不看。
5、根目录中还有一个固件库的帮助文档stm32f4xxdspstdperiphlibum.chm文件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32启动文件详解(2012-07-28 11:22:34)转载▼分类:STM32标签: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.sstartup_stm32f10x_md.sstartup_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);* -设置初始程序计数器(PC)为复位向量,并在执行main函数前初始化系统时钟;* -设置向量表入口为异常事件的入口地址;* -复位之后处理器为线程模式,优先级为特权级,堆栈设置为MSP主堆栈;* <<< Use Configuration Wizard in Context Menu >>>; 首先对栈和堆的大小进行定义,并在代码区的起始处建立中断向量表,其第一个表项是栈; 顶地址,第二个表项是复位中断服务入口地址。
然后在复位中断服务程序中跳转??C/C++标; 准实时库的__main函数。
假设STM32被设置为从内部FLASH启动中断向量表起始地位为0x8000000,; 则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处。
当STM32遇; 到复位信号后,则从0x80000004处取出复位中断服务入口地址继而执行复位中断服务程序,; 然后跳转__main函数,最后来到C的世界。
; DCD指令:作用是开辟一段空间,其意义等价于C语言中的地址符“&”。
开始建立的中断向量; 表则类似于使用C语.其每一个成员都是一个函数指针,分别指向各个中断服务函数;伪指令AREA,表示开辟一段大小为Stack_Size的内存空间作为栈,段名是STACK,可读可写。
;NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0;****************************************************************************** *; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.;****************************************************************************** *; Amount of memory (in bytes) allocated for Stack; Tailor this value to your application needs; <h> Stack Configuration; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Stack_Size EQU 0x00000400 ;定义栈大小1024BAREA STACK, NOINIT, READWRITE, ALIGN=3;###AREA 命令指示汇编器汇编一个新的代码段或数据段。
;段是独立的、指定的、不可见的代码或数据块,它们由链接器处理.;段是独立的、命名的、不可分割的代码或数据序列。
一个代码段是生成一个应用程序的最低要求;默认情况下,ELF 段在四字节边界上对齐。
expression 可以拥有0 到31 的任何整数。
;段在2expression 字节边界上对齐Stack_Mem SPACE Stack_Size ;### ;分配连续Stack_Size 字节的存储单元并初始化为0。
;堆栈段,未初始化,允许读写,8字节边界对齐;说明: Cortex-M3的指令地址要求是字边界对齐(4字节);但是代码段是8字节边界对齐的__initial_sp ;###初始化堆栈指,标号__initial_sp表示指向堆栈顶. ; ###此处有个一个问题讨论,关于栈顶在RAM中所处位置问题,很多初学者一直以为是编译器特意放在HEAP段之后是有意为之,并且认为这样可以利用heap未分配空间来防止未知的栈溢出问题; 这种理解是错误的,链接器并不会为栈的位置做特殊的处理,而且这样做也并不会利用heap段,在此文件的最后对堆栈的初始化代码中可以看出他们是两个互相独立的数据区。
此处出现的现; 象是因为MDK按数据段的字母顺序链接数据段的地址的,所以此处造成了堆的地址在栈的前面的假象,不要窃以为是有某种特殊的约定。
; <h> Heap Configuration; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Heap_Size EQU 0x00000200 ;定义堆的大小AREA HEAP, NOINIT, READWRITE, ALIGN=3 ;堆段,malloc用的地方,不一定连续空间,未初始化,允许读写,堆数据段8字节边界对齐__heap_base ;表示堆空间起始地址Heap_Mem SPACE Heap_Size ;分配堆空间__heap_limit ;表示堆空间结束地址与__heap_base配合限制堆的大小PRESERVE8 ;命令指定当前文件保持栈的八字节对齐THUMB ;指令集,THUMB 必须位于使用新语法的任何Thumb代码之前; EXPORT 命令声明一个符号,可由链接器用于解释各个目标和库文件中的符号引用,相当于声明了一个全局变量。
GLOBAL 于EXPORT相同。
; 以下为向量表,在复位时被映射到FLASH的0地址; Vector Table Mapped to Address 0 at Reset;实际上是在CODE区(假设STM32从FLASH启动,则此中断向量表起始地址即为0x8000000)AREA RESET, DATA, READONLY ;定义一块数据段,只可读,段名字是RESET,复位段,只包含数据,只读EXPORT __Vectors ;标号输出,中断向量表开始;EXPORT在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用EXPORT __Vectors_End ;在程序中声明一个全局标号__Vectors_EndEXPORT __Vectors_Size ;在程序中声明一个全局号__Vectors_Size,中断向量表大小; DCD 命令分配一个或多个字的存储器,在四个字节的边界上对齐,并定义存储器的运行时初值。
__Vectors ;建立中断表DCD __initial_sp ; Top of Stack 栈顶指针,被放在向量表的开始,FLASH的0地址,复位后首先装载栈顶指针DCD Reset_Handler ; Reset Handler 复位异常,装载完栈顶后,第一个执行的,并且不返回。