Skip to content

Commit 9e89458

Browse files
authored
Merge pull request #11584 from SteveCEvans/fix_ICM_20689
Fix ICM-20689 initialisation
2 parents 1a6fa4d + 3af0ee7 commit 9e89458

File tree

5 files changed

+78
-29
lines changed

5 files changed

+78
-29
lines changed

src/main/drivers/accgyro/accgyro_mpu.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767

6868
#define MPU_INQUIRY_MASK 0x7E
6969

70+
// Allow 100ms before attempting to access SPI bus
71+
#define GYRO_SPI_STARTUP_MS 100
72+
7073
// Need to see at least this many interrupts during initialisation to confirm EXTI connectivity
7174
#define GYRO_EXTI_DETECT_THRESHOLD 1000
7275

@@ -384,6 +387,10 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro, const gyro
384387

385388
uint8_t sensor = MPU_NONE;
386389

390+
// Allow 100ms before attempting to access gyro's SPI bus
391+
// Do this once here rather than in each detection routine to speed boot
392+
while (millis() < GYRO_SPI_STARTUP_MS);
393+
387394
// It is hard to use hardware to optimize the detection loop here,
388395
// as hardware type and detection function name doesn't match.
389396
// May need a bitmap of hardware to detection function to do it right?

src/main/drivers/accgyro/accgyro_spi_icm20689.c

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,52 @@
3636
#include "drivers/sensor.h"
3737
#include "drivers/time.h"
3838

39-
40-
4139
// 10 MHz max SPI frequency
42-
#define ICM20689_MAX_SPI_CLK_HZ 10000000
40+
#define ICM20689_MAX_SPI_CLK_HZ 8000000
4341

4442
// 10 MHz max SPI frequency for intialisation
4543
#define ICM20689_MAX_SPI_INIT_CLK_HZ 1000000
4644

45+
// Register 0x37 - INT_PIN_CFG / Pin Bypass Enable Configuration
46+
#define ICM20689_INT_ANYRD_2CLEAR 0x10
47+
48+
// Register 0x68 - SIGNAL_PATH_RESET / Pin Bypass Enable Configuration
49+
#define ICM20689_ACCEL_RST 0x02
50+
#define ICM20689_TEMP_RST 0x01
51+
52+
// Register 0x6a - USER_CTRL / User Control
53+
#define ICM20689_I2C_IF_DIS 0x10
54+
55+
// Register 0x6b - PWR_MGMT_1 / Power Management 1
56+
#define ICM20689_BIT_RESET 0x80
57+
58+
/* Allow CLKSEL setting time to settle when PLL is selected
59+
*
60+
* Not specified in the ICM-20689 datasheet, but in the ICM-20690 datasheet,
61+
*
62+
* https://invensense.tdk.com/wp-content/uploads/2016/10/DS-000178-ICM-20690-v1.0.pdf
63+
*
64+
* says (section 10.11) that the clock selection takes ~20us to settle. Testing
65+
* has shown that 60us is required, so double to allow a margin
66+
*/
67+
#define ICM20689_CLKSEL_SETTLE_US 120
68+
69+
/* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
70+
*
71+
* https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
72+
*
73+
* says (section 4.28) suggest a delay of 100ms after a reset
74+
*/
75+
#define ICM20689_RESET_DELAY_MS 100
76+
77+
/* Not specified in the ICM-20689 datasheet, but in the MPU-6000 datasheet,
78+
*
79+
* https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
80+
*
81+
* says (section 4.28) suggest a delay of 100ms after a path reset
82+
*/
83+
#define ICM20689_PATH_RESET_DELAY_MS 100
84+
4785
static void icm20689SpiInit(const extDevice_t *dev)
4886
{
4987
static bool hardwareInitialised = false;
@@ -52,7 +90,6 @@ static void icm20689SpiInit(const extDevice_t *dev)
5290
return;
5391
}
5492

55-
5693
spiSetClkDivisor(dev, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ));
5794

5895
hardwareInitialised = true;
@@ -64,13 +101,12 @@ uint8_t icm20689SpiDetect(const extDevice_t *dev)
64101

65102
spiSetClkDivisor(dev, spiCalculateDivider(ICM20689_MAX_SPI_INIT_CLK_HZ));
66103

104+
// Note that the following reset is being done repeatedly by each MPU6000
105+
// compatible device being probed
106+
67107
// reset the device configuration
68108
spiWriteReg(dev, MPU_RA_PWR_MGMT_1, ICM20689_BIT_RESET);
69-
delay(100);
70-
71-
// reset the device signal paths
72-
spiWriteReg(dev, MPU_RA_SIGNAL_PATH_RESET, 0x03);
73-
delay(100);
109+
delay(ICM20689_RESET_DELAY_MS);
74110

75111
uint8_t icmDetected;
76112

@@ -91,11 +127,21 @@ uint8_t icm20689SpiDetect(const extDevice_t *dev)
91127
break;
92128
default:
93129
icmDetected = MPU_NONE;
94-
break;
130+
return icmDetected;
95131
}
96132

133+
// We now know the device is recognised so it's safe to perform device
134+
// specific register accesses
97135
spiSetClkDivisor(dev, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ));
98136

137+
// Disable Primary I2C Interface
138+
spiWriteReg(dev, MPU_RA_USER_CTRL, ICM20689_I2C_IF_DIS);
139+
140+
// Reset the device signal paths
141+
spiWriteReg(dev, MPU_RA_SIGNAL_PATH_RESET, ICM20689_ACCEL_RST | ICM20689_TEMP_RST);
142+
143+
delay(ICM20689_PATH_RESET_DELAY_MS);
144+
99145
return icmDetected;
100146
}
101147

@@ -129,24 +175,17 @@ void icm20689GyroInit(gyroDev_t *gyro)
129175
// Device was already reset during detection so proceed with configuration
130176

131177
spiWriteReg(&gyro->dev, MPU_RA_PWR_MGMT_1, INV_CLK_PLL);
132-
delay(15);
178+
delayMicroseconds(ICM20689_CLKSEL_SETTLE_US);
133179
spiWriteReg(&gyro->dev, MPU_RA_GYRO_CONFIG, INV_FSR_2000DPS << 3);
134-
delay(15);
135180
spiWriteReg(&gyro->dev, MPU_RA_ACCEL_CONFIG, INV_FSR_16G << 3);
136-
delay(15);
137181
spiWriteReg(&gyro->dev, MPU_RA_CONFIG, mpuGyroDLPF(gyro));
138-
delay(15);
139-
spiWriteReg(&gyro->dev, MPU_RA_SMPLRT_DIV, gyro->mpuDividerDrops); // Get Divider Drops
140-
delay(100);
182+
spiWriteReg(&gyro->dev, MPU_RA_SMPLRT_DIV, gyro->mpuDividerDrops);
141183

142184
// Data ready interrupt configuration
143-
// spiWriteReg(&gyro->dev, MPU_RA_INT_PIN_CFG, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0); // INT_ANYRD_2CLEAR, BYPASS_EN
144-
spiWriteReg(&gyro->dev, MPU_RA_INT_PIN_CFG, 0x10); // INT_ANYRD_2CLEAR, BYPASS_EN
145-
146-
delay(15);
185+
spiWriteReg(&gyro->dev, MPU_RA_INT_PIN_CFG, ICM20689_INT_ANYRD_2CLEAR);
147186

148187
#ifdef USE_MPU_DATA_READY_SIGNAL
149-
spiWriteReg(&gyro->dev, MPU_RA_INT_ENABLE, 0x01); // RAW_RDY_EN interrupt enable
188+
spiWriteReg(&gyro->dev, MPU_RA_INT_ENABLE, MPU_RF_DATA_RDY_EN);
150189
#endif
151190

152191
spiSetClkDivisor(&gyro->dev, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ));

src/main/drivers/accgyro/accgyro_spi_icm20689.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
#include "drivers/bus.h"
2424

25-
#define ICM20689_BIT_RESET (0x80)
26-
2725
bool icm20689AccDetect(accDev_t *acc);
2826
bool icm20689GyroDetect(gyroDev_t *gyro);
2927

src/main/drivers/accgyro/accgyro_spi_mpu6000.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,6 @@ uint8_t mpu6000SpiDetect(const extDevice_t *dev)
138138
spiWriteReg(dev, MPU_RA_PWR_MGMT_1, BIT_H_RESET);
139139
delay(100); // datasheet specifies a 100ms delay after reset
140140

141-
// reset the device signal paths
142-
spiWriteReg(dev, MPU_RA_SIGNAL_PATH_RESET, BIT_GYRO | BIT_ACC | BIT_TEMP);
143-
delay(100); // datasheet specifies a 100ms delay after signal path reset
144-
145141

146142
const uint8_t whoAmI = spiReadRegMsk(dev, MPU_RA_WHO_AM_I);
147143
delayMicroseconds(1); // Ensure CS high time is met which is violated on H7 without this delay
@@ -168,9 +164,14 @@ uint8_t mpu6000SpiDetect(const extDevice_t *dev)
168164
case MPU6000_REV_D10:
169165
detectedSensor = MPU_60x0_SPI;
170166
}
167+
168+
spiSetClkDivisor(dev, spiCalculateDivider(MPU6000_MAX_SPI_CLK_HZ));
169+
170+
// reset the device signal paths
171+
spiWriteReg(dev, MPU_RA_SIGNAL_PATH_RESET, BIT_GYRO | BIT_ACC | BIT_TEMP);
172+
delay(100); // datasheet specifies a 100ms delay after signal path reset
171173
}
172174

173-
spiSetClkDivisor(dev, spiCalculateDivider(MPU6000_MAX_SPI_CLK_HZ));
174175
return detectedSensor;
175176
}
176177

src/main/drivers/accgyro/accgyro_spi_mpu6500.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
static void mpu6500SpiInit(const extDevice_t *dev)
4848
{
4949

50-
spiSetClkDivisor(dev, spiCalculateDivider(MPU6500_MAX_SPI_CLK_HZ));
50+
spiSetClkDivisor(dev, spiCalculateDivider(MPU6500_MAX_SPI_INIT_CLK_HZ));
5151
}
5252

5353
uint8_t mpu6500SpiDetect(const extDevice_t *dev)
@@ -82,7 +82,11 @@ uint8_t mpu6500SpiDetect(const extDevice_t *dev)
8282
break;
8383
default:
8484
mpuDetected = MPU_NONE;
85+
return mpuDetected;
8586
}
87+
88+
spiSetClkDivisor(dev, spiCalculateDivider(MPU6500_MAX_SPI_CLK_HZ));
89+
8690
return mpuDetected;
8791
}
8892

0 commit comments

Comments
 (0)