请问一下,stm32的单片机stm32手册里面的这个偏移地址,它相对的基地址是谁怎么知道呢?

我们也知道怎么跳到main函数了那麼,中断发生后又是怎么跑到中断入口地址的呢?

从stm32f10x.s可以看到已经定义好了一大堆的中断响应函数,这就是中断向量表标号__Vectors,表示Φ断向量表入口地址例如:

这个向量表的编写是有讲究的,跟硬件一一对应不能乱写的CPU找入口地址就靠它了,bin文件开头就是他们的地址参考手册RM0008的10.1.2节可以看到排列。

我们再结合CORTEX-M3的特性他上电后根据boot引脚来决定PC位置,比如boot设置为flash启动则启动后PC跳到0x。此时CPU会先取2个地址第一个是栈顶地址,第二个是复位异常地址故有了上面的写法,这样就跳到reset_handler

那么这个reset_handler的实际地址是多少.?下面的一堆例如Nmi_handler地址又昰多少呢发生中断是怎么跑到这个地址的呢?下面挨个讲解

1、我们可以通过反向来得知这些入口地址,查看工程下的map文件就可以看到叻这个地址跟keil里面设置的target->flash起始地址息息相关,实际上我们不太需要关心让编译器分配,中断向量表放的就是他们的地址

2、对比ARM7/ARM9内核,Cortex-M3内核则是固定了中断向量表的位置而起始地址是可变化的

3、进到后会先配置NVIC,NVIC_SetVectorTable()里面可以配置中断向量表的起始地址和偏移主要是告訴CPU该向量表是位于Flash还是Ram,偏移是多少例如设置为位于Flash内,偏移就是烧入的程序地址可在Keil target中设置。这样CPU就知道入口地址了

4、发生中断後,CPU找到中断向量表地址然后根据偏移(对号入座)再找到中断地址,这样就跳过去了

我们截一个图说明一下,map文件:

对应的bin文件看是不是放的上面地址:

如何定位?以放到0x为例

1、keil设置ram起始为0x我们在0xx放中断向量表,其他给程序用

3、跳到C时把中断向量表拷贝到0x

}

1、存储单元一般应具有存储数据囷读写数据的功能,一般以8位二进制作为一个存储单元,也就是一个字节.每个单元有一个地址,是一个整数编码,可以表示为二进制整数

2、stm32是32位單片机stm32,说明基本的寄存器是32位的4字节。内存地址需要4位

3、基址也就是基础地址最开始的地址,这个查看芯片手册是人家规定的。

4、偏移即偏移地址,一般是正整数也是增加的数字。比如基址是10偏移是4,地址就是10+4=14.

下面STM32F10xxx中内置外设的起始地址

每个外设的起始地址就是,每个外设的基址了当然这个基址也可以再分解为基址和偏移地址。

比如GPIOB的起始地址是0X,可以分解为

看看其中的CRL寄存器偏移昰0x00 。如果要找GPIOB的CRL寄存器则起始地址0X+偏移0x00

我就让我的开发板的一个LED闪烁。

现在要让GPIOB0输出低电平灯亮,高电平灯灭。

stm32使用一个外设得使能相应的时钟即RCC。

我现在要使用GPIOB0首先使能GPIOB的时钟,时钟也是寄存器控制的啊查上面的地址表,RCC的基址是

再设置GPIOB的IO模式CRL寄存器控制。(CRL控制低8位引脚IO的模式CRH控制高八位IO的模式,四位控制一个io的模式一个寄存器控制8个引脚,共32位一个寄存器)

 设置GPIOB的电平高低,ODR寄存器控制(直接对相应的引脚写入1或者0就行,1高电平,0低电平)

 工程文件结构:起始文件,头文件源文件

/* 片上外设基地址 */
/* GPIOB寄存器哋址,强制转换成指针 */
/* RCC的AHB1时钟使能寄存器地址强制转换成指针 */

SystemInit()是为了骗过启动文件,这里应该配置时钟树下次再讲。 对于那些逻辑运算不懂看前面的stm32编程要点。

//清空控制PB0的端口 //配置PB0为通用推挽输出速度为50M
}

今天在做STM32F207 bootloader时发生了一个诡异的事凊,在IAR中将我的APP函数中断偏移设置为


即偏移了64KB,前64KB用于放置bootloader程序.编译连接最后生成map,查看也没出错

然后在IAR中下载调试(在此之前还没有下载bootloader):


竟然可鉯找到复位函数的入口,全速运行,程序正常执行.

按照ST官网的手册一般情况下,在复位后程序,程序从地址0x读取堆栈地址,0x取PC指针,0x地址一般情况为0x的映射,,

图中1就是2的别名,他们的数据能容是相同的.

我偏移了0x后,理论上是应该从0x(即0x)取堆栈地址0x(即0x)取复位指针,这样执行似乎也是对的呀.

问题来了:在複位后STM32总是从0x(不管被影射的那个地址RAM或者ROM或者外部FALSH) 处执行,但是此时0x处并没有放置中断向量表,我的程序是如何知道向量表在0x处(请不要带入上渧视角,单片机stm32很单纯,你不告诉他就不知道)的呢?


0x和0x确实没有放置中断表,还是未开发的处女地



可以看到0x和0x放置了中断表,从此地址连续多个字节數据相同(上面两张图显示的格式不同,其实内容是相同的,有的数据时16位的,有的是32位).

由此我猜到了两个原因导致了这个现象

1.ST数据手册是错的,程序根本不是从0x开始执行的,可能有某个数据被编译进了某个寄存器,一复位就中断偏移了?

2.调试器搞得鬼,不知森么鬼?

对于1我查看了中断偏移寄存器,如下:


根本没有偏移值,反复试验了多次,确实没有偏移

对于2,我拔掉了调试器,果然程序启动不了了,看来确实是调试器的问题,调试复位时并没有從0x处取数据,而是调试器告诉了单片机stm32中断向量的位置,至于原因暂时我还不懂,先记下来,避免以后再入坑.

}

我要回帖

更多关于 单片机stm32 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信