[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"; 				\
	echo "-e __start"; 						 	\
	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 defined(CONFIG_ARM) && defined(_ASMLANGUAGE)
#if defined(CONFIG_ISA_THUMB2)
/* '.syntax unified' is a gcc-ism used in thumb-2 asm files */
#define _ASM_FILE_PROLOGUE .text; .syntax unified; .thumb
#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
 *
 * Vector table at the beginning of the image for starting system. The reset
 * vector is the system entry point, ie. the first instruction executed.
 *
 * 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
    .word __reset
    .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;

你可能感兴趣的:(zephyr)