为什么 __start 是处理器执行的第一条指令?
转载请注明出处: http://blog.csdn.net/zhumaill/article/details/23426605在《 NuttX 启动流程》一文中提到, __start 是处理器执行的第一条指令。那么,为什么在 NuttX 中 __start 是处理器执行的第一条指令?为什么我要把 __start 称为“处理器执行的第一条指令”,而不是称为“程序入口点”?
nuttx/configs/shenzhou/scripts/ld.script:
- ......
- OUTPUT_ARCH(arm)
- ENTRY(_stext)
- SECTIONS
- ......
nuttx/arch/arm/src/Makefile:
- ......
- nuttx$(EXEEXT): $(HEAD_OBJ) board/libboard$(LIBEXT)
- $(Q) echo "LD: nuttx"
- $(Q) $(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
- -o $(NUTTX) $(HEAD_OBJ) $(EXTRA_OBJS) \
- --start-group $(LDLIBS) $(EXTRA_LIBS) $(LIBGCC) --end-group
- ......
- xxx@xxx-desktop ~ $ readelf -h nuttx
- ELF Header:
- Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
- Class: ELF32
- Data: 2's complement, little endian
- Version: 1 (current)
- OS/ABI: UNIX - System V
- ABI Version: 0
- Type: EXEC (Executable file)
- Machine: ARM
- Version: 0x1
- Entry point address: 0x80003d1
- Start of program headers: 52 (bytes into file)
- Start of section headers: 145184 (bytes into file)
- Flags: 0x5000202, has entry point, Version5 EABI, soft-float ABI
- Size of this header: 52 (bytes)
- Size of program headers: 32 (bytes)
- Number of program headers: 3
- Size of section headers: 40 (bytes)
- Number of section headers: 18
- Section header string table index: 15
但是,这个程序入口点只对 elf 格式的文件有用,在非 elf 格式的祼机程序中,这个程序入口点不起作用,我们烧写到芯片 flash 中的格式为 .bin 或 .hex 的文件中没有这个程序入口点的定义。把这里的 __start 改成其它函数一样可以正常运行。
根据 cortex-m3 的定义,系统从 flash 启动时,0x08000004中的值就是 PC(程序计数器)的初始值,这才是真正起作用的,它决定了处理器执行的第一条指令。
nuttx.S:
- ......
- 08000000 <_vectors>:
- 8000000: 20005db4 .word 0x20005db4
- 8000004: 080003d1 .word 0x080003d1 <---PC 初始值
- 8000008: 08000159 .word 0x08000159
- ......
- 080003d0 <__start>:
- 80003d0: b510 push {r4, lr} <---处理器执行的第一条指令
- 80003d2: f000 f827 bl 8000424 <stm32_clockconfig>
- 80003d6: f000 f967 bl 80006a8 <stm32_lowsetup>
- 80003de: 4b0c ldr r3, [pc, #48] ; (8000410 <__start+0x40>)
- ......
顺便说一下,向量表中的跳转地址都是奇数,这是因为 cortex-m3 是在Thumb状态下执行的。在向量表以外的地方,32位指令的跳转地址是奇数,16位指令的跳转地址是偶数。但指令的实际地址都是偶数,如0x080003d0。
nuttx/arch/arm/src/stm32/stm32_vectors.S:
- ......
- _vectors:
- /* Processor Exceptions */
- .word IDLE_STACK /* Vector 0: Reset stack pointer */
- .word __start /* Vector 1: Reset vector */
- .word stm32_nmi /* Vector 2: Non-Maskable Interrupt (NMI) */
- .word stm32_hardfault /* Vector 3: Hard fault */
- ......
__start 函数的声明与定义如下:
nuttx/arch/arm/src/stm32/stm32_vectors.S:
- ......
- .globl __start
- ......
nuttx/arch/arm/src/stm32/stm32_start.c:
- ......
- void __start(void)
- {
- const uint32_t *src;
- uint32_t *dest;
- /* Configure the uart so that we can get debug output as soon as possible */
- stm32_clockconfig();
- stm32_fpuconfig();
- stm32_lowsetup();
- ......
- }
- ......