mpu9250:mag restructure to have proper retires for setup

We want to setup the mag interface with retries and report
  failurs.

  Move retry logic to contol point, instead of hiding re-reading
  the ID in ak8963_check_id.

  Allow it to fail once to overcome a read of 0 on firt read.
  after 2 failure report error to console and reset the
  mpu9250's I2C master (SPI to I2C bridge)

  The same retry logic is used on the ak8963_read_adjustments
  with a reset of the I2C master module after 5 fails. If it
  fails fter 10 retires. Disabel the mad and report the failure
  on the console, stating it is disabled.
This commit is contained in:
David Sidrane 2017-07-07 16:05:29 -10:00 committed by Lorenz Meier
parent 270dd5282a
commit aec109ac2c
3 changed files with 59 additions and 32 deletions

View File

@ -41,6 +41,7 @@
*/
#include <px4_config.h>
#include <px4_log.h>
#include <sys/types.h>
#include <stdint.h>
@ -470,18 +471,11 @@ MPU9250_mag::read_reg(unsigned int reg)
bool
MPU9250_mag::ak8963_check_id(void)
MPU9250_mag::ak8963_check_id(uint8_t &deviceid)
{
for (int i = 0; i < 5; i++) {
deviceid = read_reg(AK8963REG_WIA);
uint8_t deviceid = read_reg(AK8963REG_WIA);
if (AK8963_DEVICE_ID == deviceid) {
return true;
}
}
return false;
return (AK8963_DEVICE_ID == deviceid);
}
/*
@ -552,42 +546,71 @@ MPU9250_mag::ak8963_read_adjustments(void)
return true;
}
bool
int
MPU9250_mag::ak8963_setup(void)
{
int retries = 10;
/* Configures the parent to act in master mode */
if (_interface == nullptr) {
uint8_t user_ctrl = _parent->read_reg(MPUREG_USER_CTRL);
_parent->write_checked_reg(MPUREG_USER_CTRL, user_ctrl | BIT_I2C_MST_EN);
_parent->write_reg(MPUREG_I2C_MST_CTRL, BIT_I2C_MST_P_NSR | BIT_I2C_MST_WAIT_FOR_ES | BITS_I2C_MST_CLOCK_400HZ);
do {
} else {
// uint8_t user_ctrl = _parent->read_reg(MPUREG_USER_CTRL);
/* When _interface is null we are using SPI and must
* use the parent interface to configure the device to act
* in master mode (SPI to I2C bridge)
*/
if (_interface == nullptr) {
_parent->modify_checked_reg(MPUREG_USER_CTRL, 0, BIT_I2C_MST_EN);
_parent->write_reg(MPUREG_I2C_MST_CTRL, BIT_I2C_MST_P_NSR | BIT_I2C_MST_WAIT_FOR_ES | BITS_I2C_MST_CLOCK_400HZ);
// // Passthrough mode
// _parent->write_checked_reg(MPUREG_USER_CTRL, user_ctrl & (~BIT_I2C_MST_EN));
}
} else {
_parent->modify_checked_reg(MPUREG_USER_CTRL, BIT_I2C_MST_EN, 0);
}
if (!ak8963_check_id()) {
::printf("AK8963: bad id\n");
}
uint8_t id = 0;
while (!ak8963_read_adjustments()) {
if (!retries--) {
::printf("AK8963: failed to read adjustment data\n");
if (ak8963_check_id(id)) {
break;
}
retries--;
if (retries < 8) {
PX4_ERR("AK8963: bad id %d retries %d", id, retries);
_parent->modify_checked_reg(MPUREG_USER_CTRL, 0, BIT_I2C_MST_RST);
up_udelay(100);
}
} while (retries > 0);
if (retries > 0) {
retries = 10;
while (!ak8963_read_adjustments() && retries) {
retries--;
PX4_ERR("AK8963: failed to read adjustment data. Retries %d", retries);
if (retries == 5) {
_parent->modify_checked_reg(MPUREG_USER_CTRL, 0, BIT_I2C_MST_RST);
up_udelay(100);
}
}
}
if (retries == 0) {
PX4_ERR("AK8963: failed to initialize, disabled!");
_parent->modify_checked_reg(MPUREG_USER_CTRL, 0, BIT_I2C_MST_RST);
_parent->write_reg(MPUREG_I2C_MST_CTRL, 0);
return -EIO;
}
write_reg(AK8963REG_CNTL1, AK8963_CONTINUOUS_MODE2 | AK8963_16BIT_ADC);
if (_interface == NULL) {
/* Configure mpu to internally read ak8963 data */
/* Configure mpu' I2c Master interface to read ak8963 data
* Into to fifo
*/
set_passthrough(AK8963REG_ST1, sizeof(struct ak8963_regs));
}
return true;
return OK;
}

View File

@ -104,9 +104,9 @@ public:
void passthrough_write(uint8_t reg, uint8_t val);
void read_block(uint8_t reg, uint8_t *val, uint8_t count);
void ak8963_reset(void);
bool ak8963_setup(void);
bool ak8963_check_id(void);
int ak8963_reset(void);
int ak8963_setup(void);
bool ak8963_check_id(uint8_t &id);
bool ak8963_read_adjustments(void);
protected:

View File

@ -388,6 +388,10 @@ int MPU9250::reset()
usleep(1000);
// Enable I2C bus or Disable I2C bus (recommended on data sheet)
write_checked_reg(MPUREG_USER_CTRL, is_i2c() ? 0 : BIT_I2C_IF_DIS);
// SAMPLE RATE
_set_sample_rate(_sample_rate);