一、简介
主要介绍stm32h7移植到nuttx的修改内容。当前修改是在nuttx已经支持的stm32 f7平台的基础上进行的,即相关驱动先拷贝f7的现有代码,然后进行修改以支持h7。修改主要分为两部分:一部分是以stm32h7芯片驱动为主,相关代码主要是nuttx的驱动代码;另一部分是与飞控板本身具体硬件相关的,相关代码在px4的drivers/boards的对应目录下。
二、nuttx的芯片相关的驱动代码
nuttx与芯片驱动相关的代码主要在nuttx\arch目录下。对应stm32h7而言,有两个目录:nuttx\arch\arm\src\stm32h7,arch\arm\include\stm32h7。移植主要是增加这两个目录(从f7的对应目录copy过来),然后进行具体的修改。
修改时需要参考stm32h7的datasheet,根据不同模块看对应章节的内容,然后分析与stm32 f7的差异,进行相关的修改。
头文件主要定义了对应模块(如i2c)支持了哪些寄存器,这些寄存器的相对地址,以及对应的比特定义。因此头文件需要仔细校对一遍,确保与h7对应。
源文件要针对f7与h7的具体的不同进行相应的修改。例如,h7的dma机制与f7的不同,需要做额外的配置和修改,所以对应模块如果支持dma,就需要检查所有与dma相关的代码,分析是否需要进行相应修改。
当前库上的代码已经支持stm32h7。因此,可以通过比较stm32h7与stm32f7对应的目录代码来了解当前所做的修改。
三、与stm32h7飞控板本身硬件相关的修改
这部分代码主要在Firmware\src\drivers\boards\px4fmu-v6目录下,主要是适配具体飞控硬件的。其中最主要的是头文件board_config.h,这个文件定义了各个spi的片选,pwm输出使用的定时器等内容。其他代码不多并且不是很复杂,本文不再具体描述这部分代码。
四、nuttx的移植
1、nuttx简介
nuttx支持多种芯片平台,高度可定制,是一个类linux的rtos。与linux一样,编译nuttx时首先需要一个配置文件,如.config。这个文件就是通过宏来定制nuttx,例如选择单板的芯片平台,具体的芯片型号,是否支持硬浮点,是否支持I2C,SPI,UART,以及具体支持哪几路I2C,SPI,UART,是否支持操作系统的某个特性,等等诸如此类。配置文件的生成一般也是类似linux,可以执行make config来生成。最终makefile文件会包含这个config文件,从而根据该文件中定义的宏来选择编译哪些文件以及文件里面的哪些函数。
针对我们的h7飞控,nuttx的配置文件在Firmware\nuttx-configs\px4fmu-v6\nsh目录下,文件名为defconfig。Firmware\nuttx-configs\px4fmu-v6目录的内容都是与nuttx配置相关的。 include目录下的board.h:定义了与stm32h7芯片相关的配置,是一个需要修改的重要文件。里面定义的内容nuttx的芯片驱动会使用到。
scripts目录下的ld.script:编译器链接脚本,定义了编译的代码段数据段怎样放入到flash或ram中。也需要根据芯片进行对应修改。
2、移植的大致过程
基本的方法是根据系统的启动过程来进行移植和调试。找到系统最开始调用的函数,通过控制GPIO点灯或uart打印的方式,先确定系统调用了这个函数。然后再根据nuttx系统的启动过程,通过点灯或uart打印,逐步的调试。
对于stm32系列芯片,上电后首先需要配置时钟rcc模块,具体配置可以参考stm32cubemx工具自动生成的代码。之后如果调试具体的模块如uart,这个模块也需要进行相关的时钟配置。
3、nuttx编译的makefile简介
a) nuttx根目录下的makeifle:可以看到,根据具体平台选择不同的文件,px4是在linux 下编译的,使用的是Makefile.unix文件。
-include .config /*这个文件就是该单板针对nuttx的配置文件*/
ifeq($(CONFIG_WINDOWS_NATIVE),y)
include Makefile.win
else
includeMakefile.unix
endif
b) Makefile.unix:该文件是关键部分,我们摘取关键的内容进行分析。
Makefile大部分定义了一些宏,方便后面引用。然后定义了如何编译,主要是
按照如下的结构:
target: dep1 dep2 dep3
do_action1; do_action2
target为(编译)目标,这个目标有一些依赖项,如dep1,dep2,dep3。因此编译target 这个目标时,先完成这些依赖项;然后再做后面的action1,action2。所以这里面就存在 嵌套编译结构。
根据上面解释,从下面makefile.unix文件的内容看出,执行make操作时,默认的 target为all,all依赖$(BIN),进而又有四个依赖项。根据这些依赖项的名字可以看出, nuttx编译主要划分为两个阶段pass1,pass2。
pass1主要编译user或app层面的库或文 件。
pass2主要编译nuttx os层面的库或文件。
宏USERDEPDIRS,KERNDEPDIRS在文件Directories.mk中定义,USERLIBS、NUTTXLIBS 在文件FlatLibs.mk中定义。
注意pass2在执行完依赖项后会进入arch对应的目录下执行编译(见红色加粗的那 行)。对于stm32来说,会进入nuttx\arch\arm\src目录执行编译,该目录下有个makefile 文件。最后一步的链接操作就是在这里执行的。
BIN = nuttx$(EXEEXT)
all:$(BIN)
$(BIN): pass1depspass2deps pass1 pass2
pass1deps: pass1dep $(USERLIBS)
pass2deps:pass2dep $(NUTTXLIBS)
pass1dep: contexttools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
$(Q) for dir in $(USERDEPDIRS) ; do \
$(MAKE) -C $$dirTOP