(rtos nuttx 7.1 stm32 原始碼分析)為什麼 __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......
這裡的 ENTRY(_stext) 定義的程式進入點是 _stext。
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......
這裡的 --entry=__start 在連結時重新指定了程式進入點為 __start。
xxx@xxx-desktop ~ $ readelf -h nuttxELF 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 檔案 nuttx 的檔案頭中可以找到這個程式進入點的地址0x80003d1。
但是,這個程式進入點只對 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>)......使用《NuttX 安裝指令碼》一文中的方法安裝 NuttX 後,反組譯碼檔案 nuttx.S 位於 Linux 目前使用者的主目錄。這裡的 PC 初始值是0x080003d1,指向 __start 函數的起始地址。
順便說一下,向量表中的跳轉地址都是奇數,這是因為 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 */......
這裡的 .word __start 定義了 PC 的初始值。
__start 函數的聲明與定義如下:
nuttx/arch/arm/src/stm32/stm32_vectors.S:
...... .globl __start......
在彙編代碼中聲明了全域符號 __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();......}......在 C 語言代碼中定義了 __start 函數。