mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-01 11:06:04 +08:00
refactor bmi160: use driver base class
This commit is contained in:
@@ -77,7 +77,6 @@
|
|||||||
#define DRV_IMU_DEVTYPE_MPU9250 0x24
|
#define DRV_IMU_DEVTYPE_MPU9250 0x24
|
||||||
#define DRV_GYR_DEVTYPE_BMI160 0x25
|
#define DRV_GYR_DEVTYPE_BMI160 0x25
|
||||||
#define DRV_IMU_DEVTYPE_ICM42688P 0x26
|
#define DRV_IMU_DEVTYPE_ICM42688P 0x26
|
||||||
|
|
||||||
#define DRV_IMU_DEVTYPE_ICM40609D 0x27
|
#define DRV_IMU_DEVTYPE_ICM40609D 0x27
|
||||||
|
|
||||||
#define DRV_RNG_DEVTYPE_MB12XX 0x31
|
#define DRV_RNG_DEVTYPE_MB12XX 0x31
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ const uint8_t BMI160::_checked_registers[BMI160_NUM_CHECKED_REGISTERS] = { BM
|
|||||||
BMIREG_NV_CONF
|
BMIREG_NV_CONF
|
||||||
};
|
};
|
||||||
|
|
||||||
BMI160::BMI160(int bus, uint32_t device, enum Rotation rotation) :
|
BMI160::BMI160(I2CSPIBusOption bus_option, int bus, int32_t device, enum Rotation rotation, int bus_frequency,
|
||||||
SPI("BMI160", nullptr, bus, device, SPIDEV_MODE3, BMI160_BUS_SPEED),
|
spi_mode_e spi_mode) :
|
||||||
ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(this->get_device_id())),
|
SPI("BMI160", nullptr, bus, device, spi_mode, bus_frequency),
|
||||||
|
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus),
|
||||||
_px4_accel(get_device_id(), (external() ? ORB_PRIO_MAX - 1 : ORB_PRIO_HIGH - 1), rotation),
|
_px4_accel(get_device_id(), (external() ? ORB_PRIO_MAX - 1 : ORB_PRIO_HIGH - 1), rotation),
|
||||||
_px4_gyro(get_device_id(), (external() ? ORB_PRIO_MAX - 1 : ORB_PRIO_HIGH - 1), rotation),
|
_px4_gyro(get_device_id(), (external() ? ORB_PRIO_MAX - 1 : ORB_PRIO_HIGH - 1), rotation),
|
||||||
_accel_reads(perf_alloc(PC_COUNT, "bmi160_accel_read")),
|
_accel_reads(perf_alloc(PC_COUNT, "bmi160_accel_read")),
|
||||||
@@ -63,15 +64,12 @@ BMI160::BMI160(int bus, uint32_t device, enum Rotation rotation) :
|
|||||||
_reset_retries(perf_alloc(PC_COUNT, "bmi160_reset_retries")),
|
_reset_retries(perf_alloc(PC_COUNT, "bmi160_reset_retries")),
|
||||||
_duplicates(perf_alloc(PC_COUNT, "bmi160_duplicates"))
|
_duplicates(perf_alloc(PC_COUNT, "bmi160_duplicates"))
|
||||||
{
|
{
|
||||||
_px4_accel.set_device_type(DRV_ACC_DEVTYPE_BMI160);
|
_px4_accel.set_device_type(DRV_IMU_DEVTYPE_BMI160);
|
||||||
_px4_gyro.set_device_type(DRV_GYR_DEVTYPE_BMI160);
|
_px4_gyro.set_device_type(DRV_IMU_DEVTYPE_BMI160);
|
||||||
}
|
}
|
||||||
|
|
||||||
BMI160::~BMI160()
|
BMI160::~BMI160()
|
||||||
{
|
{
|
||||||
/* make sure we are truly inactive */
|
|
||||||
stop();
|
|
||||||
|
|
||||||
/* delete the perf counter */
|
/* delete the perf counter */
|
||||||
perf_free(_sample_perf);
|
perf_free(_sample_perf);
|
||||||
perf_free(_accel_reads);
|
perf_free(_accel_reads);
|
||||||
@@ -494,28 +492,12 @@ BMI160::set_gyro_range(unsigned max_dps)
|
|||||||
void
|
void
|
||||||
BMI160::start()
|
BMI160::start()
|
||||||
{
|
{
|
||||||
/* make sure we are stopped first */
|
|
||||||
stop();
|
|
||||||
|
|
||||||
/* start polling at the specified rate */
|
/* start polling at the specified rate */
|
||||||
ScheduleOnInterval((1_s / BMI160_GYRO_DEFAULT_RATE) - BMI160_TIMER_REDUCTION, 1000);
|
ScheduleOnInterval((1_s / BMI160_GYRO_DEFAULT_RATE) - BMI160_TIMER_REDUCTION, 1000);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
BMI160::stop()
|
|
||||||
{
|
|
||||||
ScheduleClear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
BMI160::Run()
|
|
||||||
{
|
|
||||||
/* make another measurement */
|
|
||||||
measure();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMI160::check_registers(void)
|
BMI160::check_registers(void)
|
||||||
{
|
{
|
||||||
@@ -560,7 +542,7 @@ BMI160::check_registers(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BMI160::measure()
|
BMI160::RunImpl()
|
||||||
{
|
{
|
||||||
if (hrt_absolute_time() < _reset_wait) {
|
if (hrt_absolute_time() < _reset_wait) {
|
||||||
// we're waiting for a reset to complete
|
// we're waiting for a reset to complete
|
||||||
@@ -690,8 +672,9 @@ BMI160::measure()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BMI160::print_info()
|
BMI160::print_status()
|
||||||
{
|
{
|
||||||
|
I2CSPIDriverBase::print_status();
|
||||||
perf_print_counter(_sample_perf);
|
perf_print_counter(_sample_perf);
|
||||||
perf_print_counter(_accel_reads);
|
perf_print_counter(_accel_reads);
|
||||||
perf_print_counter(_gyro_reads);
|
perf_print_counter(_gyro_reads);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
|
#include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
|
||||||
#include <perf/perf_counter.h>
|
#include <perf/perf_counter.h>
|
||||||
#include <px4_platform_common/getopt.h>
|
#include <px4_platform_common/getopt.h>
|
||||||
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
|
#include <px4_platform_common/i2c_spi_buses.h>
|
||||||
#include <systemlib/conversions.h>
|
#include <systemlib/conversions.h>
|
||||||
|
|
||||||
#define DIR_READ 0x80
|
#define DIR_READ 0x80
|
||||||
@@ -243,33 +243,38 @@
|
|||||||
|
|
||||||
using namespace time_literals;
|
using namespace time_literals;
|
||||||
|
|
||||||
class BMI160 : public device::SPI, public px4::ScheduledWorkItem
|
class BMI160 : public device::SPI, public I2CSPIDriver<BMI160>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BMI160(int bus, uint32_t device, enum Rotation rotation);
|
BMI160(I2CSPIBusOption bus_option, int bus, int32_t device, enum Rotation rotation, int bus_frequency,
|
||||||
|
spi_mode_e spi_mode);
|
||||||
virtual ~BMI160();
|
virtual ~BMI160();
|
||||||
|
|
||||||
virtual int init();
|
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
|
||||||
|
int runtime_instance);
|
||||||
|
static void print_usage();
|
||||||
|
|
||||||
/**
|
int init() override;
|
||||||
* Diagnostics - print some basic information about the driver.
|
|
||||||
*/
|
void print_status() override;
|
||||||
void print_info();
|
|
||||||
|
|
||||||
void print_registers();
|
void print_registers();
|
||||||
|
|
||||||
// deliberately cause a sensor error
|
// deliberately cause a sensor error
|
||||||
void test_error();
|
void test_error();
|
||||||
|
|
||||||
|
void RunImpl();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int probe();
|
int probe() override;
|
||||||
|
void custom_method(const BusCLIArguments &cli) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
PX4Accelerometer _px4_accel;
|
PX4Accelerometer _px4_accel;
|
||||||
PX4Gyroscope _px4_gyro;
|
PX4Gyroscope _px4_gyro;
|
||||||
|
|
||||||
uint8_t _whoami; /** whoami result */
|
uint8_t _whoami; ///< whoami result
|
||||||
|
|
||||||
unsigned _dlpf_freq;
|
unsigned _dlpf_freq;
|
||||||
|
|
||||||
@@ -306,11 +311,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop automatic measurement.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset chip.
|
* Reset chip.
|
||||||
*
|
*
|
||||||
@@ -318,13 +318,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
int reset();
|
int reset();
|
||||||
|
|
||||||
void Run() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch measurements from the sensor and update the report buffers.
|
|
||||||
*/
|
|
||||||
void measure();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a register from the BMI160
|
* Read a register from the BMI160
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,221 +33,108 @@
|
|||||||
|
|
||||||
#include "bmi160.hpp"
|
#include "bmi160.hpp"
|
||||||
|
|
||||||
/** driver 'main' command */
|
#include <px4_platform_common/getopt.h>
|
||||||
extern "C" { __EXPORT int bmi160_main(int argc, char *argv[]); }
|
#include <px4_platform_common/module.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* Local functions in support of the shell command.
|
|
||||||
*/
|
|
||||||
namespace bmi160
|
|
||||||
{
|
|
||||||
|
|
||||||
BMI160 *g_dev_int; // on internal bus
|
|
||||||
BMI160 *g_dev_ext; // on external bus
|
|
||||||
|
|
||||||
void start(bool, enum Rotation);
|
|
||||||
void stop(bool);
|
|
||||||
void info(bool);
|
|
||||||
void regdump(bool);
|
|
||||||
void testerror(bool);
|
|
||||||
void usage();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the driver.
|
|
||||||
*
|
|
||||||
* This function only returns if the driver is up and running
|
|
||||||
* or failed to detect the sensor.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
start(bool external_bus, enum Rotation rotation)
|
BMI160::print_usage()
|
||||||
{
|
{
|
||||||
BMI160 **g_dev_ptr = external_bus ? &g_dev_ext : &g_dev_int;
|
PRINT_MODULE_USAGE_NAME("bmi160", "driver");
|
||||||
|
PRINT_MODULE_USAGE_SUBCATEGORY("imu");
|
||||||
|
PRINT_MODULE_USAGE_COMMAND("start");
|
||||||
|
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(false, true);
|
||||||
|
PRINT_MODULE_USAGE_PARAM_INT('R', 0, 0, 35, "Rotation", true);
|
||||||
|
PRINT_MODULE_USAGE_COMMAND("reset");
|
||||||
|
PRINT_MODULE_USAGE_COMMAND("regdump");
|
||||||
|
PRINT_MODULE_USAGE_COMMAND("testerror");
|
||||||
|
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||||
|
}
|
||||||
|
|
||||||
if (*g_dev_ptr != nullptr)
|
I2CSPIDriverBase *BMI160::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
|
||||||
/* if already started, the still command succeeded */
|
int runtime_instance)
|
||||||
{
|
{
|
||||||
errx(0, "already started");
|
BMI160 *instance = new BMI160(iterator.configuredBusOption(), iterator.bus(), iterator.devid(), cli.rotation,
|
||||||
|
cli.bus_frequency, cli.spi_mode);
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
PX4_ERR("alloc failed");
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create the driver */
|
if (OK != instance->init()) {
|
||||||
if (external_bus) {
|
delete instance;
|
||||||
#if defined(PX4_SPI_BUS_EXT) && defined(PX4_SPIDEV_EXT_BMI)
|
return nullptr;
|
||||||
*g_dev_ptr = new BMI160(PX4_SPI_BUS_EXT, PX4_SPIDEV_EXT_BMI, rotation);
|
|
||||||
#else
|
|
||||||
errx(0, "External SPI not available");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
#if defined(PX4_SPIDEV_BMI)
|
|
||||||
*g_dev_ptr = new BMI160(PX4_SPI_BUS_SENSORS, PX4_SPIDEV_BMI, rotation);
|
|
||||||
#else
|
|
||||||
errx(0, "No Internal SPI CS");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*g_dev_ptr == nullptr) {
|
return instance;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OK != (*g_dev_ptr)->init()) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
fail:
|
|
||||||
|
|
||||||
if (*g_dev_ptr != nullptr) {
|
|
||||||
delete (*g_dev_ptr);
|
|
||||||
*g_dev_ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
errx(1, "driver start failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stop(bool external_bus)
|
BMI160::custom_method(const BusCLIArguments &cli)
|
||||||
{
|
{
|
||||||
BMI160 **g_dev_ptr = external_bus ? &g_dev_ext : &g_dev_int;
|
switch (cli.custom1) {
|
||||||
|
case 0: reset();
|
||||||
|
break;
|
||||||
|
|
||||||
if (*g_dev_ptr != nullptr) {
|
case 1: print_registers();
|
||||||
delete *g_dev_ptr;
|
break;
|
||||||
*g_dev_ptr = nullptr;
|
|
||||||
|
|
||||||
} else {
|
case 2: test_error();
|
||||||
/* warn, but not an error */
|
break;
|
||||||
warnx("already stopped.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
extern "C" int bmi160_main(int argc, char *argv[])
|
||||||
* Print a little info about the driver.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
info(bool external_bus)
|
|
||||||
{
|
{
|
||||||
BMI160 **g_dev_ptr = external_bus ? &g_dev_ext : &g_dev_int;
|
|
||||||
|
|
||||||
if (*g_dev_ptr == nullptr) {
|
|
||||||
errx(1, "driver not running");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("state @ %p\n", *g_dev_ptr);
|
|
||||||
(*g_dev_ptr)->print_info();
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dump the register information
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
regdump(bool external_bus)
|
|
||||||
{
|
|
||||||
BMI160 **g_dev_ptr = external_bus ? &g_dev_ext : &g_dev_int;
|
|
||||||
|
|
||||||
if (*g_dev_ptr == nullptr) {
|
|
||||||
errx(1, "driver not running");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("regdump @ %p\n", *g_dev_ptr);
|
|
||||||
(*g_dev_ptr)->print_registers();
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* deliberately produce an error to test recovery
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
testerror(bool external_bus)
|
|
||||||
{
|
|
||||||
BMI160 **g_dev_ptr = external_bus ? &g_dev_ext : &g_dev_int;
|
|
||||||
|
|
||||||
if (*g_dev_ptr == nullptr) {
|
|
||||||
errx(1, "driver not running");
|
|
||||||
}
|
|
||||||
|
|
||||||
(*g_dev_ptr)->test_error();
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usage()
|
|
||||||
{
|
|
||||||
warnx("missing command: try 'start', 'info', 'stop', 'regdump', 'testerror'");
|
|
||||||
warnx("options:");
|
|
||||||
warnx(" -X (external bus)");
|
|
||||||
warnx(" -R rotation");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int
|
|
||||||
bmi160_main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int myoptind = 1;
|
|
||||||
int ch;
|
int ch;
|
||||||
const char *myoptarg = nullptr;
|
using ThisDriver = BMI160;
|
||||||
bool external_bus = false;
|
BusCLIArguments cli{false, true};
|
||||||
enum Rotation rotation = ROTATION_NONE;
|
cli.default_spi_frequency = BMI160_BUS_SPEED;
|
||||||
|
|
||||||
while ((ch = px4_getopt(argc, argv, "XR:", &myoptind, &myoptarg)) != EOF) {
|
while ((ch = cli.getopt(argc, argv, "R:")) != EOF) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'X':
|
|
||||||
external_bus = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
rotation = (enum Rotation)atoi(myoptarg);
|
cli.rotation = (enum Rotation)atoi(cli.optarg());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
bmi160::usage();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myoptind >= argc) {
|
const char *verb = cli.optarg();
|
||||||
bmi160::usage();
|
|
||||||
|
if (!verb) {
|
||||||
|
ThisDriver::print_usage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *verb = argv[myoptind];
|
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_IMU_DEVTYPE_BMI160);
|
||||||
|
|
||||||
/*
|
|
||||||
* Start/load the driver.
|
|
||||||
*/
|
|
||||||
if (!strcmp(verb, "start")) {
|
if (!strcmp(verb, "start")) {
|
||||||
bmi160::start(external_bus, rotation);
|
return ThisDriver::module_start(cli, iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(verb, "stop")) {
|
if (!strcmp(verb, "stop")) {
|
||||||
bmi160::stop(external_bus);
|
return ThisDriver::module_stop(iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!strcmp(verb, "status")) {
|
||||||
* Print driver information.
|
return ThisDriver::module_status(iterator);
|
||||||
*/
|
}
|
||||||
if (!strcmp(verb, "info")) {
|
|
||||||
bmi160::info(external_bus);
|
if (!strcmp(verb, "reset")) {
|
||||||
|
cli.custom1 = 0;
|
||||||
|
return ThisDriver::module_custom_method(cli, iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Print register information.
|
|
||||||
*/
|
|
||||||
if (!strcmp(verb, "regdump")) {
|
if (!strcmp(verb, "regdump")) {
|
||||||
bmi160::regdump(external_bus);
|
cli.custom1 = 1;
|
||||||
|
return ThisDriver::module_custom_method(cli, iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(verb, "testerror")) {
|
if (!strcmp(verb, "testerror")) {
|
||||||
bmi160::testerror(external_bus);
|
cli.custom1 = 2;
|
||||||
|
return ThisDriver::module_custom_method(cli, iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmi160::usage();
|
ThisDriver::print_usage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user