1:bootloader有2个概念,一个是由芯片厂固化到芯片flash中指定区域的代码(stm32称这段为系统启动区,tc397称这段空间为BROM,这片区域的代码执行需要硬件boot-pin的配合,以stm23为例boot1-pin= 0;boot0-pin =1之后在芯片复位后就不会从flash开始执行,而是从系统启动区执行这段代码,这段代码具体的作用会有文档说明,但大概就是从指定的串口接收数据放到指定的空间,tc397的BSL ASL同理);另一个是指由用户写的类似上述功能的一段代码,但这个概念下的bootloader的执行不需要boot-pin的配合,即把这个bootloader认为是默认从flash启动执行的一段由用户实现具有特殊功能的用户代码。
2:硬件从哪里启动?
tricore架构:bmhd指定芯片复位后pc的值,假定bmhd中指定复位后pc值是0x80000000,我怎么保证0x80000000里有启动代码呢?答案在ld文件中,ld会合并所有的输入段并将它们放在指定的位置上,ENTRY( )关键字能够保证(内)函数对应的输入段放在所有代码输入段的最前面,可是这个最前面未必就是0x80000000呀?答案在于ld文件中指定了rom段的起始地址和长度,又指定了代码段都放入rom段中,因此代码段中最前面的内容必然放在rom段的开始处。这就实现了芯片复位后能从ENTRY(内)的函数处开始执行第一条指令。
cortext-m架构:是通过中断向量表偏移寄存器内的值去指定芯片复位后的pc值,即硬件自动从(0x08000000+中断向量表偏移寄存器值) 的地址处取出第一个字放入sp中,第二个字放入pc中,通常会将Reset_Handler放在该地址处; 同时中断向量表偏移寄存器的地址是固定的
X86架构:上电后x86CPU自动进入实模式,并从地址0xFFFF0处开始自动执行程序代码,这个地址通常是ROM-BIOS中的地址。PC机的 BIOS将执行某些系统的检测,并从物理地址0处开始初始化中断向量。此后BIOS将可启动设备的第一个扇区的前512字节读入内存绝对地址 0x7C00处,并跳转到这个地址。启动设备通常是软盘。linus 写了一些代码将其命名为bootsect.s,并将其编译生成后的机器码用另一个pc 烧录到软盘第一个扇区的前512字节内。这样通过BIOS就能执行到他写的这段代码,而这段代码是linux系统的开始。
3:早期IBM PC所使用的8088 CPU 外部地址总线是20位的,共可寻址内存(非单指RAM)范围 0-1MB。
0 - 640KB (640KB)是实际所含RAM内存总容量;
640KB - 960KB (320KB)用于显示卡等外设内存的寻址;
960KB - 1024KB (64KB) 用于ROM BIOS存储的寻址。
注意:由于IBM PC 使用独立编制,硬盘存储区地址不直接用于寻址,因此20位地址总线可以挂载容量大于1MB的硬盘;和mcu上采用统一编址的flash不同。
上电后CPU会自动将执行(PC)指针设置成0xFFFF0,该地址正好位于ROM BIOS中。地址0xFFFF0处存放着一条跳转指令,跳转到960KB - 1024KB区域内的某个地址,并开始执行BIOS程序。
4:hex文件和bin文件的关系:参见 深入理解工具链-Hex文件详解_hex文件格式-CSDN博客
1. bin文件只保留了hex文件中数据类型是00的内容,01-05类型的数据丢弃;有效的text段和data段数据都属于00类型数据,都被保存下来。
2. 每行00类型的数据又只保留16B的数据部分,地址信息和校验部分丢弃。
3. bin文件一行是16B,hex文件一行是44B(结尾有换行符)。
4. bin文件中没有烧录地址信息,因此需要烧录软件指定或者由用户的bootloader指定;hex文件包含完整的地址信息。
5. bin文件在处理地址不连续的段时需要pad0至段长,而hex文件则不需要;同时接收bin文件的bootloader因为地址需要人为指定因此无法做到统一。
6. armcc编译器的关键字AREA 等同于 gcc编译器的关键字 .section,都是用来指定一个段
AREA RESET, DATA, READONLY 和 .section .isr_vector,"a",%progbits 都是用来定义段和段的属性;
同时各自也通过自己的方式将这个段放在了hex文件的开头位置。