天天看點

PX4 BMI055驅動分析、PX4 BMI088驅動添加(SPI傳感器都類似)[運作環境][說明][流程][參考]

[目錄]

  • [運作環境]
  • [說明]
  • [流程]
    • 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 驅動代碼即啟動過程分析 :裝置驅動講得比較仔細

繼續閱讀