[目錄]
- [運作環境]
- [說明]
- [流程]
-
- 1.編譯部分選擇
- 2.啟動部分
- 3.BMI055傳感器代碼分析(以加速度為例)
-
- 3.1 類的繼承流程
- 3.2 最底層代碼流程
- 3.3 傳感器驅動流程分析(以加速度為例)
- 4.BMI088傳感器代碼修改
-
- 4.1 底層IO修改
- 4.2 修改傳感器SPI總線相關
- 4.3 修改BMI088傳感器初始化
- 4.4 其他
- 5. 增加CMakeLists.txt檔案
- [參考]
所有的熱愛都要不遺餘力,真正喜歡它便給它更高的優先級,和更多的時間吧!
PX4其它文章請點選這裡: PX4——無人機飛行控制系統
[運作環境]
硬體:基于PX4的v5的硬體的修改,移除掉IO從控晶片
軟體:PX4中v1.8.2版本
[說明]
●基于BMI055傳感器驅動的分析,BMI088是對BMI055的更新,順道分析傳感器的流程和部分Linux裝置驅動開發的知識。
●貼過來的代碼,都隻是摘取部分。
●配合 ctrl+f 搜尋檢視代碼更友善
[流程]
包括編譯部分、nuttx的晶片相關的驅動代碼、傳感器本身驅動部分,而“nuttx的晶片相關的驅動代碼”又包括了SPI相關
1.編譯部分選擇
(傳回目錄)
//路徑和檔案名:Firmware/cmake/configs/nuttx_px4fmu-v5_default.cmake:20
//屏蔽BMI055,增加BMI088驅動,在BMI055上更新
# drivers/imu/bmi055
drivers/imu/ccbmi088
2.啟動部分
(傳回目錄)
//路徑和檔案名:Firmware/ROMFS/px4fmu_common/init.d/rc.sensors:316
//關閉BMI055啟動,BMI088啟動分為加速度的啟動和陀螺儀的啟動
# Internal SPI bus BMI055 accel
#bmi055 -A -R 10 start
# ccbmi088 -A start
# Internal SPI bus BMI055 gyro
#bmi055 -G -R 10 start
# ccbmi088 -G start
3.BMI055傳感器代碼分析(以加速度為例)
3.1 類的繼承流程
(傳回目錄)
(傳回:傳感器驅動流程分析3.3.1)
具體流程圖如下:
A. device::Device 所有實體驅動程式(I2C, SPI)的基類
namespace device
{
/*Fundamental base class for all physical drivers (I2C, SPI)*/
class __EXPORT /*A*/Device{
virtual int read(unsigned address, void *data, unsigned count) { return -ENODEV; }
virtual int write(unsigned address, void *data, unsigned count) { return -ENODEV; }
uint8_t get_device_bus() { return _device_id.devid_s.bus; }
...
}
}
B. device::CDev 任何字元裝置的抽象類。
一般每個字元裝置或者塊裝置都會在/dev目錄(可以是任意目錄,這樣是為了統一)下對應一個裝置檔案。
linux使用者層程式通過裝置檔案來使用驅動程式操作字元裝置或塊裝置。
字元裝置是3大類裝置(字元裝置、塊裝置、網絡裝置)中較簡單的一類裝置、其驅動程式中完成的主要工作是初始化、
添加和删除 struct cdev 結構體,申請和釋放裝置号,以及填充 struct file_operations 結構體中斷的操作函數,實作
struct file_operations 結構體中的read()、write()和ioctl()等函數是驅動設計的主體工作
參考:linux中字元裝置驅動
namespace device
{
class __EXPORT /*B*/CDev : public /*A*/ Device{
virtual int open(file_t *filep);
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen);
virtual int register_class_devname(const char *class_devname);
static const px4_file_operations_t fops; /*flag3 檔案操作集合,讀寫相關等*/
...
}
}
C.device::SPI用于SPI上的字元裝置的抽象類
namespace device __EXPORT
{
class __EXPORT /*C*/SPI : public /*B*/CDev{
virtual int init();
int transfer(uint8_t *send, uint8_t *recv, unsigned len);
void set_frequency(uint32_t frequency) { _frequency = frequency; }
}
}
D.BMI055 最主要是構造函數
class /*D*/BMI055 : public /*C*/device::SPI{
BMI055(const char *name, const char *devname, int bus, uint32_t device, enum spi_mode_e mode, uint32_t frequency,enum Rotation rotation);
...
}
E. BMI055_accel 和 F. BMI055_gyro 傳感器驅動的具體實作
class /*E*/BMI055_accel : public /*D*/BMI055
BMI055_accel(int bus, const char *path_accel, uint32_t device, enum Rotation rotation);
start();
measure();
...
}
class /*F*/BMI055_gyro : public /*D*/BMI055
BMI055_gyro(int bus, const char *path_gyro, uint32_t device, enum Rotation rotation);
start();
measure();
...
}
3.2 最底層代碼流程
(傳回目錄)
3.2.1 第一步
//路徑:Firmware/src/drivers/boards/px4fmu-v5/init.c:260
//此函數應該是在boardctl()中被調用,本人也是一知半解
__EXPORT int board_app_initialize(uintptr_t arg) //第一步
{
VDD_3V3_SD_CARD_EN(true);
VDD_5V_PERIPH_EN(true);
...
int ret = stm32_spi_bus_initialize(); //第二步
...
}
3.2.1. 第二步
static struct spi_dev_s *spi_sensors;
//路徑:Firmware/src/drivers/boards/px4fmu-v5/spi.c:142
__EXPORT int board_app_initialize(uintptr_t arg) // 第二步
{
/* Configure SPI-based devices */
spi_sensors = stm32_spibus_initialize(PX4_SPI_BUS_SENSORS); // 第三步
SPI_SETFREQUENCY(spi_sensors, 10000000);
SPI_SETBITS(spi_sensors, 8);
SPI_SETMODE(spi_sensors, SPIDEV_MODE3);
for (int cs = PX4_SENSORS_BUS_FIRST_CS; cs <= PX4_SENSORS_BUS_LAST_CS; cs++) {
SPI_SELECT(spi_sensors, cs, false); //(全局搜尋flag2)
}
/* Get the SPI port for the BARO */
spi_baro = stm32_spibus_initialize(PX4_SPI_BUS_BARO);
...
/* Get the SPI port for the PX4_SPI_EXTERNAL1 */
spi_ext = stm32_spibus_initialize(PX4_SPI_BUS_EXTERNAL1);
...
/* Get the SPI port for the PX4_SPI_EXTERNAL2 */
spi_ext = stm32_spibus_initialize(PX4_SPI_BUS_EXTERNAL2);
...
}
3.2.3. 第三步 stm32_spibus_initialize
//路徑:Firmware/platforms/nuttx/NuttX/nuttx/arch/arm/src/stm32f7/stm32_spi.c:1751
//@return: (FAR struct spi_dev_s *) priv
FAR struct /*A1*/spi_dev_s *stm32_spibus_initialize(int bus)
{
FAR struct /*B1*/stm32_spidev_s *priv = NULL; //第四步:SPI底層操作
irqstate_t flags = enter_critical_section(); //進入臨界區
#ifdef CONFIG_STM32F7_SPI1
if (bus == 1)
{
/* Select SPI1 */
priv = /*B2*/&g_spi1dev; ///B2: g_spi1dev就代表了SPI1整個裝置集合
/* Only configure if the bus is not already configured */
if ((spi_getreg(priv, STM32_SPI_CR1_OFFSET) & SPI_CR1_SPE) == 0) //flag1(可全局搜flag1)
{
/* Configure SPI1 pins: SCK, MISO, and MOSI*/
/* GPIO配置 */
stm32_configgpio(GPIO_SPI1_SCK);
stm32_configgpio(GPIO_SPI1_MISO);
stm32_configgpio(GPIO_SPI1_MOSI); //第五步:IO 配置 GPIO_SPI1_SCK GPIO_SPI1_MISO
/* Set up default configuration: Master, 8-bit, etc. */
spi_bus_initialize(priv); //第六步
}
}
else
#endif
#ifdef CONFIG_STM32F7_SPI2
if (bus == 2)
{
/* Select SPI2 */
...
leave_critical_section(flags); //離開臨界區
return (FAR struct spi_dev_s *)priv;
}
3.2.4 第四步
①. spi 結構體相關綜述,執行個體化對象 (A1 A2 B1 B2定義)
//路徑:Firmware/platforms/nuttx/NuttX/nuttx/arch/arm/src/stm32f7/stm32_spi.c:229
//綁定SPI操作集合,就是綁定功能函數
static const struct /*A1*/ spi_ops_s /*A2*/g_sp1iops =
{
.lock = spi_lock,
/*#define SPI_SELECT(d,id,s) ((d)->ops->select(d,id,s))*/
.select = stm32_spi1select, /*flag2 spi片選選擇*/
/*#define SPI_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f))*/
.setfrequency = spi_setfrequency, /*spi設定頻率*/
...
/*#define SPI_SNDBLOCK(d,b,l) ((d)->ops->exchange(d,b,0,l))*/
.exchange = spi_exchange,
...
};
//綁定SPI裝置操作集合,包括了A2 SPI操作集合的執行個體,g_spi1dev就代表了SPI1整個裝置集合
static struct /*B1*/ stm32_spidev_s /*B2*/g_spi1dev =
{
.spidev = /*A2*/{ &g_sp1iops },
.spibase = STM32_SPI1_BASE, //#define STM32_SPI1_BASE 0x40013000
/*(flag1)
uint16_t spi_getreg(FAR struct stm32_spidev_s *priv, uint8_t offset){
return getreg16(priv->spibase + offset); }
# define getreg16(a) (*(volatile uint16_t *)(a)) */
.spiclock = STM32_PCLK2_FREQUENCY,
...
}
②:A1 結構體定義
//@路徑:v5/NuttX/nuttx/include/nuttx/spi/spi.h:519 (編譯後的路徑)
struct spi_ops_s
{
CODE int (*lock)(FAR struct spi_dev_s *dev, bool lock);
CODE void (*select)(FAR struct spi_dev_s *dev, uint32_t devid, bool selected);
CODE uint32_t (*setfrequency)(FAR struct spi_dev_s *dev, uint32_t frequency);
...
CODE void (*exchange)(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);
...
};
③:A1 結構體指針
//@路徑:v5/NuttX/nuttx/include/nuttx/spi/spi.h:560 (編譯後的路徑)
struct spi_dev_s
{
FAR const struct spi_ops_s *ops;
};
④:B1 結構體定義
//路徑:Firmware/platforms/nuttx/NuttX/nuttx/arch/arm/src/stm32f7/stm32_spi.c:143
struct stm32_spidev_s
{
struct spi_dev_s spidev; /* Externally visible part of the SPI interface */
uint32_t spibase; /* SPIn base address */
uint32_t spiclock; /* Clocking for the SPI module */
...
};
⑤: flag2 stm32_spi1select 片選選擇 以片選為例,深入底層
//路徑:Firmware/src/drivers/boards/px4fmu-v5/spi.c:242
__EXPORT void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
{
/* SPI select is active low, so write !selected to select the device */
int sel = (int) devid;
ASSERT(PX4_SPI_BUS_ID(sel) == PX4_SPI_BUS_SENSORS);
/* Making sure the other peripherals are not selected */
for (size_t cs = 0; arraySize(spi1selects_gpio) > 1 && cs < arraySize(spi1selects_gpio); cs++) {
if (spi1selects_gpio[cs] != 0) {
stm32_gpiowrite(spi1selects_gpio[cs], 1); //④-5-1 spi1selects_gpio[cs]
}
}
uint32_t gpio = spi1selects_gpio[PX4_SPI_DEV_ID(sel)];
if (gpio) {
stm32_gpiowrite(gpio, !selected);
}
}
//路徑:Firmware\src\drivers\boards\px4fmu-v5\spi.c
static const uint32_t spi1selects_gpio[] = PX4_SENSOR_BUS_CS_GPIO;
//路徑:Firmware\src\drivers\boards\px4fmu-v5\board_config.h
#define PX4_SENSOR_BUS_CS_GPIO {GPIO_SPI1_CS1_ICM20689, GPIO_SPI1_CS2_ICM20602, GPIO_SPI1_CS3_BMI055_GYRO, GPIO_SPI1_CS4_BMI055_ACC}
#define PX4_SENSORS_BUS_FIRST_CS PX4_SPIDEV_ICM_20689
#define PX4_SENSORS_BUS_LAST_CS PX4_SPIDEV_BMI055_ACC
//路徑:Firmware\src\drivers\boards\px4fmu-v5\board_config.h
#define GPIO_SPI1_CS1_ICM20689 /* PF2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTF|GPIO_PIN2)
#define GPIO_SPI1_CS2_ICM20602 /* PF3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTF|GPIO_PIN3)
#define GPIO_SPI1_CS3_BMI055_GYRO /* PF4 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTF|GPIO_PIN4)
#define GPIO_SPI1_CS4_BMI055_ACC /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10)
3.2.5 第五步: 根據自己硬體修改IO引腳定義
(傳回4.1代碼底層IO修改)
//路徑: Firmware/platforms/nuttx/nuttx-configs/px4fmu-v5/include/board.h:390
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_3 /* PG9 */
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_3 /* PD7 */
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_3 /* PG11 */
3.2.6.第六步: SPI總線預設初始化,寄存器操作 (主、8位、SPI模式0等)
static void spi_bus_initialize(FAR struct stm32_spidev_s *priv)
{
...
/* Configure CR1 and CR2. Default configuration:
* Mode 0: CR1.CPHA=0 and CR1.CPOL=0
* Master: CR1.MSTR=1
* 8-bit: CR2.DS=7
* MSB tranmitted first: CR1.LSBFIRST=0
* Replace NSS with SSI & SSI=1: CR1.SSI=1 CR1.SSM=1 (prevents MODF error)
* Two lines full duplex: CR1.BIDIMODE=0 CR1.BIDIOIE=(Don't care) and CR1.RXONLY=0
*/
clrbits = SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_BR_MASK | SPI_CR1_LSBFIRST |
SPI_CR1_RXONLY | SPI_CR1_BIDIOE | SPI_CR1_BIDIMODE;
setbits = SPI_CR1_MSTR | SPI_CR1_SSI | SPI_CR1_SSM;
spi_modifycr1(priv, setbits, clrbits);
clrbits = SPI_CR2_DS_MASK;
setbits = SPI_CR2_DS_8BIT | SPI_CR2_FRXTH; /* FRXTH must be high in 8-bit mode */
spi_modifycr2(priv, setbits, clrbits);
priv->frequency = 0;
priv->nbits = 8;
priv->mode = SPIDEV_MODE0;
/* Select a default frequency of approx. 400KHz */
spi_setfrequency((FAR struct spi_dev_s *)priv, 400000);
/* CRCPOLY configuration */
spi_putreg(priv, STM32_SPI_CRCPR_OFFSET, 7);
/* Initialize the SPI semaphore that enforces mutually exclusive access. */
...
/* Enable spi */
spi_modifycr1(priv, SPI_CR1_SPE, 0);
}
3.3 傳感器驅動流程分析(以加速度為例)
(傳回目錄)
#執行 bmi055 -A start 後:主要分三步:
void
start(bool external_bus, enum Rotation rotation, enum sensor_type sensor)
{
/*3.3.1 建立對象*/
BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
*g_dev_acc_ptr = new BMI055_accel(PX4_SPI_BUS_SENSORS, path_accel, PX4_SPIDEV_BMI055_ACC, rotation);
/*3.3.2 初始化*/
if (OK != (*g_dev_acc_ptr)->init()) {
goto fail_accel;
}
/*3.3.3 檔案操作 */
fd_acc = open(path_accel, O_RDONLY);
if (fd_acc < 0) {
goto fail_accel;
}
if (ioctl(fd_acc, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
goto fail_accel;
}
close(fd_acc);
}
3.3.1 : 檢視繼承關系 3.1 類的繼承流程 ,各個參數繼承流程如下:
(傳回:4.2 BMI088中修改傳感器SPI總線相關)
/* 編号配合搜尋更加
編号| 項目 | 原始值 | Value
-- |-------- | -------------------- | ---
Z1 | SPI總線 | PX4_SPI_BUS_SENSOR | 1
Z2 |裝置路徑 | path_accel | "/dev/bmi055_gyro"
Z3 |CS片選 | PX4_SPIDEV_BMI055_ACC | PX4_MK_SPI_SEL(PX4_SPI_BUS_SENSORS,3) = 0x1000 0405
Z4 |旋轉角度 | rotation | 0
Z5 |裝置名字 | name | "BMI055_ACCEL"
Z6 |SPI模式 | SPIDEV_MODE3 | //CPOL=1 CHPHA=1
Z7 |SPI頻率 | BMI055_BUS_SPEED | 10*1000*1000
*/
//E:
//路徑:Firmware/src/drivers/imu/bmi055/bmi055_main.cpp:72
new BMI055_accel(/*Z1*/PX4_SPI_BUS_SENSORS,/*Z2*/path_accel,/*Z3*/PX4_SPIDEV_BMI055_ACC,/*Z4*/rotation);
//路徑:Firmware/src/drivers/imu/bmi055/bmi055_accel.cpp:25
BMI055_accel::BMI055_accel(int/*Z1*/bus, const char/*Z2*/*path_accel, uint32_t/*Z3*/device,/*Z4*/enum Rotation rotation)
BMI055(/*Z5*/"BMI055_ACCEL",/*Z2*/path_accel,/*Z1*/bus,/*Z3*/device,/*Z6*/SPIDEV_MODE3,/*Z7*/BMI055_BUS_SPEED, /*Z4*/rotation),
{
_device_id.devid_s.devtype = DRV_ACC_DEVTYPE_BMI055;
}
//D:
//路徑:Firmware/src/drivers/imu/bmi055/bmi055_main.cpp:432
BMI055::BMI055(const char/*Z5*/*name, const char/*Z2*/*devname, int/*Z1*/bus, uint32_t/*Z3*/device, enum spi_mode_e/*Z6*/mode,uint32_t/*Z7*/frequency, enum Rotation/*Z4*/rotation):
/*C*/SPI(/*Z5*/name,/*Z2*/devname, /*Z1*/bus,/*Z3*/device,/*Z6*/mode,/*Z7*/frequency),
/*Z4*/_rotation(/*Z4*/rotation),
{
}
//C:
//路徑:Firmware/src/lib/drivers/device/nuttx/SPI.cpp:60
SPI::SPI(const char/*Z5*/*name,
const char/*Z2*/*devname,
int/*Z1*/bus,
uint32_t/*Z3*/device,
/*Z6*/enum spi_mode_e mode,
/*Z7*/uint32_t frequency) :
// base class
CDev(/*Z5*/name, /*Z2*/devname),
/*Z3*/_device(device), //SPI_SELECT(_dev, _device, true); 片選 與“3.2.4”相關
/*Z6*/_mode(mode), //SPI_SETMODE(_dev, _mode); 設定模式 與“3.2.4”相關
/*Z7*/_frequency(frequency), //SPI_SETFREQUENCY(_dev, _frequency); 設定頻率 與“3.2.4”相關
_dev(nullptr)
{
// fill in _device_id fields for a SPI device
_device_id.devid_s.bus_type = DeviceBusType_SPI;
/*Z1*/_device_id.devid_s.bus =/*Z1*/bus;
/*Z3*/_device_id.devid_s.address = (uint8_t)/*Z3*/device;
// devtype needs to be filled in by the driver
_device_id.devid_s.devtype = 0;
}
//B:
//路徑:Firmware/src/lib/drivers/device/CDev.cpp:50
CDev::CDev(const char/*Z5*/*name, const char/*Z2*/*devname) :
Device(/*Z5*/name),
/*Z2*/_devname(devname){
...
}
//A:
//路徑:Firmware/src/lib/drivers/device/Device.hpp:191
Device(const char/*Z5*/*name) : /*Z5*/_name(name){
...
/*預設構造函數*/
}
3.3.2 BMI055_accel::init() 初始化
如修改總線、片選、總線頻率、SPI模式、注冊路徑等:
(傳回:4.3 傳感器初始化)
//路徑:Firmware/src/drivers/imu/bmi055/bmi055_accel.cpp:73
int BMI055_accel::init()
{
/*① 第一步 見下面分析*/
int ret = SPI::init(); //
/*② 第二步 BMI055傳感器本身配置,包括帶寬、量程、使能DRDY中斷等,寫BMI088的話,就再此初始化BMI088傳感器*/
reset();
/*③ 第三步 這個不太懂,希望懂的人,能告知一二*/
_accel_class_instance = register_class_devname(ACCEL_BASE_DEVICE_PATH);
/*④ 第四步:測量包括:傳感器資料讀取、低通濾波、角度旋轉、資料大小端處理、歸一化等,uORB釋出*/
measure(false);
/*⑤ 第五步主題相關*/
sensor_accel_s arp;
_accel_reports->get(&arp);
_accel_topic = orb_advertise_multi(ORB_ID(sensor_accel), &arp, &_accel_orb_class_instance, ORB_PRIO_HIGH - 1);
return OK;
}
① 第一步
//路徑:Firmware/src/lib/drivers/device/nuttx/SPI.cpp:91
int
SPI::init()
{
_dev = px4_spibus_initialize(get_device_bus());
//#define px4_spibus_initialize(bus_num_1based) stm32_spibus_initialize(bus_num_1based)
//stm32_spibus_initialize() 見“3.2.3. 第三步(可搜尋)” 就和底層完全聯系起來了,傳回的值代表了整個總線1,包括綁定了SPI的操作函數集合,SPI時間基準,SPI分頻,SPIDMA相關
//全局搜get_device_bus()和_device_id.devid_s.bus發現就是總線1。
/*Z3*/SPI_SELECT(_dev, _device, false);
ret = probe();
/*_whoami寄存器相關,驗證總線是否正常和傳感器是否存在 */
ret = CDev::init();
//最重要是這個注冊函數:ret = register_driver(/*Z2*/_devname, &fops, 0666, (void *)this); //flag3
/*向作業系統注冊一個裝置節點,定義一個驅動程式類bmi055并繼承CDev類,來注冊裝置節點。CDev類是PX4程式中提供的一個C++基類,驅動程式需要繼承,并重寫open、close、read、write、ioctl、seek等方法。
比如fops中包括讀操作,而bmi055::read 繼承了CDev的虛函數,之後就可以用
sz = read(fd_acc, &a_report, sizeof(a_report)); 來調用bmi055::read()的函數(不知道說錯了沒,自己的了解)
●Linux中用insmod裝載驅動程式,是以隻需要指定函數入口,在裝載時會自動執行入口函數,并生成裝置節點.
●Nuttx中裝載驅動程式不同于Linux可以在随時裝載,而是寫死在代碼中的,即調用register_driver後完成驅動的裝載。
*/
out:
return ret;
}
3.3.3 檔案操作
...
fd_acc = open(path_accel, O_RDONLY);
/*在之前注冊了驅動,在此打開裝置,就能ioctl、read、write、了
傳感器作為一個檔案裝置,操作步驟: open -> ioctl -> read -> close */
ioctl(fd_acc, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)
/*ioctl(filp, SENSORIOCSPOLLRATE, BMI055_ACCEL_DEFAULT_RATE)==>start()==>
BMI055_accel::measure_trampoline==>dev->measure();
是通過高精度定時器回調函數實作measure(), 有些精度不高的可以用工作者隊列work_queue來循環
*/
close(fd_acc);
...
4.BMI088傳感器代碼修改
(傳回目錄)
4.1 底層IO修改
如修改SPI底層IO:3.2.5 根據自己硬體修改IO引腳定義
4.2 修改傳感器SPI總線相關
如修改總線、片選、總線頻率、SPI模式、注冊路徑等:3.3.1 各個參數繼承流程
4.3 修改BMI088傳感器初始化
如帶寬、測量量程、使能DRDY中斷,還要注意讀寫函數(讀有一個dummy_byte位):3.3.2 init() 初始化第二步BMI055傳感器本身配置
4.4 其他
調試列印我用warnx(); 或者PX4_INFO(); 其他調試也可以多利用“bmi055 test”
還可以在終端輸入“bmi055 info”來擷取傳感器狀态資訊,包括讀取原始資料所需要的時間,運作程式的次數,運作程式周期等。
5. 增加CMakeLists.txt檔案
在該目錄下建立一個CMakeLists.txt檔案 加入編譯規則,參考着已有的編寫就行了。
[參考]
● Pixhawk原生固件PX4之MPU6000驅動分析
● PX4 MPU6000 驅動代碼即啟動過程分析 :裝置驅動講得比較仔細