-------- 转载请注明出处
文中使用的是nuttx-7.17
Nuttx系统编译(主要针对arm体系结构 ):
编译离不开工具链,而arm工具链是在各体系结构下的Toolchain.defs文件中定义的,arm7/9在nuttx\arch\arm\src\arm文件中,Cortex-M3/M4/M7在nuttx\arch\arm\src\armv7-m文件中,Cortex-M0在nuttx\arch\arm\src\armv6-m文件中。
而编译器选择相关的配置在nuttx\configs\xxx\nsh目录的defconfig文件中定义,同时这个文件会被重命名为.config和该目录下的Make.defs、setenv.sh文件一起复制到根目录下。这一步可以通过在nuttx\tool中执行 ./configure.sh /来完成,其中就是nuttx\configs中的目录名,而是包含上述三个文件的目录。
CONFIG_HOST_LINUX=y 定义主机环境
CONFIG_ARCH_ARM=y 定义开发板架构
CONFIG_ARCH_CHIP_STM32=y 定义芯片厂商
CONFIG_ARCH_CORTEXM3=y 定义芯片内核
CONFIG_ARCH_FAMILY="armv7-m" 定义芯片的体系结构
CONFIG_ARM_TOOLCHAIN_GNU=y
CONFIG_ARMXXX_TOOLCHAIN?_XXX定义使用的工具链:
CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y : NuttX buildroot under Linux or Cygwin
(default)
CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL=y : Generic GCC ARM EABI toolchain for
Linux
CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : Generic GCC ARM EABI toolchain for
Windows
以上这些宏定义都辅助Toolchain.defs文件来判断具体使用的交叉工具链。
总之,开始编译前nuttx\configs\xxx\nsh目录中Make.defs、setenv.sh文件被复制到根目录下。
setenv.sh文件会将编译工具目录加到系统环境变量中。
Make.defs指定了编译相关的选项,同时也指定了链接脚本的路径,该脚本的主要目的是指定了如何把输入文件中的节(sections)映射到输出文件中,并控制输出文件的存储布局。这里的输出文件可以认为就是bin文件。
deconfig会重命名为.config文件复制到根目录,编译过程中会根据该文件自动生成nuttx\include\nuttx目录中的config.h文件,该文件中定义了各种宏是系统编译的基础。
NuttX 启动流程
本文以stm32的cm3内核为例介绍,cortex-m3内核在上电后,首先会把中断向量表中偏移地址0处的值赋给SP指针,然后把偏移地址04地址(即Reset vector)的值赋给PC进入该函数开始执行。这里用到偏移地址是因为CM3的中断向量表基址是可以通过NVIC中的一个寄存器,称为“向量表偏移寄存器”(0xE000_ED08)来配置的。
要追踪系统的启动流程就必须知道程序的入口,而要知道程序入口只要找到链接脚本就可以,链接脚本目录是通过Make.defs中的变量ARCHSCRIPT指定的即在目录nuttx\configs\XXX\scripts中,
-
.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
对于
CM3核该文件首先加载的是*(.vectors),即中断向量表。该向量表是选择位于nuttx\arch\arm\src\stm32\gnu目录中的stm32_vectors.S中,还是nuttx\arch\arm\src\目录中的up_vectors.c中,这个需要查看nuttx-7.17\arch\arm\src\stm32目录中的Make.defs文件
-
ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
-
HEAD_ASRC =
-
else
-
HEAD_ASRC = stm32_vectors.S
-
endif
-
-
CMN_UASRCS =
-
CMN_UCSRCS =
-
-
CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S
-
CMN_ASRCS += up_testset.S vfork.S
-
-
CMN_CSRCS = up_assert.c up_blocktask.c up_copyfullstate.c
-
CMN_CSRCS += up_createstack.c up_mdelay.c up_udelay.c up_exit.c
-
CMN_CSRCS += up_initialize.c up_initialstate.c up_interruptcontext.c
-
CMN_CSRCS += up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c
-
CMN_CSRCS += up_releasepending.c up_releasestack.c up_reprioritizertr.c
-
CMN_CSRCS += up_schedulesigaction.c up_sigdeliver.c up_stackframe.c
-
CMN_CSRCS += up_systemreset.c up_unblocktask.c up_usestack.c up_doirq.c
-
CMN_CSRCS += up_hardfault.c up_svcall.c up_vfork.c
-
-
ifeq ($(CONFIG_ARMV7M_STACKCHECK),y)
-
CMN_CSRCS += up_stackcheck.c
-
endif
-
-
ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
-
ifeq ($(CONFIG_ARMV7M_LAZYFPU),y)
-
CMN_ASRCS += up_lazyexception.S
-
else
-
CMN_ASRCS += up_exception.S
-
endif
-
CMN_CSRCS += up_vectors.c
-
endif
通过该文件可以知道如果在.config文件中没有配置CONFIG_ARMV7M_CMNVECTOR宏就会选择stm32_vectors.S,否则选择up_vectors.c,不论如何配置0x04地址对应的__start函数位于nuttx-7.17\arch\arm\src\stm32目录的stm32_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
-
-
/* Configure the UART so that we can get debug output as soon as possible */
-
-
stm32_clockconfig();
-
stm32_fpuconfig();
-
stm32_lowsetup();
-
stm32_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 = _START_BSS; dest < _END_BSS; )
-
{
-
*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 = _DATA_INIT, dest = _START_DATA; dest < _END_DATA; )
-
{
-
*dest++ = *src++;
-
}
-
-
showprogress('C');
-
-
#ifdef CONFIG_ARMV7M_ITMSYSLOG
-
/* Perform ARMv7-M ITM SYSLOG initialization */
-
-
itm_syslog_initialize();
-
#endif
-
-
/* Perform early serial initialization */
-
-
#ifdef USE_EARLYSERIALINIT
-
up_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
-
stm32_userspace();
-
showprogress('E');
-
#endif
-
-
/* Initialize onboard resources */
-
-
stm32_boardinitialize();
-
showprogress('F');
-
-
/* Then start NuttX */
-
-
showprogress('\r');
-
showprogress('\n');
-
-
#ifdef CONFIG_STACK_COLORATION
-
/* Set the IDLE stack to the coloration value and jump into os_start() */
-
-
go_os_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE);
-
#else
-
/* Call os_start() */
-
-
os_start();
-
-
/* Shoulnd't get here */
-
-
for (; ; );
-
#endif
-
}
完成一系列初始化后调用nuttx\sched\init目录os_start.c中的os_start()函数,进入nutxx内核初始化和启动过程中。
阅读(4197) | 评论(0) | 转发(0) |