Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
中断向量表
启动文件
10
stm32启动文件中定义的中断向量表被放在主FLASH的哪个位置?
发布于 2024-04-30 15:36:00 浏览:500
订阅该版
最近在学习stm32的启动流程,发现网上讲的大多比较笼统,看到网上说中断向量表在最开始位置,就是0x08000000,具体为啥在这也没过多讲述,我的问题: 1.为什么中断向量表会被放在0x08000000这个位置?是通过链接文件(.ld)指定的吗? 2.如果是通过链接文件指定的,可以理解为链接文件可以控制下载器吗?链接文件指定下载到哪下载器就会乖乖的把程序下载到那个位置处,是这样吗? 3.如果链接文件可以控制下载器,他们两个是怎么建立联系的?我知道的是,链接文件是一个文件,链接器通过链接文件把所有的目标文件(.o)链接为可执行文件,这么说来,是可执行文件中既包含目标文件又包含函数或者变量的位置信息(链接文件提供),然后下载器边解读可执行文件得到从而下载的位置信息然后边下载吗?是这样吗? 4.据说(__main)函数还具有数据重定位的功能,原因是数据一开始被下载到了主flash(ROM),所以要拷贝到SRAM(RAM)中,这个功能好像也是需要读取链接文件才能正常执行,所以说不光下载器下载时会读取可执行文件中的链接文件部分,运行时程序自己也会读取自己程序中的链接部分,从而实现数据重定位吗? 5.如果问题3和问题4中的假设是正确的,那可执行文件中难道真的存在链接文件相关内容(位置信息)吗?为啥我看网上说可执行文件结构只有stack,heap,bss,data,text段,请问链接文件实在text段里吗?它存在的形式是什么样的?是放在函数或变量名字的前面来指定这个函数或变量应该放在那个位置吗? 6.如果上述理论是对的,那链接文件是不是很重要呢?感觉学懂链接文件很多问题就会恍然大悟了,那为啥很多课程没有过多讲述链接文件的功能及实现呢? 实在搞不懂了,脑子都乱了,请大佬答疑解惑一下🧐
查看更多
聚散无由
2024-05-01
https://jswyll.com/
可以看我写的[程序编译、下载、运行过程分析](https://jswyll.com/note/iap/#1-%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E3%80%81%E4%B8%8B%E8%BD%BD%E3%80%81%E8%BF%90%E8%A1%8C%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90),示例代码在
的STM32F103_test。照着代码,使用AC6编译器,看看map文件可以知道各个部分的程序最终放到了哪里。可以用VS Code(安装扩展:Intel HEX format)打开编译输出的.hex文件看看最终下载到STM32的程序的机器码是怎样的。 1. 芯片制造时就定好了FLASH、RAM等的地址,例如STM32F103系列,查看[Programming Manual RM0056](https://www.st.com/resource/en/datasheet/stm32f103c8.pdf)Memory map。STM32F1可以从用户FLASH(地址0x08000000),SRAM(地址0x20000000),内部固定FLASH的FLASH(地址0x00000000)启动,通过启动时BOOT0、BOOT1引脚的电平控制。一般都是从用户FLASH启动,所以程序会下载到地址0x08000000。对于STM32 HAL库,中断向量表通常在[system_stm32f1xx.c](https://gitee.com/jswyll_com/iap/blob/master/STM32F103_test/Src/system_stm32f1xx.c)文件中的`SCB->VTOR`设置。 2. 流程分析: 1. 编译:展开头文件、宏定义,检查各个源文件的语法,每个.c文件都编译成同名的.o文件 2. 链接:把全部.o拼起来,例如在A文件调用了一个A文件里没有定义的函数,其它文件真的有吗?在MDK中,这个过程生成了.axf文件;在GCC类的编译器中,生成.elf文件。生成的文件包含了函数程序、变量的地址等等信息,类似.map文件所表示的信息。 3. 拷贝:将上一步生成的文件转为机器码(函数、变量、常量等等),一般转成.hex文件,它可以表示烧录到芯片的对应地址的机器码,一个地址存储一个字节。具体点?参考[目标程序](https://jswyll.com/note/iap/#%E7%9B%AE%E6%A0%87%E7%A8%8B%E5%BA%8F)。 4. 下载:下载器及下载器的辅助程序解析上一步的文件所表示的信息,请求将机器码下载(烧录)到指定的地址。芯片本身有那样的接口(调试单元)来接收下载器的信息并执行。 所以,链接文件控制的是链接时把函数、变量等放置的地址。在链接完成时,生成的文件已经记录了函数、变量等的地址,链接文件已经完成它的任务了。链接生成的文件没有链接文件,拷贝时生成的.hex文件跟链接文件更没有(直接的)关系了。下载器按照.hex文件所表示的地址及其数据请求下载到芯片中,如果地址无效、非法,芯片的调试单元会拒绝,下载器的辅助程序报错,不是“乖乖的”。 3. 下载过程可以理解为:下载器(及电脑上下载器的辅助程序)控制芯片进入调试模式;下载器解析文件;下载器读取.hex文件,按一定的大小逐次发起下载请求;下载完成,可以配置下载器复位运行芯片。一般下载到FLASH,断电不丢失。 4. 芯片运行程序,此时跟链接文件没有直接关系了。例如,链接文件使链接时把有初始值的全局变量(.data段)放在一块,并记录起始地址和段的大小(或记录起始地址和结束地址)及其(在RAM中的)目标起始地址,__main函数的程序负责根据这几个信息把FLASH中的.data段拷贝到RAM中。 5. 链接文件在.text段的存在形式?这个用像RT-Thread Studio这类使用GCC编辑器的更好解释些。还是以有初始值的全局变量为例,编译生成的.o会将代码转为对应的标志,例如在代码中定义的`uint32_t g_RW_data = 0x789ABCDE;`会生成一个名称为`.data.g_RW_data`、大小为4字节的标志。GCC链接脚本的相关部分如下: ``` /* FLASH和RAM的地址及其大小 */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K FLASH (rx) : ORIGIN = 0x8010000, LENGTH = 256K } /* Define output sections */ SECTIONS { .data : { _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH } ``` 这段表示.data段存储在FLASH中,运行时需要放在RAM里。根据链接脚本,链接时链接器按照某种规则为.data段安排一个在RAM中的起始地址(RAM里还是其它段嘛)存储在某个标志(假设是_data_start);然后选取所有.data和以.data开头的标志放到.data段里,将.data段在FLASH的起始地址存储在_sdata标志,将末尾地址存在_edata标志。 如果用C语言表示__main函数里关于这部分的程序: ```c #include
memcpy(_data_start, _sdata, _edata - _sdata); ``` 6. MDK中一个常见的链接脚本如下: ``` ; 加载地址(下载地址)及大小 LR_IROM1 0x08000000 0x00004000 { ; 执行地址1及大小 ER_IROM1 0x08000000 0x00004000 { ; 暂且不管 *.o (RESET, +First) ; 暂且不管 *(InRoot$$Sections) ; 只读数据,例如函数、常量 .ANY (+RO) ; 只执行数据,例如函数 .ANY (+XO) } ; 执行地址2及大小 RW_IRAM1 0x20000000 0x00001800 { ; 可读可写的数据(例如有初始值的全局变量+初始值为0的全局变量) .ANY (+RW +ZI) } } ``` 原理是相似的。要先区分stack、heap、bss、data、text、rodata的区别,以及为什么要分成这几大段。简单来说,因为FLASH是(在正常运行时)只读的,所以text和rodata放在FLASH就可以;全局变量data和bss是可读可写的,所在要放在RAM里;但RAM断电数据就丢失了,所以data在下载到FLASH,在每次复位运行时复制到RAM去(什么?你问为什么不造一个即可读写又能断电存储的?因为成本高、体积大...);RAM的内存很有限,而且函数中的局部变量只在调用期间有效,所以用stack(栈,默认是1KB)来实现临时使用和释放,编译器可以自动为我们处理好关于这部分的程序;有些变量只在一定的时间内有效,所以用heap(堆,由程序员手动分配和释放)。 7. 回到第1个问题,看我提供的链接可以看到:0x08000000\~0x08000004存储了栈顶地址;中断向量表存储在0x08000004\~0x080000ec,共58个向量。system_stm32f1xx.c文件中的`SCB->VTOR = 0x08000000`告诉芯片中断向量表的位置(`SCB->VTOR`实际上是栈顶地址的位置)。为什么放在那里?因为一般通过启动时BOOT0、BOOT1引脚的电平控制芯片从0x08000000地址启动,根据ARM Cortex-M3架构,芯片取启动地址的前4个字节作为栈顶地址;然后取启动地址的第二个4字节(0x08000004~0x08000007)向量所指向的地址(0x08000101),跳转到这个地址(Reset_Handler函数)开始执行程序。
4
个回答
默认排序
按发布时间排序
winfeng
认证专家
2024-05-01
这家伙很懒,什么也没写!
12344567
KunYi
2024-05-01
这家伙很懒,什么也没写!
推薦一本書 "程序员的自我修养:链接、装载与库" 雖然不是單片機,但是原理是一致的大同小異
梦笑真美
2024-05-09
这家伙很懒,什么也没写!
详解启动过程
撰写答案
登录
注册新账号
关注者
1
被浏览
500
关于作者
鹿鸣溪
这家伙很懒,什么也没写!
提问
14
回答
1
被采纳
0
关注TA
发私信
相关问题
1
更改向量中断表,0X3FFFFF80代表什么
2
关于重新跳转中断向量表的问题
3
中断向量表设置问题求助
4
GD32 GCC下startup中断向量表有遗漏
5
bootloader app 中断向量偏移问题
6
移植代码时,启动文件的问题。
7
启动文件的格式是什么?
8
为什么RT-Thread的移植要关联那么多的底层呢?
9
cmake 编译 undefined reference to `entry'
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部