PX4源代码分析,Nuttx系统启动(转)
(2017-04-01 11:04:56)
标签:
px4pixhawknuttx启动 |
分类: Pixhawk、PX4无人机 |
写在前面
1.1
|
void {
#ifdef
#endif
#ifdef #endif
#ifdef #endif
} |
我们可以先通过注释大概了解这里都做了哪些事情。在这之前还有一个程序在跑:bootloader。这个不是我们今天讨论的话题。在最后我们看到调用了一个os_start()函数也就是接下来系统将启动,对应的源文件是os_start.c:
|
void {
#ifndef #endif
#ifndef #endif #ifdef #endif
#if #endif
#if #endif
#if #if #else #endif #endif
#ifdef
#endif
#if
#endif
#if
#ifdef
#endif
#endif
#ifdef
#endif
#ifdef
#endif
#ifndef
#ifdef
#endif
#endif
#ifndef
#ifdef
#endif
#endif
#ifndef
#ifdef
#endif
#endif
#ifndef
#ifdef
#endif
#endif
#ifndef
#ifdef
#endif
#endif
#if
#ifdef
#endif
#endif #ifdef #if
#endif
#endif
#ifdef
#endif
#ifdef #endif #ifdef #endif
#ifndef
#endif
} |
我们看到这里初始化了各种资源,最后进入了一个空闲任务。而在空闲任务的前面我们看到对其他任务也进行了初始化,这是在os_bringup.c文件中:
|
int {
#if #endif #ifdef
#endif
#ifdef
#ifdef
#ifdef #else #endif
#ifdef
#endif #endif
#if #endif #endif
#ifdef #endif
#ifdef
#else
#endif
#if #endif
} |
这里跟我们关系最大的就是init进程。在Linux中也有init进程,是所有应用程序进程的祖先进程,进程ID为1。这里其实类似。Init进程启动了所有应用程序进程。不过这里需要注意的是CONFIG_USER_ENTRYPOINT是在配置文件中指定的,相当于一个宏:
|
CONFIG_USER_ENTRYPOINT="nsh_main"
int {
#if #endif
#if #endif
#if
#endif
#ifdef
#endif
#ifdef #endif
} |
这里就相当于Linux中启动了shell,然后去执行初始化脚本。
|
int {
#ifdef #endif
#ifdef #endif
} |
在这里实际上nsh_initscript和nsh_session都会去执行命令,但nsh_session从代码上看更像是Linux的命令行参数解析, nsh_initscript回去执行/etc/init.d/rcS脚本。
|
int {
} |
这里我们需要对NSH_INITPATH进行展开:
|
#
# # #
# # # # |
所以到了这里我们需要把目光转向启动脚本。后面我们所需要的很多东西,包括PX4飞控主线程都是在脚本中意命令的方式启动的。所以说如果抛开脚本,单纯看源码是看不出PX4飞控主线程是如何启动的,因为这些个东西根本就不在源码中。
|
int
{
} |
这段代码并不难理解,就是打开了我们的脚本文件,然后逐行读取并解析执行。那显然nsh_parse就是解析这些脚本的关键。
|
int {
#if #endif
} |
需要说明的是这个函数是删减过的,就是说只留下了我最想要看到的部分。nsh_builtin和nsh_execute分别对应两个数组:g_builtins和g_cmdmap。什么区别呢?在我看来这两组命令是可以合并到一起的,但如果真的这样做了会有一个问题,用户扩展不方便。于是对其进行区分。像ls这样的命令不需要用户实现及处理,就作为系统命令在g_cmdmap数组中,而作为用户的应用程序如ArduPilot完全有用户决定,便作为用户命令在g_builtins数组中。对于系统命令我们常用的基本都已经实现,通过特定的宏进行选择编译。而用户命令我们只需按照相应规则编写一个入口函数然并设定堆栈大小然后放到g_builtins数组中即可。
|
set MODE set USB
if then
else
fi echo "[init] looking for microSD..." if mount
-t then
else
fi if [ -f
/fs/microsd/etc/rc then
fi if [ -f /fs/microsd/etc/rc.txt ] then
fi if [ $USB
!= then
else
fi if [ -f /etc/init.d/rc.APM -a $HAVE_MICROSD == 1 -a ! -f /fs/microsd/APM/nostart] then
else
fi |
我们看到先是设置了环境变量,然后打开了RGB灯,就是PX4飞控上的那个三色高亮LED,设置了这几个等如何闪烁。然后挂载SD卡并执行SD卡中的脚本,接下来自动连接USB,最后是执行rc.APM脚本。所以PX4要用的东西基本上都在rc.APM脚本中启动。
|
set deviceA /dev/ttyACM0 if [ -f /fs/microsd/APM ] then
fi if [ -f
/fs/microsd/APM/nostart then
fi if [ -f /bin/reboot ] then
else
fi set sketch NONE
if then fi
set if [ ! -f /bin/ArduPilot ] then
fi
if then
fi if [ -f /bin/lsm303d ] then
else
fi if [ $BOARD == FMUv1 ] then
else fi
if then
else
fi if [ -f
/fs/microsd/APM/mkblctrl then
fi if [ -f /fs/microsd/APM/mkblctrl_+ ] then
fi if [ -f /fs/microsd/APM/mkblctrl_x ] then
fi set HAVE_PX4IO false if px4io start then
else
fi if [ $HAVE_PX4IO == true ] then
else
fi if [ $BOARD == FMUv1 -a $deviceD == /dev/ttyS1 ] then
else
fi echo "Starting APM sensors" if ms5611 start then
else
fi if adc start then
else
fi if [ $BOARD == FMUv1 ] then
else
fi if ets_airspeed start then
fi if meas_airspeed start then
fi if ll40ls start then
fi if mb12xx start then
fi echo "Trying PX4IO board" if mtd start /fs/mtd then
else
fi if mtd readtest /fs/mtd then
else
fi if [ $BOARD == FMUv2 ] then
fi echo Starting ArduPilot $deviceA $deviceC $deviceD if ArduPilot -d $deviceA -d2 $deviceC -d3 $deviceD start then
else
fi echo "rc.APM finished" |
这个脚本比较长。第一句应该是对设备进行重定向,然后对上一次的日志进行备份并创建日志。然后通过lsm303d判断PX4的版本,是V1还是V2。换句话说V1跟V2最大的区别是V2有lsm303d传感器,这是一个地磁传感器,而且内置加计。从这里我们也可以看出相比V1,V2在设计上采用了内置地磁的设计。然后根据硬件版本分别初始化输入输出设备。

加载中…