refactor ist8308: use driver base class

This commit is contained in:
Beat Küng
2020-03-19 13:24:03 +01:00
committed by Daniel Agar
parent 030ba24f53
commit ee49e500e7
3 changed files with 87 additions and 194 deletions

View File

@@ -40,9 +40,9 @@ static constexpr int16_t combine(uint8_t msb, uint8_t lsb)
return (msb << 8u) | lsb;
}
IST8308::IST8308(int bus, uint8_t address, enum Rotation rotation) :
I2C(MODULE_NAME, nullptr, bus, address, I2C_SPEED),
ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(get_device_id())),
IST8308::IST8308(I2CSPIBusOption bus_option, int bus, enum Rotation rotation, int bus_frequency) :
I2C(MODULE_NAME, nullptr, bus, I2C_ADDRESS_DEFAULT, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus),
_px4_mag(get_device_id(), external() ? ORB_PRIO_VERY_HIGH : ORB_PRIO_HIGH, rotation)
{
set_device_type(DRV_MAG_DEVTYPE_IST8308);
@@ -53,43 +53,34 @@ IST8308::IST8308(int bus, uint8_t address, enum Rotation rotation) :
IST8308::~IST8308()
{
Stop();
perf_free(_transfer_perf);
perf_free(_bad_register_perf);
perf_free(_bad_transfer_perf);
}
bool IST8308::Init()
int IST8308::init()
{
if (I2C::init() != PX4_OK) {
PX4_ERR("I2C::init failed");
return false;
int ret = I2C::init();
if (ret != PX4_OK) {
DEVICE_DEBUG("I2C::init failed (%i)", ret);
return ret;
}
return Reset();
}
void IST8308::Stop()
{
// wait until stopped
while (_state.load() != STATE::STOPPED) {
_state.store(STATE::REQUEST_STOP);
ScheduleNow();
px4_usleep(10);
}
return Reset() ? 0 : -1;
}
bool IST8308::Reset()
{
_state.store(STATE::RESET);
_state = STATE::RESET;
ScheduleClear();
ScheduleNow();
return true;
}
void IST8308::PrintInfo()
void IST8308::print_status()
{
I2CSPIDriverBase::print_status();
perf_print_counter(_transfer_perf);
perf_print_counter(_bad_register_perf);
perf_print_counter(_bad_transfer_perf);
@@ -102,21 +93,21 @@ int IST8308::probe()
const uint8_t whoami = RegisterRead(Register::WAI);
if (whoami != Device_ID) {
PX4_WARN("unexpected WAI 0x%02x", whoami);
DEVICE_DEBUG("unexpected WAI 0x%02x", whoami);
return PX4_ERROR;
}
return PX4_OK;
}
void IST8308::Run()
void IST8308::RunImpl()
{
switch (_state.load()) {
switch (_state) {
case STATE::RESET:
// CNTL3: Software Reset
RegisterSetAndClearBits(Register::CNTL3, CNTL3_BIT::SRST, 0);
_reset_timestamp = hrt_absolute_time();
_state.store(STATE::WAIT_FOR_RESET);
_state = STATE::WAIT_FOR_RESET;
ScheduleDelayed(50_ms); // Power On Reset: max:50ms
break;
@@ -127,14 +118,14 @@ void IST8308::Run()
&& ((RegisterRead(Register::CNTL3) & CNTL3_BIT::SRST) == 0)) {
// if reset succeeded then configure
_state.store(STATE::CONFIGURE);
_state = STATE::CONFIGURE;
ScheduleNow();
} else {
// RESET not complete
if (hrt_elapsed_time(&_reset_timestamp) > 100_ms) {
PX4_ERR("Reset failed, retrying");
_state.store(STATE::RESET);
_state = STATE::RESET;
ScheduleNow();
} else {
@@ -148,7 +139,7 @@ void IST8308::Run()
case STATE::CONFIGURE:
if (Configure()) {
// if configure succeeded then start reading every 20 ms (50 Hz)
_state.store(STATE::READ);
_state = STATE::READ;
ScheduleOnInterval(20_ms, 20_ms);
} else {
@@ -203,22 +194,13 @@ void IST8308::Run()
} else {
// register check failed, force reconfigure
PX4_DEBUG("Health check failed, reconfiguring");
_state.store(STATE::CONFIGURE);
_state = STATE::CONFIGURE;
ScheduleNow();
}
}
}
break;
case STATE::REQUEST_STOP:
ScheduleClear();
_state.store(STATE::STOPPED);
break;
case STATE::STOPPED:
// DO NOTHING
break;
}
}

View File

@@ -47,22 +47,31 @@
#include <lib/drivers/magnetometer/PX4Magnetometer.hpp>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/atomic.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <px4_platform_common/i2c_spi_buses.h>
using namespace iSentek_IST8308;
class IST8308 : public device::I2C, public px4::ScheduledWorkItem
class IST8308 : public device::I2C, public I2CSPIDriver<IST8308>
{
public:
IST8308(int bus, uint8_t address = I2C_ADDRESS_DEFAULT, enum Rotation rotation = ROTATION_NONE);
IST8308(I2CSPIBusOption bus_option, int bus, enum Rotation rotation, int bus_frequency);
~IST8308() override;
bool Init();
void Start();
void Stop();
bool Reset();
void PrintInfo();
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void print_status();
int init() override;
void Start();
bool Reset();
void RunImpl();
protected:
void custom_method(const BusCLIArguments &cli) override;
private:
// Sensor Configuration
@@ -74,8 +83,6 @@ private:
int probe() override;
void Run() override;
bool Configure();
bool RegisterCheck(const register_config_t &reg_cfg, bool notify = false);
@@ -100,11 +107,9 @@ private:
WAIT_FOR_RESET,
CONFIGURE,
READ,
REQUEST_STOP,
STOPPED,
};
px4::atomic<STATE> _state{STATE::RESET};
STATE _state{STATE::RESET};
static constexpr uint8_t size_register_cfg{5};
register_config_t _register_cfg[size_register_cfg] {

View File

@@ -34,177 +34,83 @@
#include "IST8308.hpp"
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
namespace ist8308
void
IST8308::print_usage()
{
enum class BUS {
ALL = 0,
I2C_EXTERNAL = 1,
I2C_EXTERNAL1 = 2,
I2C_EXTERNAL2 = 3,
I2C_EXTERNAL3 = 4,
I2C_INTERNAL = 5,
};
struct bus_option {
BUS busid;
uint8_t busnum;
IST8308 *dev;
} bus_options[] = {
#if defined(PX4_I2C_BUS_ONBOARD)
{ BUS::I2C_INTERNAL, PX4_I2C_BUS_ONBOARD, nullptr },
#endif
#if defined(PX4_I2C_BUS_EXPANSION)
{ BUS::I2C_EXTERNAL, PX4_I2C_BUS_EXPANSION, nullptr },
#endif
#if defined(PX4_I2C_BUS_EXPANSION1)
{ BUS::I2C_EXTERNAL1, PX4_I2C_BUS_EXPANSION1, nullptr },
#endif
#if defined(PX4_I2C_BUS_EXPANSION2)
{ BUS::I2C_EXTERNAL2, PX4_I2C_BUS_EXPANSION2, nullptr },
#endif
#if defined(PX4_I2C_BUS_EXPANSION3)
{ BUS::I2C_EXTERNAL3, PX4_I2C_BUS_EXPANSION3, nullptr },
#endif
};
// find a bus structure for a busid
static bus_option *find_bus(BUS busid)
{
for (bus_option &bus_option : bus_options) {
if ((busid == BUS::ALL || busid == bus_option.busid)
&& bus_option.dev != nullptr) {
return &bus_option;
}
}
return nullptr;
PRINT_MODULE_USAGE_NAME("ist8308", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("magnetometer");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_PARAM_INT('R', 0, 0, 35, "Rotation", true);
PRINT_MODULE_USAGE_COMMAND("reset");
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
static bool start_bus(bus_option &bus, enum Rotation rotation)
I2CSPIDriverBase *IST8308::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
{
IST8308 *dev = new IST8308(bus.busnum, I2C_ADDRESS_DEFAULT, rotation);
IST8308 *instance = new IST8308(iterator.configuredBusOption(), iterator.bus(), cli.rotation, cli.bus_frequency);
if (dev == nullptr) {
if (!instance) {
PX4_ERR("alloc failed");
return false;
return nullptr;
}
if (!dev->Init()) {
PX4_ERR("driver start failed");
delete dev;
return false;
if (OK != instance->init()) {
delete instance;
return nullptr;
}
bus.dev = dev;
return true;
return instance;
}
static int start(BUS busid, enum Rotation rotation)
void IST8308::custom_method(const BusCLIArguments &cli)
{
for (bus_option &bus_option : bus_options) {
if (bus_option.dev != nullptr) {
// this device is already started
PX4_WARN("already started");
continue;
}
if (busid != BUS::ALL && bus_option.busid != busid) {
// not the one that is asked for
continue;
}
if (start_bus(bus_option, rotation)) {
return 0;
}
}
return -1;
Reset();
}
static int stop(BUS busid)
{
bus_option *bus = find_bus(busid);
if (bus != nullptr && bus->dev != nullptr) {
delete bus->dev;
bus->dev = nullptr;
} else {
PX4_WARN("driver not running");
return -1;
}
return 0;
}
static int status(BUS busid)
{
bus_option *bus = find_bus(busid);
if (bus != nullptr && bus->dev != nullptr) {
bus->dev->PrintInfo();
return 0;
}
PX4_WARN("driver not running");
return -1;
}
static int usage()
{
PX4_INFO("missing command: try 'start', 'stop', 'status'");
PX4_INFO("options:");
PX4_INFO(" -R rotation");
return 0;
}
} // namespace ist8308
extern "C" int ist8308_main(int argc, char *argv[])
{
enum Rotation rotation = ROTATION_NONE;
int myoptind = 1;
int ch = 0;
const char *myoptarg = nullptr;
ist8308::BUS busid = ist8308::BUS::ALL;
int ch;
using ThisDriver = IST8308;
BusCLIArguments cli{true, false};
cli.default_i2c_frequency = I2C_SPEED;
// start options
while ((ch = px4_getopt(argc, argv, "R:b:", &myoptind, &myoptarg)) != EOF) {
while ((ch = cli.getopt(argc, argv, "R:")) != EOF) {
switch (ch) {
case 'R':
rotation = (enum Rotation)atoi(myoptarg);
cli.rotation = (enum Rotation)atoi(cli.optarg());
break;
case 'b':
busid = (ist8308::BUS)atoi(myoptarg);
break;
default:
return ist8308::usage();
}
}
if (myoptind >= argc) {
return ist8308::usage();
const char *verb = cli.optarg();
if (!verb) {
ThisDriver::print_usage();
return -1;
}
const char *verb = argv[myoptind];
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_MAG_DEVTYPE_IST8308);
if (!strcmp(verb, "start")) {
return ist8308::start(busid, rotation);
} else if (!strcmp(verb, "stop")) {
return ist8308::stop(busid);
} else if (!strcmp(verb, "status")) {
return ist8308::status(busid);
return ThisDriver::module_start(cli, iterator);
}
return ist8308::usage();
if (!strcmp(verb, "stop")) {
return ThisDriver::module_stop(iterator);
}
if (!strcmp(verb, "status")) {
return ThisDriver::module_status(iterator);
}
if (!strcmp(verb, "reset")) {
return ThisDriver::module_custom_method(cli, iterator);
}
ThisDriver::print_usage();
return -1;
}