PX4 FMU启动流程 1.nsh
PX4 FMU启动流程 1.nsh
PX4 FMU启动流程 1.nsh
-------- 转载请注明出处
-------- 2014-11-27.冷月追风
-------- email:merafour@163.com
现在我们来分析 FMU的启动。
我们应该先去看 “config_px4fmu-v2_default.mk”文件,但是该文件内容太多,不可能直接贴进来,于是我们只好取其中一些比较特殊的数据出来看下。
#
# Use the configuration's ROMFS, copy the px4iov2 firmware into
# the ROMFS if it's available
#
ROMFS_ROOT = $(PX4_BASE)/ROMFS/px4fmu_common
ROMFS_OPTIONAL_FILES = $(PX4_BASE)/Images/px4io-v2_default.bin
define _B
$(strip $1).$(or $(strip $2),SCHED_PRIORITY_DEFAULT).$(or $(strip $3),CONFIG_PTHREAD_STACK_DEFAULT).$(strip $4)
endef
# command priority stack entrypoint
BUILTIN_COMMANDS := \
$(call _B, sercon, , 2048, sercon_main ) \
$(call _B, serdis, , 2048, serdis_main )
说特殊当然主要是相对 IO而言的,在 IO中只有 “MODULES”。
那么这部分信息它究竟有什么作用呢? “BUILTIN_COMMANDS”我们在分析编译脚本的时候就一句碰到过了,跟数组 “g_builtins”相关,直接影响该数组中的变量。而前两者呢从名字和内容上看是跟文件系统目录和 IO固件。
昨天在看 IO的时候,我们找到了一个特殊的符号(宏): “CONFIG_USER_ENTRYPOINT”。为什么特殊呢?因为昨天我们看到这是 “init”进程。 “init”进程是 Nuttx系统的,在系统启动的时候调用, FMU自然也避不开。
bitcraze@bitcraze-vm:~/apm/PX4Firmware$ grep -nr CONFIG_USER_ENTRYPOINT ./
./Build/px4fmu-v1_APM.build/nuttx-export/include/nuttx/init.h:71:EXTERN int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]);
./Build/px4fmu-v1_APM.build/nuttx-export/include/nuttx/config.h:106:#define CONFIG_USER_ENTRYPOINT nsh_main
./Build/px4fmu-v1_APM.build/nuttx-export/include/nuttx/config.h:491: * with existing code, for builds which do not define CONFIG_USER_ENTRYPOINT.
./Build/px4fmu-v1_APM.build/nuttx-export/include/nuttx/config.h:494:#ifndef CONFIG_USER_ENTRYPOINT
./Build/px4fmu-v1_APM.build/nuttx-export/include/nuttx/config.h:495:# define CONFIG_USER_ENTRYPOINT user_start
./Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/init.h:71:EXTERN int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]);
./Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/config.h:118:#define CONFIG_USER_ENTRYPOINT nsh_main
./Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/config.h:521: * with existing code, for builds which do not define CONFIG_USER_ENTRYPOINT.
./Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/config.h:524:#ifndef CONFIG_USER_ENTRYPOINT
./Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/config.h:525:# define CONFIG_USER_ENTRYPOINT user_start
./Build/px4io-v2_default.build/nuttx-export/include/nuttx/init.h:71:EXTERN int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]);
./Build/px4io-v2_default.build/nuttx-export/include/nuttx/config.h:91:#define CONFIG_USER_ENTRYPOINT user_start
./Build/px4io-v2_default.build/nuttx-export/include/nuttx/config.h:391: * with existing code, for builds which do not define CONFIG_USER_ENTRYPOINT.
./Build/px4io-v2_default.build/nuttx-export/include/nuttx/config.h:394:#ifndef CONFIG_USER_ENTRYPOINT
./Build/px4io-v2_default.build/nuttx-export/include/nuttx/config.h:395:# define CONFIG_USER_ENTRYPOINT user_start
./Build/px4io-v1_default.build/nuttx-export/include/nuttx/init.h:71:EXTERN int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]);
./Build/px4io-v1_default.build/nuttx-export/include/nuttx/config.h:89:#define CONFIG_USER_ENTRYPOINT user_start
./Build/px4io-v1_default.build/nuttx-export/include/nuttx/config.h:389: * with existing code, for builds which do not define CONFIG_USER_ENTRYPOINT.
./Build/px4io-v1_default.build/nuttx-export/include/nuttx/config.h:392:#ifndef CONFIG_USER_ENTRYPOINT
./Build/px4io-v1_default.build/nuttx-export/include/nuttx/config.h:393:# define CONFIG_USER_ENTRYPOINT user_start
Binary file ./.git/objects/pack/pack-21197c7a17153b865ac0fe548eb997c747da54a5.pack matches
./nuttx-configs/px4fmu-v1/nsh/defconfig:384:CONFIG_USER_ENTRYPOINT="nsh_main"
./nuttx-configs/px4io-v2/nsh/defconfig:337:CONFIG_USER_ENTRYPOINT="user_start"
./nuttx-configs/px4io-v1/nsh/defconfig:320:CONFIG_USER_ENTRYPOINT="user_start"
./nuttx-configs/px4fmu-v2/nsh/defconfig:424:CONFIG_USER_ENTRYPOINT="nsh_main"
bitcraze@bitcraze-vm:~/apm/PX4Firmware$
昨天我们是直接到 Nuttx源码中去找,今天一不小心跑到 Firmware源码中去找却发现 Firmware源码中的信息更加清晰明了。从中我们看到, FMU中使用的是 "nsh_main",其功能跟 Linux中的 shell一样。既然功能跟 shell一样那显然是由 Nuttx提供的。其实如果我们直接去查看 “firmware.elf.map”文件也可以看到这样一些内容(别再问我 map是什么,打死都不想说):
/home/bitcraze/apm/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/libs/libapps.a(nsh_main.o)
/home/bitcraze/apm/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/libs/libnuttx.a(sched-os_bringup.o) (nsh_main)
/home/bitcraze/apm/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/libs/libapps.a(nsh_init.o)
/home/bitcraze/apm/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/libs/libapps.a(nsh_main.o) (nsh_initialize)
我们看到 “nsh_main”源自 libapps.a库。
这时候我在意识到为什么 Nuttx有两个库,一个是系统即内核,一个是应用。但内核或许是我沿用了 Linux的说法,可能在 Nuttx中并不区分应用跟内核,也就是可能并没有内核空间跟用户空间的概念。根据编译的一些基本规则,从目标文件 “nsh_main.o”来看应该是存在一个名为 “nsh_main.c”的源文件。
bitcraze@bitcraze-vm:~/apm/PX4Firmware$ find ../PX4NuttX/ -name nsh_main.c
../PX4NuttX/apps/examples/nsh/nsh_main.c
bitcraze@bitcraze-vm:~/apm/PX4Firmware$ ls ../PX4NuttX/apps/examples/nsh/
Kconfig Makefile nsh_main.c
bitcraze@bitcraze-vm:~/apm/PX4Firmware$
我们也确实能够找到这样一个源文件。
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
config EXAMPLES_NSH
bool "NuttShell (NSH) example"
default n
select NSH_LIBRARY
select SYSTEM_READLINE
---help---
Enable the NuttShell (NSH) example
if EXAMPLES_NSH
endif
这是 “Kconfig”中的内容, “Kconfig”清楚地告诉我们 nsh就是一个 shell。