ak09916: PX4_ERR if reset/configure is failing after 5s

This commit is contained in:
Daniel Agar
2022-09-23 19:16:10 -04:00
parent 16b4149492
commit eb2a714aa5
5 changed files with 69 additions and 66 deletions
@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* *
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved. * Copyright (c) 2019-2022 PX4 Development Team. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -50,7 +50,6 @@ AK09916::AK09916(const I2CSPIDriverConfig &config) :
AK09916::~AK09916() AK09916::~AK09916()
{ {
perf_free(_reset_perf); perf_free(_reset_perf);
perf_free(_transfer_perf);
perf_free(_bad_register_perf); perf_free(_bad_register_perf);
perf_free(_bad_transfer_perf); perf_free(_bad_transfer_perf);
perf_free(_magnetic_sensor_overflow_perf); perf_free(_magnetic_sensor_overflow_perf);
@@ -65,8 +64,6 @@ int AK09916::init()
return ret; return ret;
} }
_retries = 2;
return Reset() ? 0 : -1; return Reset() ? 0 : -1;
} }
@@ -83,7 +80,6 @@ void AK09916::print_status()
I2CSPIDriverBase::print_status(); I2CSPIDriverBase::print_status();
perf_print_counter(_reset_perf); perf_print_counter(_reset_perf);
perf_print_counter(_transfer_perf);
perf_print_counter(_bad_register_perf); perf_print_counter(_bad_register_perf);
perf_print_counter(_bad_transfer_perf); perf_print_counter(_bad_transfer_perf);
perf_print_counter(_magnetic_sensor_overflow_perf); perf_print_counter(_magnetic_sensor_overflow_perf);
@@ -91,32 +87,39 @@ void AK09916::print_status()
int AK09916::probe() int AK09916::probe()
{ {
const uint8_t WIA1 = RegisterRead(Register::WIA1); // 3 retries
for (int i = 0; i < 3; i++) {
if (WIA1 != Company_ID) { const uint8_t WIA1 = RegisterRead(Register::WIA1);
DEVICE_DEBUG("unexpected WIA1 0x%02x", WIA1); const uint8_t WIA2 = RegisterRead(Register::WIA2);
return PX4_ERROR;
if ((WIA1 == Company_ID) && (WIA2 == Device_ID)) {
return PX4_OK;
}
if (WIA1 != Company_ID) {
DEVICE_DEBUG("unexpected WIA1 0x%02x", WIA1);
}
if (WIA2 != Device_ID) {
DEVICE_DEBUG("unexpected WIA2 0x%02x", WIA2);
}
} }
const uint8_t WIA2 = RegisterRead(Register::WIA2); return PX4_ERROR;
if (WIA2 != Device_ID) {
DEVICE_DEBUG("unexpected WIA2 0x%02x", WIA2);
return PX4_ERROR;
}
return PX4_OK;
} }
void AK09916::RunImpl() void AK09916::RunImpl()
{ {
const hrt_abstime now = hrt_absolute_time();
switch (_state) { switch (_state) {
case STATE::RESET: case STATE::RESET:
perf_count(_reset_perf); perf_count(_reset_perf);
// CNTL3 SRST: Soft reset // CNTL3 SRST: Soft reset
RegisterWrite(Register::CNTL3, CNTL3_BIT::SRST); RegisterWrite(Register::CNTL3, CNTL3_BIT::SRST);
_reset_timestamp = hrt_absolute_time(); _reset_timestamp = now;
_consecutive_failures = 0; _failure_count = 0;
_state = STATE::WAIT_FOR_RESET; _state = STATE::WAIT_FOR_RESET;
ScheduleDelayed(100_ms); ScheduleDelayed(100_ms);
break; break;
@@ -124,16 +127,14 @@ void AK09916::RunImpl()
case STATE::WAIT_FOR_RESET: case STATE::WAIT_FOR_RESET:
if ((RegisterRead(Register::WIA1) == Company_ID) && (RegisterRead(Register::WIA2) == Device_ID)) { if ((RegisterRead(Register::WIA1) == Company_ID) && (RegisterRead(Register::WIA2) == Device_ID)) {
// if reset succeeded then configure // if reset succeeded then configure
RegisterWrite(Register::CNTL2, CNTL2_BIT::MODE3);
_state = STATE::CONFIGURE; _state = STATE::CONFIGURE;
ScheduleDelayed(100_ms); ScheduleDelayed(100_ms);
} else { } else {
// RESET not complete // RESET not complete
if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { if (hrt_elapsed_time(&_reset_timestamp) > 30_s) {
PX4_DEBUG("Reset failed, retrying"); PX4_ERR("Reset failed, retrying");
_state = STATE::RESET; Reset();
ScheduleDelayed(100_ms);
} else { } else {
PX4_DEBUG("Reset not complete, check again in 100 ms"); PX4_DEBUG("Reset not complete, check again in 100 ms");
@@ -151,26 +152,34 @@ void AK09916::RunImpl()
} else { } else {
// CONFIGURE not complete // CONFIGURE not complete
if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { if (hrt_elapsed_time(&_reset_timestamp) > 30_s) {
PX4_DEBUG("Configure failed, resetting"); PX4_ERR("Configure failed, resetting");
_state = STATE::RESET; Reset();
} else { } else {
PX4_DEBUG("Configure failed, retrying"); PX4_DEBUG("Configure failed, retrying");
ScheduleDelayed(100_ms);
} }
ScheduleDelayed(100_ms);
} }
break; break;
case STATE::READ: { case STATE::READ: {
perf_begin(_transfer_perf);
TransferBuffer buffer{}; struct TransferBuffer {
const hrt_abstime timestamp_sample = hrt_absolute_time(); uint8_t ST1;
uint8_t HXL;
uint8_t HXH;
uint8_t HYL;
uint8_t HYH;
uint8_t HZL;
uint8_t HZH;
uint8_t TMPS;
uint8_t ST2;
} buffer{};
uint8_t cmd = static_cast<uint8_t>(Register::ST1); uint8_t cmd = static_cast<uint8_t>(Register::ST1);
int ret = transfer(&cmd, 1, (uint8_t *)&buffer, sizeof(TransferBuffer)); int ret = transfer(&cmd, 1, (uint8_t *)&buffer, sizeof(TransferBuffer));
perf_end(_transfer_perf);
bool success = false; bool success = false;
@@ -186,31 +195,39 @@ void AK09916::RunImpl()
// sensor's frame is +X forward (X), +Y right (Y), +Z down (Z) // sensor's frame is +X forward (X), +Y right (Y), +Z down (Z)
_px4_mag.set_error_count(perf_event_count(_bad_register_perf) + perf_event_count(_bad_transfer_perf) _px4_mag.set_error_count(perf_event_count(_bad_register_perf) + perf_event_count(_bad_transfer_perf)
+ perf_event_count(_magnetic_sensor_overflow_perf)); + perf_event_count(_magnetic_sensor_overflow_perf));
_px4_mag.update(timestamp_sample, x, y, z);
_px4_mag.update(now, x, y, z);
success = true; success = true;
_consecutive_failures = 0; if (_failure_count > 0) {
_failure_count--;
}
}
}
if (!success) {
_failure_count++;
// full reset if things are failing consistently
if (_failure_count > 10) {
Reset();
return;
} }
} }
if (!success || hrt_elapsed_time(&_last_config_check_timestamp) > 100_ms) { if (!success || hrt_elapsed_time(&_last_config_check_timestamp) > 100_ms) {
// check configuration registers periodically or immediately following any failure // check configuration registers periodically or immediately following any failure
if (RegisterCheck(_register_cfg[_checked_register])) { if (RegisterCheck(_register_cfg[_checked_register])) {
_last_config_check_timestamp = timestamp_sample; _last_config_check_timestamp = now;
_checked_register = (_checked_register + 1) % size_register_cfg; _checked_register = (_checked_register + 1) % size_register_cfg;
} else { } else {
// register check failed, force reset // register check failed, force reset
perf_count(_bad_register_perf); perf_count(_bad_register_perf);
Reset(); Reset();
return;
} }
} }
if (_consecutive_failures > 10) {
Reset();
}
} }
break; break;
@@ -219,9 +236,11 @@ void AK09916::RunImpl()
bool AK09916::Configure() bool AK09916::Configure()
{ {
_retries = 2;
// first set and clear all configured register bits // first set and clear all configured register bits
for (const auto &reg_cfg : _register_cfg) { for (const auto &reg_cfg : _register_cfg) {
RegisterWrite(reg_cfg.reg, reg_cfg.set_bits); RegisterSetAndClearBits(reg_cfg.reg, reg_cfg.set_bits, reg_cfg.clear_bits);
} }
// now check that all are configured // now check that all are configured
@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* *
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved. * Copyright (c) 2019-2022 PX4 Development Team. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -64,19 +64,6 @@ public:
void print_status() override; void print_status() override;
private: private:
struct TransferBuffer {
uint8_t ST1;
uint8_t HXL;
uint8_t HXH;
uint8_t HYL;
uint8_t HYH;
uint8_t HZL;
uint8_t HZH;
uint8_t TMPS;
uint8_t ST2;
};
struct register_config_t { struct register_config_t {
Register reg; Register reg;
uint8_t set_bits{0}; uint8_t set_bits{0};
@@ -98,14 +85,13 @@ private:
PX4Magnetometer _px4_mag; PX4Magnetometer _px4_mag;
perf_counter_t _reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": reset")}; perf_counter_t _reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": reset")};
perf_counter_t _transfer_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": transfer")};
perf_counter_t _bad_register_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad register")}; perf_counter_t _bad_register_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad register")};
perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")}; perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")};
perf_counter_t _magnetic_sensor_overflow_perf{perf_alloc(PC_COUNT, MODULE_NAME": magnetic sensor overflow")}; perf_counter_t _magnetic_sensor_overflow_perf{perf_alloc(PC_COUNT, MODULE_NAME": magnetic sensor overflow")};
hrt_abstime _reset_timestamp{0}; hrt_abstime _reset_timestamp{0};
hrt_abstime _last_config_check_timestamp{0}; hrt_abstime _last_config_check_timestamp{0};
unsigned _consecutive_failures{0}; int _failure_count{0};
enum class STATE : uint8_t { enum class STATE : uint8_t {
RESET, RESET,
@@ -118,6 +104,6 @@ private:
static constexpr uint8_t size_register_cfg{1}; static constexpr uint8_t size_register_cfg{1};
register_config_t _register_cfg[size_register_cfg] { register_config_t _register_cfg[size_register_cfg] {
// Register | Set bits, Clear bits // Register | Set bits, Clear bits
{ Register::CNTL2, CNTL2_BIT::MODE3, 0 }, { Register::CNTL2, CNTL2_BIT::MODE3_SET, CNTL2_BIT::MODE3_CLEAR },
}; };
}; };
@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* *
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved. * Copyright (c) 2019-2022 PX4 Development Team. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -93,10 +93,8 @@ enum ST2_BIT : uint8_t {
// CNTL2 // CNTL2
enum CNTL2_BIT : uint8_t { enum CNTL2_BIT : uint8_t {
// MODE[4:0] bits // MODE[4:0] bits
MODE1 = Bit1, // “00010”: Continuous measurement mode 1 (10Hz) MODE3_SET = Bit2 | Bit1, // “00110”: Continuous measurement mode 3 (50Hz)
MODE2 = Bit2, // “00100”: Continuous measurement mode 2 (20Hz) MODE3_CLEAR = Bit4 | Bit3 | Bit0,
MODE3 = Bit2 | Bit1, // “00110”: Continuous measurement mode 3 (50Hz)
MODE4 = Bit3, // “01000”: Continuous measurement mode 4 (100Hz)
}; };
// CNTL3 // CNTL3
@@ -1,6 +1,6 @@
############################################################################ ############################################################################
# #
# Copyright (c) 2019-2020 PX4 Development Team. All rights reserved. # Copyright (c) 2019-2022 PX4 Development Team. All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* *
* Copyright (c) 2020, 2021 PX4 Development Team. All rights reserved. * Copyright (c) 2019-2022 PX4 Development Team. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions