px4启动流程

PX4操作系统介绍

Nuttx 是一个实时嵌入式操作系统(Embedded RTOS),它很小巧,在微控制器环境中使用。Nuttx完全可扩展,可从从小型(8位)至中型嵌入式(32位)系统。它的设计目的还在于完全符合POSIX标准,完全实时,并完全开放。
从编程的角度来看,Nuttx文件系统看起来与Linux文件系统非常类似,但是,有一个根本的区别:Nuttx根文件系统是一个伪文件系统,而真正的文件系统可以挂载在伪文件系统中;相比之下,在典型的Linux安装中,Linux根文件系统是一个真正的文件系统,伪文件系统挂载在真正的根文件系统中。Nuttx选择的方法,旨在提供从非常小的平台到中等平台等的支持,以便具备更好的可扩展性。

PX4启动流程

px4操作系统nuttx为嵌入式实时操作系统,该系统类linux系统,在unix基础上进行裁剪。初学者对于程序的认知,大多数都是从main()函数开始启动, 实际上我们接触的所有软件程序,使用到的main函数都不是程序实际开始运行的入口,只是用户程序的入口而已。从这个角度而言,PX4的每个任务的main函数都是该任务的入口。这一篇我们分析一下PX4是如何从单片机的启动入口引导到应用任务启动的。
Nuttx操作系统和大多数操作系统相似,都先进入Bootloader启动引导程序,然后再启动fmu和io的操作系统。
PX4的启动流程分为两个部分,第一部分为Nuttx的启动,到加载nsh启动脚本;第二部分为PX4启动脚本的执行,用于启动PX4的所有应用程序。

在这里插入图片描述
一、第一部分Nuttx的启动流程:飞控程序跑起来之前的操作——bootloader
Bootloader是系统上电后启动的一段引导程序,负责引导进入Nuttx系统。

1.1bootloader和Nuttx启动
在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。

Bootloader是嵌入式系统在上电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装在到内存中然后跳转到操作系统所在的空间,启动操作系统运行.

1.2主处理器和协处理器的固件烧写和运行流程
在这里插入图片描述
上图为主处理器和协处理器,固件下载到固件运行的流程图。值得说明的一点是分别给两个处理器下载blootloader以后,主处理器等待下载飞控固件,用地面站通过USB向飞控固件,下载完以后,主处理器的飞控固件启动,这时候通过串口给协处理器下载固件(固件只是下载一次)。这个工作完成之后,主处理器和协处理器同时开始工作。

Firmware\src\modules\px4iofirmware 这里面主要是一些,IO口的操作和安全开关的操作。他会在编译飞控固件的时候,一起被编译成为px4io-v2.bin,放在NUTTX文件系统中,在主处理器运行的时候把这个固件烧写进入协处理器。具体的烧写到单片机的FLASH哪个位置由px4io.cpp文件设置。

从编译后文件.map文件中,可以观察到fmu和io板都是从stm32_start.o文件开始启动。在这里插入图片描述
在这里插入图片描述
对应路径

/platforms/nuttx/NuttX/nuttx/arch/arm/src/stm32/stm32_start.c

void __start(void)描述:This is the reset entry point.就是复位进入的函数,跟32的启动文件进入main函数一个意思。

一开始进行了一系列初始化一系列初始化:

stm32_clockconfig();
stm32_fpuconfig();
stm32_lowsetup();
stm32_gpioinit();
showprogress(‘A’);

跟踪下去函数,会发现会根据不同的宏定义去配置不同的东西,也就是说不同的芯片对应宏定义不同。

以stm32_gpioinit为例子,它进入stm32_gpioremap函数
关于stm32_gpioremap函数的说明是:

Based on configuration within the .config file, this function will remaps positions of alternative functions.

里面有一些宏定义CONFIG_STM32_STM32F10XX来自于nuttx/config.h
config.h说自己是自动生成的,它是根据.config生成的。

这里说一下这个.config文件怎么来的,如果之前做过linux驱动移植,那么这东西一定比较眼熟了,他是通过剪裁得来的,NuttX的所有操作都对标的unix规范。

目前先不纠结这个,知道它是根据不同的.config生成不同的宏定义,在同样的上层文件里配置不同的初始化工作就行,这些初始化的宏定义和初始化函数不会去人为的去改动,统一由nuttx的剪裁来完成,并且自动生成。

继续看void __start(void)
最终由go_nx_start进入nx_start()
函数定义在/platforms/nuttx/NuttX/nuttx/sched/init/nx_start.c
整个系统的启动在这里,启动了内存分配,时间调度,调试中端和log等等
感兴趣区域在最下方:

/_ Then start the other CPUs _/
DEBUGVERIFY(nx_smp_start());/_ Create initial tasks and bring-up the system _/
DEBUGVERIFY(nx_bringup());
nx_smp_start()

启动了所有cpu,PIXHAWK包含一个F4和一个F1,启动操作最终指向了nuttx底层,最终进入:

/_ Create initial tasks and bring-up the system _/
DEBUGVERIFY(nx_bringup());
nx_bringup()

在这个里面进入了 nx_create_initthread();
然后进入nx_start_application();

执行nx_start_application();

 pid = nxtask_create("init", CONFIG_USERMAIN_PRIORITY,
                      CONFIG_USERMAIN_STACKSIZE,
                      (main_t)CONFIG_USER_ENTRYPOINT,
                      (FAR char * const *)NULL);
进入CONFIG_USER_ENTRYPOINT

这个CONFIG_USER_ENTRYPOINT开始就是最关注的应用层启动啦

对于FMU芯片,是nsh_main
对于IO芯片,是user_start

user_start是直接进入了一个死循环for (;😉 {

nsh_main则是进入了进入/platforms/nuttx/NuttX/apps/system/nsh/nsh_main.c中的main函数,然后进入nsh_task()

在这个里面进入nsh_consolemain对应

/platforms/nuttx/NuttX/apps/nshlib/nsh_consolemain.c
执行(void)nsh_initscript(&pstate->cn_vtbl);
跳到ret = nsh_script(vtbl, “init”, NSH_INITPATH);

NSH_INITPATH就是执行脚本的指向了
在这里插入图片描述

PX4启动流程,分为4步:
1.__start:
上电之后程序入口为Firmware/NuttX/nuttx/arch/arm/src/stm32/stm32_start.c中的__start函数,负责stm32芯片的底层初始化,包括是时钟,GPIO等。


2.os_start:
__start函数调用Firmware/NuttX/nuttx/sched/os_start.c中的os_start函数,负责os的底层初始化,包括队列和进程结构等。


3.os_bringup:
os_start函数调用Firmware/NuttX/nuttx/sched/os_bringup.c中的os_bringup函数,负责os基本进程的启动和用户进程的启动。用户启动入口由CONFIG_USER_ENTRYPOINT宏定义进行指定。


4.CONFIG_USER_ENTRYPOINT:
FMU和IO的启动入口不同,分别为:
(1)FMU中CONFIG_USER_ENTRYPOINT宏定义为nsh_main:
[1] 调用nsh_main函数。
[2] nsh_main函数调用Firmware/NuttX/apps/nshlib/nsh_consolemain.c中nsh_consolemain函数。
[3] nsh_consolemain函数调用nsh_initscript函数。
[4] nsh_initscript函数所执行的脚本即为FMU的启动脚本rcS。
[5] rcS脚本中负责挂载Sd卡,启动uorb,加载参数配置文件,启动dataman数据管理,启动各传感器,commander,执行rc.io,执行rc.interface(混控器),执行rc.mc_app(飞控姿态与位置算法)等。

(2)IO中CONFIG_USER_ENTRYPOINT宏定义为user_main:
调用src/modules/px4iofirmware/px4io.c中的user_start函数,负责IO基础环境的初始化,包括PWM,串口,ADC等,最后进入死循环,用于遥控器输入和与FMU通信的内容。
 

在软件层面的详细流程图如下:
在这里插入图片描述
到这里为止即完成了Nuttx系统的启动,程序执行到加载启动脚本,后面即是PX4应用的启动。

    PX4系统层(platforms):除了nuttx系统以外,还有common(中间件);

    中间件主要提供:px4_work_queue(nx_work_queue);uORB;task_manage;驱动等

    PX4板子启动平台公共部分:HRT、console_buffer、crypto、WorkQueue、uorb、log、mavlink_usb_check等。(这部分后续有时间继续深入。)

在这里插入图片描述
启动的过程按图示大致如下(当前版本)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

其中黄色部分为SD卡自定义脚本,蓝色部分为控制相关程序,紫色部分为机型相关自动配置程序,绿色部分为算法程序。

总结主要的点有:

1 程序启动首先Load SD卡,如果SD卡上有自定义启动脚本,就运行SD卡上的脚本,如果没有(默认情况),运行板载自动启动流程
2 机型相关的参数配置通过SYS_AUTOSTART值来定义,通过设置这个值,可以自动载入某一机型对应的参数(如DJI 450,3DR SOLO等)
3 飞行控制相关程序在commander,rc.vehicle_setup,navigator等模块或脚本启动,主要的飞控相关模块有
rc_input - 遥控输入
commander - 命令处理
navigator - 导航
pos_control - 位置控制
att_control - 姿态控制
pwm_out - 电机输出

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值