[stm32F4,0]zephyr鏡像的入口函數--移置的第一步

目的:將zephyr搬到我的stm32F4 soc上。


移置當然是有個base,所以這裏是stm32f1。第一步當然是cpu上電後執行的第一個命令。

找到鏡像程序被cpu執行的第一條語句,那需要知道鏡像文件的組成結構,

那麼根據根目錄下的Makefile,其指明編譯zephyr鏡像文件需要的鏈接腳本。

ifdef CONFIG_HAVE_CUSTOM_LINKER_SCRIPT
KBUILD_LDS         := $(subst $(DQUOTE),,$(CONFIG_CUSTOM_LINKER_SCRIPT))
else
# Try a board specific linker file
KBUILD_LDS := $(srctree)/boards/$(BOARD_NAME)/linker.ld

# If not available, try an SoC specific linker file
ifeq ($(wildcard $(KBUILD_LDS)),)
KBUILD_LDS         := $(srctree)/arch/$(ARCH)/soc/$(SOC_PATH)/linker.ld
endif
endif

CONFIG_CUSTOM_LINKER_SCRIPT=""中定義的優先級最高,接着使用board目錄下的,最後使用arch目錄下的鏈接文件。

目前stm32f1使用的文件是arch/arm/soc/st_stm32/stm32f1->include/arch/arm/cortex_m/scripts/linker.ld

而實際上知道了這個並沒有什麼用,你不知道鏡像的第一條指令是由那條代碼提供的。

仔細查看根目錄的makefile,可以得到如下的參數設定:

quiet_cmd_create-lnk = LINK    $@
      cmd_create-lnk =								\
(										\
	echo $(LDFLAGS_zephyr); 						\
	echo "$(LINKFLAGPREFIX)-Map=$(O)/$(KERNEL_NAME).map"; 			\
	echo "-L $(objtree)/include/generated";					\
	echo "-u _OffsetAbsSyms -u _ConfigAbsSyms"; 				\
	<span style="color:#003300;"><strong>echo "-e __start"; </strong></span>						 	\
	echo "$(LINKFLAGPREFIX)--start-group";					\
	echo "$(LINKFLAGPREFIX)--whole-archive";				\
	echo "$(KBUILD_ZEPHYR_APP)";						\
	echo "$(LINKFLAGPREFIX)--no-whole-archive";         			\
	echo "$(KBUILD_ZEPHYR_MAIN)";						\
	echo "$(objtree)/arch/$(ARCH)/core/offsets/offsets.o"; 			\
	echo "$(LINKFLAGPREFIX)--end-group"; 					\
	echo "$(LIB_INCLUDE_DIR) $(LINK_LIBS)";					\
) > $@
其中顏色突出的部分即爲鏡像文件的入口點,__start。依稀記得學彙編程序的時候編寫過鏈接腳本的,

而腳本中將指定程序的入口點。根據網絡到的信息可以有以下幾個方式來完成入口點的指定:

1:在連接的時候使用-e參數。
2:在腳本里使用ENTRY
3:如果定義過start這個入口(如果你在彙編裏如果本身就有這個名字叫start的入口,那麼不用特別的聲明也可以)
4:SECTION中.text的第一個入口函數
5:地址爲0的指令
優先級5爲最低。

接下來需要找到這個__start爲何物,這樣才能開始我的stm32f4的zephyr之旅。

x86是從crt0.s這個文件開始的,但是arm沒有這個文件。

搜索整個zephyr源碼,得到如下結果:

./arch/arm/core/cortex_m/vector_table.h:49:GTEXT(__start)
而gcc.h中對GTEXT的定義爲:

#define GTEXT(sym) .global FUNC(sym); .type FUNC(sym), %function
這,這,這聲明瞭__start是個全局的函數,這只是聲明,並沒有找到__start的實現。未找到入口。

接着嘗試ENTRY、start,未找到入口。
.text的第一個函數作爲入口?這在哪兒去撈?

include/toolchain/gcc.h中找找看,看我找到了啥:

#if <span style="color:#000099;">defined(CONFIG_ARM)</span> && defined(_ASMLANGUAGE)
#if defined(CONFIG_ISA_THUMB2)
/* '.syntax unified' is a gcc-ism used in thumb-2 asm files */
<span style="color:#000099;">#define _ASM_FILE_PROLOGUE .text; .syntax unified; .thumb</span>
#elif defined(CONFIG_ISA_THUMB)
#define _ASM_FILE_PROLOGUE .text; .code 16
#else
#define _ASM_FILE_PROLOGUE .text; .code 32
#endif
#endif
_ASM_FILE_PROLOGUE這個便是入口了?! vector_table.S中給出了答案。

/**
 * @file
 * @brief Populated vector table in ROM
 *
 * <span style="color:#000099;">Vector table at the beginning of the image for starting system. The reset
 * vector is the system entry point, ie. the first instruction executed.</span>
 *
 * The table is populated with all the system exception handlers. The NMI vector
 * must be populated with a valid handler since it can happen at any time. The
 * rest should not be triggered until the kernel is ready to handle them.
 */

#define _ASMLANGUAGE
...
#include "vector_table.h"

_ASM_FILE_PROLOGUE
...
    .word __CORTEXM_BOOT_MSP
    <span style="color:#000099;">.word __reset</span>
    .word __nmi
所以zephyr中關於stm32的入口函數便是找到了。接下來便是愉快的玩耍了。
這裏需要說明下,cpu是從第2個word(int32)位置開始執行命令的,其跳過了第一個word。


參考:

http://www.cnblogs.com/cbs-soft/archive/2010/01/08/1642388.html

https://www.zephyrproject.org zephyr是啥。


以下是stm32f1所對應編譯生成的linker.cmd文件的內容:

MEMORY
    {
    FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512*1K
    SRAM (wx) : ORIGIN = 0x20000000, LENGTH = 64 * 1K
    SYSTEM_CONTROL_SPACE (wx) : ORIGIN = 0xE000E000, LENGTH = 4K
    SYSTEM_CONTROL_PERIPH (wx) : ORIGIN = 0x400FE000, LENGTH = 4K
    }
SECTIONS
    {
 _image_rom_start = 0x08000000;
    text :
 {
 KEEP(*(.exc_vector_table))
 KEEP(*(".exc_vector_table.*"))
 KEEP(*(.irq_vector_table))
 KEEP(*(".irq_vector_table.*"))
 KEEP(*(.security_frdm_k64f))
 KEEP(*(".security_frdm_k64f.*"))
 KEEP(*(.isr_irq*))
 KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9])))
 KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9][0-9])))
 KEEP(*(SORT(.gnu.linkonce.isr_irq[0-9][0-9][0-9])))
 _image_text_start = .;
 *(.text)
 *(".text.*")
 *(.gnu.linkonce.t.*)
 } > FLASH
 _image_text_end = .;
 devconfig () :
 {
  __devconfig_start = .;
  *(".devconfig.*")
  KEEP(*(SORT(".devconfig*")))
  __devconfig_end = .;
 } > FLASH
 gpio_compat () :
 {
  __gpio_compat_start = .;
  *(".gpio_compat.*")
  KEEP(*(SORT(".gpio_compat*")))
  __gpio_compat_end = .;
 } > FLASH
 .ARM.exidx :
 {
 __exidx_start = .;
 *(.ARM.exidx* gnu.linkonce.armexidx.*)
 __exidx_end = .;
 } > FLASH
    rodata :
 {
 *(.rodata)
 *(".rodata.*")
 *(.gnu.linkonce.r.*)
 } > FLASH
 _image_rom_end = .;
    __data_rom_start = ALIGN(4);
   
   
    datas : AT(__data_rom_start)
 {
 _image_ram_start = .;
 __data_ram_start = .;
 *(.data)
 *(".data.*")
 } > SRAM
 initlevel () :
 {
  __device_init_start = .; __device_PRIMARY_start = .; KEEP(*(SORT(.init_PRIMARY[0-9]))); KEEP(*(SORT(.init_PRIMARY[1-9][0-9]))); __device_SECONDARY_start = .; KEEP(*(SORT(.init_SECONDARY[0-9]))); KEEP(*(SORT(.init_SECONDARY[1-9][0-9]))); __device_NANOKERNEL_start = .; KEEP(*(SORT(.init_NANOKERNEL[0-9]))); KEEP(*(SORT(.init_NANOKERNEL[1-9][0-9]))); __device_MICROKERNEL_start = .; KEEP(*(SORT(.init_MICROKERNEL[0-9]))); KEEP(*(SORT(.init_MICROKERNEL[1-9][0-9]))); __device_APPLICATION_start = .; KEEP(*(SORT(.init_APPLICATION[0-9]))); KEEP(*(SORT(.init_APPLICATION[1-9][0-9]))); __device_init_end = .;
 } > SRAM
 _k_task_list () :
 {
  _k_task_list_start = .;
   *(._k_task_list.public.*)
   *(._k_task_list.private.*)
  _k_task_list_idle_start = .;
   *(._k_task_list.idle.*)
  KEEP(*(SORT("._k_task_list*")))
  _k_task_list_end = .;
 } > SRAM
 _k_task_ptr () :
 {
  _k_task_ptr_start = .;
   *(._k_task_ptr.public.*)
   *(._k_task_ptr.private.*)
   *(._k_task_ptr.idle.*)
  KEEP(*(SORT("._k_task_ptr*")))
  _k_task_ptr_end = .;
 } > SRAM
 _k_pipe_ptr () :
 {
  _k_pipe_ptr_start = .;
   *(._k_pipe_ptr.public.*)
   *(._k_pipe_ptr.private.*)
  KEEP(*(SORT("._k_pipe_ptr*")))
  _k_pipe_ptr_end = .;
 } > SRAM
 _k_mem_map_ptr () :
 {
  _k_mem_map_ptr_start = .;
   *(._k_mem_map_ptr.public.*)
   *(._k_mem_map_ptr.private.*)
  KEEP(*(SORT("._k_mem_map_ptr*")))
  _k_mem_map_ptr_end = .;
 } > SRAM
 _k_event_list () :
 {
  _k_event_list_start = .;
   *(._k_event_list.event.*)
  KEEP(*(SORT("._k_event_list*")))
  _k_event_list_end = .;
 } > SRAM
    __data_ram_end = .;
    bss (NOLOAD) :
 {
        . = ALIGN(4);
 __bss_start = .;
 *(.bss)
 *(".bss.*")
 *(COMMON)
 __bss_end = ALIGN(4);
 } > SRAM
    noinit (NOLOAD) :
        {
        *(.noinit)
        *(".noinit.*")
        } > SRAM
 _image_ram_end = .;
    _end = .;
    __bss_num_words = (__bss_end - __bss_start) >> 2;
   
   
    .scp (NOLOAD) :
 {
 *(.scp)
 *(".scp.*")
  } > SYSTEM_CONTROL_PERIPH
   
   
    .scs (NOLOAD) :
 {
 *(.scs)
 *(".scs.*")
  } > SYSTEM_CONTROL_SPACE
   
 initlevel_error () :
 {
  KEEP(*(SORT(.init_[_A-Z0-9]*)))
 }
 ASSERT(SIZEOF(initlevel_error) == 0, "Undefined initialization levels used.")
    }
__data_size = (__data_ram_end - __data_ram_start);
__data_num_words = (__data_size + 3) >> 2;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章