在初写STM32程序时,遇到一个困惑,STM32的Flash在MDK里被设置为起始地址0x0800 0000,而CM3手册规定芯片复位时要从0x0000 0000地址开始取出中断向量 ,那STM32怎么样执行代码呢?地址重映射?或者在0x0000 0000里有对应有实际存储器?
仔细阅读手册,发现这件事是因为STM32设计的Flash起始地址是在0x0800 0000位置开始的。全部代码都只能从这里开始存储。详见STM32 referenc manual手册第54页。
那既然从这里才能存储代码,就必须在MDK里设置Flash地址为0x0800 0000,下面是MDK设置页面,这个应该都看到过。
这样就还有一个问题,理论上,CM3中规定上电后CPU是从0地址开始执行,但是这里中断向量表却被烧写在0x0800 0000地址里,那启动时不就找不到中断向量表了?既然CM3定下的规矩是从0地址启动,SMT32当然不能破坏ARM定下的“规矩”,所以它做了一个启动映射的过程,就是和芯片上总能见到的BOOT0和BOOT1有关了,当选择从主Flash启动模式后,芯片一上电,Flash的0x0800 0000地址被映射到0地址处,不影响CM3内核的读取,所以这时的CM3既可以在0地址处访问中断向量表,也可以在0x0800 0000地址处访问中断向量表,而代码还是在0x0800 0000地址处存储的。这就是最难理解的地方,其实,这是基本上所有ARM芯片采用的启动映射方法。ARM7,ARM9没有内部Flash的通常都是这样做的。这个过程出自STM32 referenc manual手册,里面是有说明的。
还要注意,这个中断向量表是可以在程序中再次被映射的。控制它的就是CM3已经规定的NVIC寄存器SCB->VTOR。在STM32库中给出的启动代码里,startup_stm32f10x_hd.s文件里,第146行,是上电后读取中断向量表中的复位中断位置,并执行复位中断处理代码,代码如下:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
注意复位后第一个被执行的是SystemInit代码,这个代码在库目录下的system_stm32f10x.c文件里,它初始化了时钟,NVIC等一系列操作,这里摘要与中断向量有关的代码:
void SystemInit (void)
{
......
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
可以看出中断向量重映射是一个选择性编译,通常宏定义VECT_TAB_SRAM都没有被定义,所以这里执行结束后,SCB->VTOR就是FLASH_BASE了,值为0x0800 0000。以后CM3再取中断向量里,就会根据SCB->VTOR的设置,从这里取向量执行了。中断向量自此终于转正。
注意这时连__main函数都还没进,看起来中断向量的重映射位置还是够早的。
关键字:STM32 Flash地址 重映射
引用地址:
为什么STM32从Flash地址0x08000000的启动重映射
推荐阅读最新更新时间:2024-03-16 16:01
WS2812灯珠(二)-- STM32 SPI+DMA方式驱动
通过硬件SPI的可以很巧妙的模拟出WS2812的通信时序,用spi的8位数据模拟ws281x的一位数据。 要将系统时钟设置为56M,SPI分频数设置为8,则SPI的通信频率为7M,1s/7M≈143ns 即传输一位数据的时间约为143纳秒(ns) 3*143 = 429ns 5*143 = 715ns 符合WS281X芯片的通信时序。 11111000 high level (十六进制:0XF8)表示WS281X的1码 11100000 low level (十六进制:0XE0)表示WS281X的0码 程序头文件部分: 通过宏的方式定义了灯珠个数和WS281X的0码和1码。 #ifndef __WS2812_
[单片机]
关于STM32中定义数组的问题
功能描述:今天做数据采集,TIM2定时中断20ms采集一次数据,并存入一个数组中。采集完4000个数据后,用串口将这4000个数据依次发送给上位机。 问题描述:DEBUG中对数组指针add watch,发现指针由0增加至1后就不再增加,怀疑TIM2配置有问题,只进了一次中断。于是查了半天关于定时中断配置及清除中断标志位的问题,一直得不到解决。 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM2,TIM_IT_Update); Read_Vel_Puls
[单片机]
STM32之Bit banding
【1】Bit banding即位带操作,STM32的寄存器大都为32位,想要修改某个特定位很困难,位带操作即可解决这个问题,它是将寄存器的特定位和bit-band区域的一个32位地址绑定,也就是一对32,你对这个位带区域的32地址赋值即可控制相应位,可赋值范围是0-2的32次方,但这里赋值0和1便足够。 【2】位带操作是硬件支持还是需要软件设置? 硬件支持,只要你能根据公式找到对应地址,你就可以轻松使用位带操作!这里推荐使用宏定义,可以看这里: https://blog.csdn.net/wofreeo/article/details/82255491 【3】位带操作支持所有寄存器吗? 可见包含了
[单片机]
STM32-(01):认识ARM
ARM(Advanced RISC Machines)是微处理器行业的一家知名企业,设计了大量的高性能、廉价、低耗能的RISC(Reduced Instruction Set Computer,中文是精简指令集计算机)处理器、相关技术及软件。技术具有性能高、成本低和能耗省的特点。适用于多种领域,比如嵌入控制、消费/教育类多媒体、DSP和移动式应用等。 市场份额 手机处理器90%以上的市场份额 上网本处理器30%的市场份额 平板电脑处理器70%的市场份额 基于ARM技术的微处理器应用约占据了32位嵌入式微处理器80%以上的市场份额。 风靡全球的几大原因: 1、功耗低 2、功能强 3、32位指令集 4、合作伙伴众多 5、产品线丰富
[单片机]
基于STM32微处理器的LED光电特性测试装置设计
本文介绍了以基于Cortex-M3内核的32位STM32微处理器为控制核心,外接可控恒流源电路和颜色传感器等部件,组成了简易的LED光电特性测试装置,结构简洁,成本低廉,在LED特性的研究上有较高的实用价值。 1.引言 LED(Light-EMItting-Diode),即发光二极管,以其高效、节能、环保、寿命长、可靠性高等优点正在逐步取代传统的白炽灯、荧光灯,成为新一代照明光源。各国政府均大力扶持白光LED的发展,美、日、欧盟等发达国家皆由政府成立专项积极推行。随着LED应用范围的扩大,用户对产品质量也有了更高的要求,不仅要求其发光亮度和波长等光特性具有一致性,对其正向工作电压和电流等电特性也有严格的要求。因此,研究
[单片机]
STM32上电以后GPIO默认是Floating input
真实案例1: 用开发板STM32的PD13来测试,直接裸露的管脚。 硬件连接我手上发光二极管的比较长的一端也就是 + 极,开发板找GND连接二极管较短的一端也就是 - 极。 #define TSBUZGPIO GPIOD #define TSBUZGPIOPIN GPIO_Pin_13 #define TS_BUZ_H() GPIO_SetBits(TSBUZGPIO ,TSBUZGPIOPIN) #define TS_BUZ_L() GPIO_ResetBits(TSBUZGPIO ,TSBUZGPIOPIN) void TS_Buz_Init(void) { GPIO
[单片机]
STM32的ADC简介_DMA方式的程序设计与实现
ADC简介: ADC(Analog-to-Digital Converter,模/ 数转换器)。也就是将模拟信号转换为数字信号进行处理,在存储或传输时,模数转换器几乎必不可少。 STM32在片上集成的ADC外设非常强大,我使用的奋斗开发板是STM32F103VET6,属于增强型的CPU,它有18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次,连续,扫描或间断模式执行,ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。 ADC工作过程分析: 我们以ADC规则通道转换过程来分析,如上图,所有的器件都是围绕中间的模拟至数字转换器部分展开的。它的左端VREF+,VREF- 等ADC参考电压,ADCx
[单片机]
STM32的IIC库函数使用误区
HAL库里有很多的IIC的库函数,比如 HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t
[单片机]