文档视界 最新最全的文档下载
当前位置:文档视界 › stm32启动文件详解

stm32启动文件详解

stm32启动文件详解
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堆的结束地址。堆由低向高生长。动态分配内存用到堆。

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

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

3.向量表

AREA RESET, DATA, READONLY

EXPORT __Vectors

EXPORT __Vectors_End

EXPORT __Vectors_Size

定义一个名为RESET,可读的数据段。并声明 __Vectors、__Vectors_End 和__Vectors_Size 这三个标号可被外部的文件使用。

__Vectors DCD __initial_sp ; Top of Stack

DCD Reset_Handler ; Reset Handler

DCD NMI_Handler ; NMI Handler

DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved

DCD 0 ; Reserved

DCD 0 ; Reserved

DCD 0 ; Reserved

DCD SVC_Handler ; SVCall Handler

DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved

DCD PendSV_Handler ; PendSV Handler

DCD SysTick_Handler ; SysTick Handler

; External Interrupts

DCD WWDG_IRQHandler ; Window Watchdog

.

.

.

__Vectors_End

__Vectors_Size EQU __Vectors_End - __Vectors ;向量表大小

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

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

4.复位程序

AREA |.text|, CODE, READONLY

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

Reset_Handler PROC ;复位子程序开始

EXPORT Reset_Handler [WEAK]

IMPORT __main

IMPORT SystemInit

LDR R0, =SystemInit

BLX R0

LDR R0, =__main

BX R0

ENDP ;子程序结束

复位子程序是系统上电后第一个执行的程序,调用 SystemInit ()函数初始化系统时钟,然后调用 C 库函数_main。

备注:

__main() 和 main()

当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序,即呼叫主应用程序。最简单的一种情况是:

IMPORT main

B main

直接从启动代码跳转到应用程序的主函数入口,当然主函数名字可以由用户随便定义。

在ARM ADS环境中,还另外提供了一套系统级的呼叫机制。

IMPORT __main

B __main

__main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境,最后自动跳转到main()。所以说,前者是库函数,后者就是我们自己编写的main()主函数;

因此我们用的 B __main其实是执行库函数,然后该库函数再调用我们的main() 函数,因此在单步调试时会看到先要跑一段程序(其实是库函数),然后再单步到我们自己的main函数(这个同时也说明如果有B __main 则就对应必须有main函数,否则编译出错),如果我们用 B main来进入我们的主函数的话,那在单

步调试时就看到直接进入到我们自己的main函数了,中间不会看到其他程序;

那么用B __main和用B main 这两这进入我们的main函数方式有什么不同呢?

如果采用前者则会由编译器加入一段"段拷贝"程序,即我们说的从加载域到执行域转化程序;而采用后者就没有这个了,因此如果要进行 "段拷贝"只能自己动手编写程序来实现了,完成段拷贝后就可以进入我们的主函数了,当然这个主函数不一定是叫做main(),可以起个其他好听的名字,这个有别于使用B __main 方式;不管采用哪种方式进入我们的程序,都要有一段"段拷贝"程序,跑完了段拷贝后才能可以进入我们主程序了!(顺便提一下:startup.s这个文件并没有所谓的"段拷贝"功能,再看也无益!)

对含有启动程序来说,"执行地址与加载地址相同"不容易实现:

如果执行地址与加载地址相同那当然不需要做"段拷贝",但是个人理解编译器还会加入"段拷贝"程序(如果用B __main的话),只是因为条件不满足而不执行而已;但是对含有启动程序来说,"执行地址与加载地址相同"就不容易了。因为启动程序是要烧到非易失存储器里,用来在上电执行的,而这个程序必定会有RW段,如果RW放在非易失存储器,如FLASH,那就不好实现RW功能了,因此要给RW移动到能够实现RW功能的存储器,如SRAM等。因此,对含有启动程序来说,"执行地址与加载地址相同"就不容易实现;程序的入口点在C 库中的__main 处,在该点,库代码执行以下操作:

1. 将非零(只读和读写)运行区域从其载入地址复制到运行地址。

2. 清零ZI 区域。

3. 跳转到__rt_entry。

5.终端服务程序

NMI_Handler PROC

EXPORT NMI_Handler [WEAK]

B .

ENDP

HardFault_Handler\

PROC

EXPORT HardFault_Handler [WEAK]

B .

ENDP

MemManage_Handler\

PROC

EXPORT MemManage_Handler [WEAK]

B .

ENDP

此处省略部分……

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

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

B:跳到一个“ .”,表示无限循环。

6.用户堆栈初始化

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

IF :DEF:__MICROLIB

EXPORT __initial_sp

EXPORT __heap_base

EXPORT __heap_limit

ELSE

IMPORT __use_two_region_memory

EXPORT __user_initial_stackheap

;初始化堆&&栈

__user_initial_stackheap

LDR R0, = Heap_Mem

LDR R1, = (Stack_Mem + Stack_Size)

LDR R2, = (Heap_Mem + Heap_Size)

LDR R3, = Stack_Mem

BX LR

ALIGN

ENDIF

END

判断是否定义了__MICROLIB ,如果定义了则赋予标号__initial_sp(栈顶地址)、__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用;如果没有定义(实际的情况就是我们没定义__MICROLIB)则使用默认的 C 库,然后初始化用户堆栈大小,这部分有 C 库函数__main 来完成。

四、附录

;******************** (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-EV AL 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.

;* <<< Use Configuration Wizard in Context Menu >>>

;***************************************************************** **************

; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS

; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SA VE 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

;/*********************栈定义*********************/

; Stack Configuration

; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>

;

Stack_Size EQU 0x00000400 ;EQU伪指令,作用是左边的符号名代表右边的表达式

AREA STACK, NOINIT, READWRITE, ALIGN=3 ;定义栈段:名称为STACK,未初始化,可读写,ELF 的栈段按2^3=8对齐Stack_Mem SPACE Stack_Size ;分配一片连续的存储区域并初始化为0,栈空间:0x400(1024B)个字节

__initial_sp ;栈空间顶地址

;/*********************堆定义*********************/

; Heap Configuration

; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>

;

Heap_Size EQU 0x00000200

AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base ;堆空间起始地

Heap_Mem SPACE Heap_Size ;堆空间:0x200(512B)个字节

__heap_limit ;堆空间结束地址

PRESERVE8

;PRESERVE8 指令指定当前文件保持堆栈八字节对齐

THUMB ;告诉汇编器下面是32位的Thumb指令,如果需要汇编器将插入位以保证对齐; 中断向量表定义

; Vector Table Mapped to Address 0 at Reset

; 实际上是在CODE区(假设STM32从FLASH启动,则此中断向量表起始

地址即为0x08000000)

AREA RESET, DATA, READONLY ;定义一块数据段,只可读,段名字是RESET

EXPORT __Vectors ;EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用

EXPORT __Vectors_End ;在程序中声明一个全局的标号__Vectors_End

EXPORT __Vectors_Size ;在程序中声明一个全局的标号__Vectors_Size

;DCD(DCDU)用于分配一片连续的字存储单元并用指定的数据初始化。

__Vectors DCD __initial_sp ; Top of Stack

;该处物理地址值存储__initial_sp所表示的地址值,即为__Vetors 标号所表示的值

DCD Reset_Handler ; Reset Handler

DCD NMI_Handler ; NMI Handler

DCD HardFault_Handler ; Hard Fault Handler

DCD MemManage_Handler ; MPU Fault Handler

DCD BusFault_Handler ; Bus Fault Handler

DCD UsageFault_Handler ; Usage Fault Handler

DCD 0 ; Reserved

DCD 0 ; Reserved

DCD 0 ; Reserved

DCD 0 ; Reserved

DCD SVC_Handler ; SVCall Handler

DCD DebugMon_Handler ; Debug Monitor Handler

DCD 0 ; Reserved

DCD PendSV_Handler ; PendSV Handler

DCD SysTick_Handler ; SysTick Handler

; External Interrupts ; 以下为外部中断向量表

DCD WWDG_IRQHandler ; Window Watchdog

through EXTI Line detect

DCD TAMPER_IRQHandler ; Tamper

DCD RTC_IRQHandler ; RTC

DCD FLASH_IRQHandler ; Flash

DCD RCC_IRQHandler ; RCC

DCD EXTI0_IRQHandler ; EXTI Line 0

DCD EXTI1_IRQHandler ; EXTI Line 1

DCD EXTI2_IRQHandler ; EXTI Line 2

DCD EXTI3_IRQHandler ; EXTI Line 3

DCD EXTI4_IRQHandler ; EXTI Line 4

DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1

DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2

DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3

DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4

DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5

DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6

DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7

DCD ADC1_2_IRQHandler ; ADC1 & ADC2

DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX

DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0

DCD CAN1_RX1_IRQHandler ; CAN1 RX1

DCD CAN1_SCE_IRQHandler ; CAN1 SCE

DCD EXTI9_5_IRQHandler ; EXTI Line 9..5

DCD TIM1_BRK_IRQHandler ; TIM1 Break

Update

DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation

DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare

DCD TIM2_IRQHandler ; TIM2

DCD TIM3_IRQHandler ; TIM3

DCD TIM4_IRQHandler ; TIM4

DCD I2C1_EV_IRQHandler ; I2C1 Event

DCD I2C1_ER_IRQHandler ; I2C1 Error

DCD I2C2_EV_IRQHandler ; I2C2 Event

DCD I2C2_ER_IRQHandler ; I2C2 Error

DCD SPI1_IRQHandler ; SPI1

DCD SPI2_IRQHandler ; SPI2

DCD USART1_IRQHandler ; USART1

DCD USART2_IRQHandler ; USART2

DCD USART3_IRQHandler ; USART3

DCD EXTI15_10_IRQHandler ; EXTI Line 15..10

DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line

DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend

DCD TIM8_BRK_IRQHandler ; TIM8 Break

DCD TIM8_UP_IRQHandler ; TIM8 Update

DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation

DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare

DCD ADC3_IRQHandler ; ADC3

DCD FSMC_IRQHandler ; FSMC

DCD SDIO_IRQHandler ; SDIO

DCD TIM5_IRQHandler ; TIM5

DCD SPI3_IRQHandler ; SPI3

DCD UART4_IRQHandler ; UART4

DCD UART5_IRQHandler ; UART5

DCD TIM6_IRQHandler ; TIM6

DCD TIM7_IRQHandler ; TIM7

DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1

DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2

DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3

DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5

__Vectors_End ; Vectors结束

__Vectors_Size EQU __Vectors_End - __Vectors ; 得到向量表的大小,304个字节也就是0x130个字节

AREA |.text|, CODE, READONLY ;定义一个代码段,可读,段名字是.text

; |.text| 用于表示由C 编译程序产生的代码段,或用于以某种方式与 C 库关联的代码段;利用PROC、ENDP这一对伪指令标记程序开始、结束,把程序段分为若干

个过程,使程序的结构加清晰

; Reset handler

Reset_Handler PROC

EXPORT Reset_Handler [WEAK] ;WEAK声明其他的同名标号优先于该标号被引用,就是说如果外面声明了的话,调用外面的对应函数

IMPORT __main ;IMPORT:伪指令用于通知编译器要使用的标号在其他的源文件中定义

IMPORT SystemInit

LDR R0, =SystemInit ;系统初始化

BLX R0 ;带链接的跳转,切换指令集,跳到SystemInit

LDR R0, =__main

;__main为运行时库提供的函数;完成堆栈,堆的初始化等工作,

;会调用下面定义的__user_initial_stackheap

BX R0 ;切换指令集,main函数不返回跳到__main,进入C的世界

ENDP ;子程序结束

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler PROC

EXPORT NMI_Handler [WEAK] ;不可屏蔽中断处理函数

B .

ENDP

HardFault_Handler\ ;"\"意为换行

PROC

EXPORT HardFault_Handler [WEAK] ;硬件错误处理函数

B .

ENDP

MemManage_Handler\

PROC

EXPORT MemManage_Handler [WEAK]

B .

ENDP

BusFault_Handler\

PROC

EXPORT BusFault_Handler [WEAK]

B .

ENDP

UsageFault_Handler\

PROC

EXPORT UsageFault_Handler [WEAK]

B .

ENDP

SVC_Handler PROC

EXPORT SVC_Handler [WEAK]

B .

ENDP

DebugMon_Handler\

PROC

EXPORT DebugMon_Handler [WEAK]

B .

ENDP

PendSV_Handler PROC

EXPORT PendSV_Handler [WEAK]

B .

ENDP

SysTick_Handler PROC

EXPORT SysTick_Handler [WEAK]

B .

ENDP

Default_Handler PROC

;输出异常向量表标号,方便外部实现异常的具体功能,[WEAK]是弱定义的意思,如果外部定义了,优先执行外部定义,否则下面的函数定义

EXPORT WWDG_IRQHandler [WEAK]

EXPORT PVD_IRQHandler [WEAK]

EXPORT TAMPER_IRQHandler [WEAK]

EXPORT RTC_IRQHandler [WEAK]

EXPORT FLASH_IRQHandler [WEAK]

EXPORT RCC_IRQHandler [WEAK]

EXPORT EXTI0_IRQHandler [WEAK]

EXPORT EXTI1_IRQHandler [WEAK]

EXPORT EXTI2_IRQHandler [WEAK]

EXPORT EXTI3_IRQHandler [WEAK]

EXPORT EXTI4_IRQHandler [WEAK]

EXPORT DMA1_Channel1_IRQHandler [WEAK]

EXPORT DMA1_Channel2_IRQHandler [WEAK]

EXPORT DMA1_Channel3_IRQHandler [WEAK]

EXPORT DMA1_Channel4_IRQHandler [WEAK]

EXPORT DMA1_Channel5_IRQHandler [WEAK]

EXPORT DMA1_Channel6_IRQHandler [WEAK]

EXPORT DMA1_Channel7_IRQHandler [WEAK]

EXPORT ADC1_2_IRQHandler [WEAK]

EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK]

EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK]

EXPORT CAN1_RX1_IRQHandler [WEAK]

EXPORT CAN1_SCE_IRQHandler [WEAK]

EXPORT EXTI9_5_IRQHandler [WEAK]

EXPORT TIM1_BRK_IRQHandler [WEAK]

EXPORT TIM1_UP_IRQHandler [WEAK]

EXPORT TIM1_TRG_COM_IRQHandler [WEAK]

EXPORT TIM1_CC_IRQHandler [WEAK]

EXPORT TIM2_IRQHandler [WEAK]

EXPORT TIM3_IRQHandler [WEAK]

EXPORT TIM4_IRQHandler [WEAK]

EXPORT I2C1_EV_IRQHandler [WEAK]

EXPORT I2C1_ER_IRQHandler [WEAK]

EXPORT I2C2_EV_IRQHandler [WEAK]

EXPORT I2C2_ER_IRQHandler [WEAK]

EXPORT SPI1_IRQHandler [WEAK]

EXPORT SPI2_IRQHandler [WEAK]

EXPORT USART1_IRQHandler [WEAK]

EXPORT USART2_IRQHandler [WEAK]

EXPORT USART3_IRQHandler [WEAK]

EXPORT EXTI15_10_IRQHandler [WEAK]

EXPORT RTCAlarm_IRQHandler [WEAK]

EXPORT USBWakeUp_IRQHandler [WEAK]

EXPORT TIM8_BRK_IRQHandler [WEAK]

EXPORT TIM8_UP_IRQHandler [WEAK]

EXPORT TIM8_TRG_COM_IRQHandler [WEAK]

EXPORT TIM8_CC_IRQHandler [WEAK]

EXPORT ADC3_IRQHandler [WEAK]

EXPORT FSMC_IRQHandler [WEAK]

EXPORT SDIO_IRQHandler [WEAK]

EXPORT TIM5_IRQHandler [WEAK]

EXPORT SPI3_IRQHandler [WEAK]

EXPORT UART4_IRQHandler [WEAK]

EXPORT UART5_IRQHandler [WEAK]

EXPORT TIM6_IRQHandler [WEAK]

EXPORT TIM7_IRQHandler [WEAK]

EXPORT DMA2_Channel1_IRQHandler [WEAK]

EXPORT DMA2_Channel2_IRQHandler [WEAK]

EXPORT DMA2_Channel3_IRQHandler [WEAK]

EXPORT DMA2_Channel4_5_IRQHandler [WEAK] ;如下只是定义一些空函数

WWDG_IRQHandler

PVD_IRQHandler

TAMPER_IRQHandler

RTC_IRQHandler

FLASH_IRQHandler

RCC_IRQHandler

EXTI0_IRQHandler

EXTI1_IRQHandler

EXTI2_IRQHandler

EXTI3_IRQHandler

EXTI4_IRQHandler

DMA1_Channel1_IRQHandler

DMA1_Channel2_IRQHandler

DMA1_Channel3_IRQHandler

DMA1_Channel4_IRQHandler

DMA1_Channel5_IRQHandler

DMA1_Channel6_IRQHandler

DMA1_Channel7_IRQHandler

ADC1_2_IRQHandler

USB_HP_CAN1_TX_IRQHandler

USB_LP_CAN1_RX0_IRQHandler

CAN1_RX1_IRQHandler

CAN1_SCE_IRQHandler

.

EXTI9_5_IRQHandler

TIM1_BRK_IRQHandler

TIM1_UP_IRQHandler

TIM1_TRG_COM_IRQHandler

TIM1_CC_IRQHandler

TIM2_IRQHandler

TIM3_IRQHandler

TIM4_IRQHandler

I2C1_EV_IRQHandler

I2C1_ER_IRQHandler

I2C2_EV_IRQHandler

I2C2_ER_IRQHandler

SPI1_IRQHandler

SPI2_IRQHandler

USART1_IRQHandler

USART2_IRQHandler

USART3_IRQHandler

EXTI15_10_IRQHandler

RTCAlarm_IRQHandler

USBWakeUp_IRQHandler

TIM8_BRK_IRQHandler

TIM8_UP_IRQHandler

TIM8_TRG_COM_IRQHandler

TIM8_CC_IRQHandler

ADC3_IRQHandler

FSMC_IRQHandler

SDIO_IRQHandler

TIM5_IRQHandler

SPI3_IRQHandler

UART4_IRQHandler

UART5_IRQHandler

TIM6_IRQHandler

TIM7_IRQHandler

DMA2_Channel1_IRQHandler

DMA2_Channel2_IRQHandler

DMA2_Channel3_IRQHandler

DMA2_Channel4_5_IRQHandler

B .

ENDP

ALIGN ;默认是字对齐方式,也说明了代码是4字节对齐的

.

;***************************************************************** **************

; User Stack and Heap initialization 用户堆栈初始化;***************************************************************** **************

IF :DEF:__MICROLIB ;判断是否使用DEF:__MICROLIB(micro lib),如果勾选了micro lib

EXPORT __initial_sp ;将栈顶地址、堆起始地址、堆结束地址赋予全局属性,使外部程序可用

EXPORT __heap_base

EXPORT __heap_limit

ELSE ;如果没有勾选micro lib

IMPORT __use_two_region_memory ;两区堆栈空间,堆和栈有各自的空间地址

EXPORT __user_initial_stackheap

;标号__user_initial_stackheap,表示用户堆栈初始化程序入口

__user_initial_stackheap

;此处是初始化两区的堆栈空间,堆是从由低到高的增长,栈是由高向低生长的,;两个是互相独立的数据段,并不能交叉使用

LDR R0, = Heap_Mem ;保存堆起始地址

LDR R1, = (Stack_Mem + Stack_Size) ;保存栈结束地址

LDR R2, = (Heap_Mem + Heap_Size) ;保存堆结束地址

LDR R3, = Stack_Mem ;保存栈起始地址

BX LR

ALIGN

ENDIF

END ;END命令指示汇编器,已到达一个源文件的末尾

;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

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头文件。

相关文档
相关文档 最新文档