px4原生源码学习-(4)--Nuttx 实时操作系统编程
来源:互联网 发布:仿阿里云控制台 模板 编辑:程序博客网 时间:2024/06/04 20:05
前面说到px4是基于Nuttx实时操作系统上的,那么px4也是由一些程序所构成,这些程序实现了飞行器的自主控制,只不过这些程序并不是我们通常所见到的单片机或者windows编程那样的程序,但基本编程思想是一致的。我认为如果要看懂px4的源码,那你一定要了解px4的那些程序是怎么编写出来,怎么运行的。所以本章我就大概介绍一下基于Nuttx的编程,我以一个所有编程入门都会介绍的一个程序作为例子。这个程序就是大名鼎鼎的hello world
。
在讲解编程之前,我得交代两个重要的东西,因为这两个东西存在于px4的源码系统当中,非常重要,它们就是make和Cmake。
首先谈谈何为make,熟悉linux系统的朋友对make肯定不陌生,它就是用来读取Makefile文件然后执行,把源码编译链接为可执行程序的一个软件。我们只要把待编译的源码文件和这些源码所需要用到的库写到Makefile文件里面执行make命令就能得到可执行或者可烧录的二进制文件。
那何为Cmake呢?
我们可以这样理解,早期人们直接使用gcc命令编译程序,当源码文件多起了之后,直接用gcc命令过长,链接的库过多,这样就太麻烦了。这时候Make就应运而生,解决了人们对于代码文件过多的困扰。但随着项目越来越大,文件越来越多,人们发现make也捉襟见肘,因为编写Makefile文件又会变得异常复杂。这个时候聪明的程序猿就想能不能有个程序可以帮我写Makefile文件呢?这样就引出了Cmake,当然Cmake不是智能的,它不可能自己去辨别那些是代码,那些是文件,需要什么库。这样就引入了另外一套规则,也引入了一个文件CMakeLists.txt,这个文件就是Cmake程序识别的文件,有这个文件,Cmake就能帮助程序猿自动生成Makefile文件。
总的来说流程应该是这样的:
cmake make
CMakeLists.txt-------------->Makefile---------------------->可执行文件
src,lib
看过px4源码文件的朋友肯定会发现里面有很多CMakeLists.txt文件,事实上整个px4源码的文件都是基于CMakeLists.txt的(Nuttx系统不是,Nuttx是基于Makefile的,px4源码基本都在Firmware/src下,Nuttx操作系统源码在Firmware/NuttX下)
有了上面这个两个概念之后,我们就开始着手编写我们的hello world程序。
首先进入/Firmware/src/examples文件夹,然后在这个文件夹下面建立一个文件夹hello_world,再进入hello_world文件夹,在该文件夹下建立两个文件:CMakeLists.txt,hello_world.c。
首先编辑hello_world.c文件。
#include <px4_config.h>#include <px4_tasks.h>#include <px4_posix.h>#include <unistd.h>#include <stdio.h>#include <poll.h>#include <string.h>__EXPORT int hello_world_main(int argc, char *argv[]);int hello_world_main(int argc, char *argv[]){PX4_INFO("hello world!");return 0;}
然后编辑CMakeLists.txt文件
px4_add_module(MODULE examples__hello_worldMAIN hello_worldSTACK_MAIN 2000SRCShello_world.cDEPENDSplatforms__common)
最后最重要的是我们要将这个程序注册到Nuttx的系统当中
找到文件/Firmware/cmake/configs/nuttx_px4fmu-v2_default.cmake
针对不同的硬件所注册的文件是不同的,下面是不同硬件的注册方式:
- Posix SITL: Firmware/cmake/configs/posix_sitl_default.cmake
- Pixhawk v1/2: Firmware/cmake/configs/nuttx_px4fmu-v2_default.cmake
- Pixracer: Firmware/cmake/configs/nuttx_px4fmu-v4_default.cmake
在cmake文件中添加“examples/hello_world”
像下面这样:
include(nuttx/px4_impl_nuttx)set(CMAKE_TOOLCHAIN_FILE ${PX4_SOURCE_DIR}/cmake/toolchains/Toolchain-arm-none-eabi.cmake)set(config_uavcan_num_ifaces 2)set(config_module_list## Board support modules#drivers/devicedrivers/stm32drivers/stm32/adcdrivers/stm32/tone_alarmdrivers/leddrivers/px4fmudrivers/px4iodrivers/boards/px4fmu-v2drivers/rgbleddrivers/mpu6000#drivers/mpu9250drivers/lsm303ddrivers/l3gd20drivers/hmc5883drivers/ms5611#drivers/mb12xx#drivers/srf02drivers/sf0x#drivers/ll40lsdrivers/tronedrivers/gpsdrivers/pwm_out_sim#drivers/hott#drivers/hott/hott_telemetry#drivers/hott/hott_sensors#drivers/blinkmdrivers/airspeeddrivers/ets_airspeeddrivers/meas_airspeed#drivers/frsky_telemetrymodules/sensors#drivers/mkblctrldrivers/px4flow#drivers/oreoled#drivers/vmountdrivers/pwm_inputdrivers/camera_triggerdrivers/bst#drivers/snapdragon_rc_pwmdrivers/lis3mdl#exampleexamples/px4_simple_appexamples/hello_world## System commands#systemcmds/bl_updatesystemcmds/configsystemcmds/dumpfile#systemcmds/esc_calibsystemcmds/mixer#systemcmds/motor_rampsystemcmds/mtdsystemcmds/nshtermsystemcmds/paramsystemcmds/perfsystemcmds/pwmsystemcmds/reboot#systemcmds/sd_benchsystemcmds/top#systemcmds/topic_listenersystemcmds/ver## Testing##drivers/sf0x/sf0x_tests#drivers/test_ppm#lib/rc/rc_tests#modules/commander/commander_tests#modules/controllib_test#modules/mavlink/mavlink_tests#modules/unit_test#modules/uORB/uORB_tests#systemcmds/tests## General system control#modules/commandermodules/load_monmodules/navigatormodules/mavlinkmodules/gpio_ledmodules/uavcanmodules/land_detector## Estimation modules#modules/attitude_estimator_q#modules/position_estimator_inavmodules/local_position_estimatormodules/ekf2## Vehicle Control#modules/fw_pos_control_l1modules/fw_att_controlmodules/mc_att_controlmodules/mc_pos_controlmodules/vtol_att_control## Logging##modules/loggermodules/sdlog2## Library modules#modules/parammodules/systemlibmodules/systemlib/mixermodules/uORBmodules/dataman## Libraries#lib/controlliblib/mathliblib/mathlib/math/filterlib/ecllib/external_lgpllib/geolib/geo_lookuplib/conversionlib/launchdetectionlib/terrain_estimationlib/runway_takeofflib/tailsitter_recoverylib/DriverFramework/frameworkplatforms/nuttx# had to add for cmake, not sure why wasn't in original configplatforms/commonplatforms/nuttx/px4_layer## OBC challenge##modules/bottle_drop## Rover apps##examples/rover_steering_control## Demo apps##examples/math_demo# Tutorial code from# https://px4.io/dev/px4_simple_app#examples/px4_simple_app# Tutorial code from# https://px4.io/dev/daemon#examples/px4_daemon_app# Tutorial code from# https://px4.io/dev/debug_values#examples/px4_mavlink_debug# Tutorial code from# https://px4.io/dev/example_fixedwing_control#examples/fixedwing_control# Hardware test#examples/hwtest)set(config_extra_builtin_cmdsserdissercon)set(config_io_boardpx4io-v2)set(config_extra_libsuavcanuavcan_stm32_driver)set(config_io_extra_libs)add_custom_target(sercon)set_target_properties(sercon PROPERTIESPRIORITY "SCHED_PRIORITY_DEFAULT"MAIN "sercon" STACK_MAIN "2048"COMPILE_FLAGS "-Os")add_custom_target(serdis)set_target_properties(serdis PROPERTIESPRIORITY "SCHED_PRIORITY_DEFAULT"MAIN "serdis" STACK_MAIN "2048"COMPILE_FLAGS "-Os")
这样cmake的编译系统就会将这个程序加入到编译链中去了。
在Firmware文件夹下面执行make px4fmu-v2_default,如果不出问题的话,编译成功会显示下面的画面:
然后将硬件连接至虚拟机,执行烧录命令:make px4fmu-v2_default upload
按照上一篇文章所讲的那样同Nuttx shell通信
./mavlink_shell.py /dev/ttyACM0
在nsh中输入help命令之后,你就会在Builtin Apps下面找到hello_world程序
执行hello_world程序:
可以看到输出了hello world!
那么这一切是怎么做到的呢?首先看看代码文件即hello_world.c文件
首先是include
#include <px4_config.h>#include <px4_tasks.h>#include <px4_posix.h>#include <unistd.h>#include <stdio.h>#include <poll.h>#include <string.h>
这些库文件你可以认为是编写基于Nuttx操作系统修改的px4程序程序必不可少的库文件包含(其实px4团队修改了不少Nuttx操作系统的东西,使其使用更加方便,所以这些程序并不是真正意义上的Nuttx程序)
然后是main函数(这里要提醒一下广大同学,可能px4基于stm32的编译器语法规则过于严格,所以在编写一个函数之前,必须要去申明这个函数,即使这个函数是main函数也要申明,不然编译报错,无法通过)
int hello_world_main(int argc, char *argv[]){PX4_INFO("hello world!");return 0;}
可以看到基于Nuttx操作系统的main函数和其它系统的命名有很大不同,但也有自己的规律,那就是函数名+_+main,即name_main(),程序主函数里的参数(int argc, char *argv[])和其它系统main函数所带的参数没什么不同(如果不懂main函数带形参的同学最好自己百度一下,因为px4的那些程序基本都带参数的)。
PX4_INFO();是一个类似于printf的函数(事实上他就是是基于printf实现的),用来输出PX4的一些信息的。
再来看看CMakeLists.txt文件
px4_add_module(MODULE examples__hello_worldMAIN hello_worldSTACK_MAIN 2000SRCShello_world.cDEPENDSplatforms__common)
从字面上可以了解到每个程序在CMake里面都是一个模块,最后总的Cmake文件会去自动将这些模块添加到最后的生成的Makefile文件里面。所以我们要做的就是把我们写的模块的一些属性描写清楚,然后将其注册到nuttx_px4fmu-v2_default.cmake文件当中。
首先是模块名MODULE:这个名字的命名规则是当前文件夹+__+主函数名。
然后是MIAN :这个就是用来确定代码中那个函数为主函数的,填写主函数名即可。
STACK_MAIN:目前暂不清楚用途
SRCS:所用到的源文件。
DEPENDS :依赖。
以上就是关于编写一个基于Nuttx操作系统hello world程序的全过程。
因为我本人对Cmake的一些语法还不是很清楚,所以以上有些东西可能描述的不是很清楚,如有大神,还望指点。
下面一篇文章我将简介一下大家都很关心和迫切想知道的问题,就是px4的飞控程序是怎么开始执行的,程序入口在哪。
- px4原生源码学习-(4)--Nuttx 实时操作系统编程
- px4原生源码学习-(4)--Nuttx 实时操作系统编程
- px4原生源码学习四--Nuttx 实时操作系统编程
- px4原生源码学习-(3)--Nuttx实时操作系统的使用
- px4原生源码学习三--Nuttx实时操作系统的使用
- px4原生源码学习-(2)--实时操作系统篇
- px4原生源码学习二--实时操作系统篇
- PX4实时操作系统(nuttx)自学笔记
- px4原生源码学习-(1)
- px4原生源码学习-(1)
- px4原生源码学习一
- 实时操作系统NuttX 介绍
- NuttX实时操作系统
- NuttX实时操作系统
- 实时操作系统Nuttx学习笔记(手册学习部分)
- PX4代码学习系列博客(2)——PX4与实时操作系统
- PX4源码学习二--PX4环境搭建
- (嵌入式 实时操作系统 rtos nuttx 7.1 stm32 源代码分析)
- 【Linux】利用管道在进程通讯拷贝文件
- Linux c==Linux 下的段错误分析(38)
- IE浏览器 按F12 不出现调试窗口 解决办法
- 行人检测3
- ZCMU—1780
- px4原生源码学习-(4)--Nuttx 实时操作系统编程
- ffmpeg常用基本命令(转)
- 1088: [SCOI2005]扫雷Mine
- 基于TI-RTOS的CC2650DK开发(12)---事件模块
- DataX介绍
- 邮箱验证方法
- RSA非对称加解密算法的使用
- Android-Webrtc APM For Android
- 滑动到尽头时去掉阴影效果