当前位置: 首页 > 工具软件 > NuttX > 使用案例 >

nuttx-OS启动前的准备工作

司寇烨伟
2023-12-01

程序的基本编译过程为:预处理、编译成汇编语言、汇编成机器指令、链接成可执行文件,链接依赖于链接脚本,使用链接脚本来进行更复杂的地址设置,包括了代码段,数据段,bss段等,nuttx就使用ARCHSCRIPT宏来指定链接文件,下面以nucleo-l432kc为例,进行跟踪。

nuttx/boards/arm/stm32l4/nucleo-l432kc/scripts/l432kc.ld 

MEMORY
{ 
  flash (rx) : ORIGIN = 0x08000000, LENGTH = 256K
  sram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}

OUTPUT_ARCH(arm)
ENTRY(_stext)
SECTIONS
{
    .text : {
        _stext = ABSOLUTE(.);
        *(.vectors)
        *(.text .text.*)
        *(.fixup)
        *(.gnu.warning)
        *(.rodata .rodata.*)
        *(.gnu.linkonce.t.*)
        *(.glue_7)
        *(.glue_7t)
        *(.got)
        *(.gcc_except_table)
        *(.gnu.linkonce.r.*)
        _etext = ABSOLUTE(.);
    } > flash

    .init_section : {
        _sinit = ABSOLUTE(.);
        *(.init_array .init_array.*)
        _einit = ABSOLUTE(.);
    } > flash

    .ARM.extab : {
        *(.ARM.extab*)
    } > flash

    __exidx_start = ABSOLUTE(.);
    .ARM.exidx : {
        *(.ARM.exidx*)
    } > flash
    __exidx_end = ABSOLUTE(.);

    _eronly = ABSOLUTE(.);

    /* The STM32L432KC has 64Kb of SRAM beginning at the following address */

    .data : {
        _sdata = ABSOLUTE(.);
        *(.data .data.*)
        *(.gnu.linkonce.d.*)
        CONSTRUCTORS
        . = ALIGN(4);
        _edata = ABSOLUTE(.);
    } > sram AT > flash

    .bss : {
        _sbss = ABSOLUTE(.);
        *(.bss .bss.*)
        *(.gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN(4);
        _ebss = ABSOLUTE(.);
    } > sram

    /* Stabs debugging sections. */
    .stab 0 : { *(.stab) }
    .stabstr 0 : { *(.stabstr) }
    .stab.excl 0 : { *(.stab.excl) }
    .stab.exclstr 0 : { *(.stab.exclstr) }
    .stab.index 0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }
    .comment 0 : { *(.comment) }
    .debug_abbrev 0 : { *(.debug_abbrev) }
    .debug_info 0 : { *(.debug_info) }
    .debug_line 0 : { *(.debug_line) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    .debug_aranges 0 : { *(.debug_aranges) }
}                                                

stm32l4是基于Armv7E-M架构,nuttx/arch/arm/src/armv7-m/arm_vectors.c

#include "chip.h"
#include "arm_internal.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

#define IDLE_STACK      ((unsigned)&_ebss+CONFIG_IDLETHREAD_STACKSIZE)

#ifndef ARMV7M_PERIPHERAL_INTERRUPTS
#  error ARMV7M_PERIPHERAL_INTERRUPTS must be defined to the number of I/O interrupts to be supported
#endif

/****************************************************************************
 * Public Functions
 ****************************************************************************/

/* Chip-specific entrypoint */

extern void __start(void);

/* Common exception entrypoint */

extern void exception_common(void);

/****************************************************************************
 * Public data
 ****************************************************************************/

/* The v7m vector table consists of an array of function pointers, with the
 * first slot (vector zero) used to hold the initial stack pointer.
 *
 * As all exceptions (interrupts) are routed via exception_common, we just
 * need to fill this array with pointers to it.                                                                                                                                                            
 *
 * Note that the [ ... ] designated initializer is a GCC extension.
 */

unsigned _vectors[] locate_data(".vectors") =
{
  /* Initial stack */

  IDLE_STACK,

  /* Reset exception handler */

  (unsigned)&__start,

  /* Vectors 2 - n point directly at the generic handler */

  [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common
};

make menuconfig中配置CONFIG_IDLETHREAD_STACKSIZE,默认为4096

IDLE_STACK对应占用flash前四个字节,摆放栈起始地址。

复位入口函数__start

中断向量表

复位入口函数定义在:arch/arm/src/stm32l4/stm32l4_start.c 中

void __start(void)
{                                                                                                                                                                                                          
  const uint32_t *src;
  uint32_t *dest;

#ifdef CONFIG_ARMV7M_STACKCHECK
  /* Set the stack limit before we attempt to call any functions */

  __asm__ volatile("sub r10, sp, %0" : : 
                   "r"(CONFIG_IDLETHREAD_STACKSIZE - 64) :); 
#endif

#ifdef CONFIG_STM32L4_SRAM2_INIT
  /* The SRAM2 region is parity checked, but upon power up, it will be in
   * a random state and probably invalid with respect to parity, potentially
   * generating faults if accessed.  If elected, we will write zeros to the
   * memory, forcing the parity to be set to a valid state.
   * NOTE:  this is optional because this may be inappropriate, especially
   * if the memory is being used for it's battery backed purpose.  In that
   * case, the first-time initialization needs to be performed by the board
   * under application-specific circumstances.  On the other hand, if we're
   * using this memory for, say, additional heap space, then this is handy.
   */

  for (dest = (uint32_t *)SRAM2_START; dest < (uint32_t *)SRAM2_END; )
    {   
      *dest++ = 0;
    }   
#endif

  /* Configure the UART so that we can get debug output as soon as possible */

  stm32l4_clockconfig();
  stm32l4_fpuconfig();
  stm32l4_lowsetup();
  stm32l4_gpioinit();
  showprogress('A');

  /* Clear .bss.  We'll do this inline (vs. calling memset) just to be
   * certain that there are no issues with the state of global variables.
   */

  for (dest = &_sbss; dest < &_ebss; )
    {
      *dest++ = 0;
    }

  showprogress('B');

  /* Move the initialized data section from his temporary holding spot in
   * FLASH into the correct place in SRAM.  The correct place in SRAM is
   * give by _sdata and _edata.  The temporary location is in FLASH at the
   * end of all of the other read-only data (.text, .rodata) at _eronly.
   */

  for (src = &_eronly, dest = &_sdata; dest < &_edata; )
    {
      *dest++ = *src++;
    }

  showprogress('C');

  /* Perform early serial initialization */

#ifdef USE_EARLYSERIALINIT
  arm_earlyserialinit();
#endif
  showprogress('D');

  /* For the case of the separate user-/kernel-space build, perform whatever
   * platform specific initialization of the user memory is required.
   * Normally this just means initializing the user space .data and .bss
   * segments.
   */
#ifdef CONFIG_BUILD_PROTECTED
  stm32l4_userspace();
  showprogress('E');
#endif

  /* Initialize onboard resources */

  stm32l4_board_initialize();
  showprogress('F');

  /* Then start NuttX */

  showprogress('\r');
  showprogress('\n');

  nx_start();

  /* Shouldn't get here */

  for (; ; );
}


__start函数包含了板级初始化等相关内容,都是操作系统启动前的准备工作,最后通过nx_start函数,启动nuttx操作系统。

 类似资料: