2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #include "build/atomic.h"
29 #include "build/build_config.h"
30 #include "build/debug.h"
32 #include "common/maths.h"
33 #include "common/utils.h"
35 #include "drivers/bus.h"
36 #include "drivers/bus_i2c.h"
37 #include "drivers/bus_spi.h"
38 #include "drivers/exti.h"
39 #include "drivers/io.h"
40 #include "drivers/nvic.h"
41 #include "drivers/sensor.h"
42 #include "drivers/system.h"
43 #include "drivers/time.h"
45 #include "drivers/accgyro/accgyro.h"
46 #include "drivers/accgyro/accgyro_mpu3050.h"
47 #include "drivers/accgyro/accgyro_mpu6050.h"
48 #include "drivers/accgyro/accgyro_mpu6500.h"
49 #include "drivers/accgyro/accgyro_spi_bmi160.h"
50 #include "drivers/accgyro/accgyro_spi_bmi270.h"
51 #include "drivers/accgyro/accgyro_spi_icm20649.h"
52 #include "drivers/accgyro/accgyro_spi_icm20689.h"
53 #include "drivers/accgyro/accgyro_spi_icm426xx.h"
54 #include "drivers/accgyro/accgyro_spi_lsm6dso.h"
55 #include "drivers/accgyro/accgyro_spi_mpu6000.h"
56 #include "drivers/accgyro/accgyro_spi_mpu6500.h"
57 #include "drivers/accgyro/accgyro_spi_mpu9250.h"
58 #include "drivers/accgyro/accgyro_spi_l3gd20.h"
59 #include "drivers/accgyro/accgyro_mpu.h"
62 #include "pg/gyrodev.h"
65 #define MPU_ADDRESS 0x68
68 #define MPU_INQUIRY_MASK 0x7E
70 // Need to see at least this many interrupts during initialisation to confirm EXTI connectivity
71 #define GYRO_EXTI_DETECT_THRESHOLD 1000
74 static void mpu6050FindRevision(gyroDev_t
*gyro
)
76 // There is a map of revision contained in the android source tree which is quite comprehensive and may help to understand this code
77 // See https://android.googlesource.com/kernel/msm.git/+/eaf36994a3992b8f918c18e4f7411e8b2320a35f/drivers/misc/mpu6050/mldl_cfg.c
79 // determine product ID and revision
80 uint8_t readBuffer
[6];
81 bool ack
= busReadRegisterBuffer(&gyro
->dev
, MPU_RA_XA_OFFS_H
, readBuffer
, 6);
82 uint8_t revision
= ((readBuffer
[5] & 0x01) << 2) | ((readBuffer
[3] & 0x01) << 1) | (readBuffer
[1] & 0x01);
83 if (ack
&& revision
) {
84 // Congrats, these parts are better
86 gyro
->mpuDetectionResult
.resolution
= MPU_HALF_RESOLUTION
;
87 } else if (revision
== 2) {
88 gyro
->mpuDetectionResult
.resolution
= MPU_FULL_RESOLUTION
;
89 } else if ((revision
== 3) || (revision
== 7)) {
90 gyro
->mpuDetectionResult
.resolution
= MPU_FULL_RESOLUTION
;
92 failureMode(FAILURE_ACC_INCOMPATIBLE
);
96 ack
= busReadRegisterBuffer(&gyro
->dev
, MPU_RA_PRODUCT_ID
, &productId
, 1);
97 revision
= productId
& 0x0F;
98 if (!ack
|| revision
== 0) {
99 failureMode(FAILURE_ACC_INCOMPATIBLE
);
100 } else if (revision
== 4) {
101 gyro
->mpuDetectionResult
.resolution
= MPU_HALF_RESOLUTION
;
103 gyro
->mpuDetectionResult
.resolution
= MPU_FULL_RESOLUTION
;
110 * Gyro interrupt service routine
114 // Called in ISR context
115 // Gyro read has just completed
116 busStatus_e
mpuIntcallback(uint32_t arg
)
118 gyroDev_t
*gyro
= (gyroDev_t
*)arg
;
119 int32_t gyroDmaDuration
= cmpTimeCycles(getCycleCounter(), gyro
->gyroLastEXTI
);
121 if (gyroDmaDuration
> gyro
->gyroDmaMaxDuration
) {
122 gyro
->gyroDmaMaxDuration
= gyroDmaDuration
;
125 gyro
->dataReady
= true;
130 static void mpuIntExtiHandler(extiCallbackRec_t
*cb
)
132 gyroDev_t
*gyro
= container_of(cb
, gyroDev_t
, exti
);
134 // Ideally we'd use a time to capture such information, but unfortunately the port used for EXTI interrupt does
135 // not have an associated timer
136 uint32_t nowCycles
= getCycleCounter();
137 int32_t gyroLastPeriod
= cmpTimeCycles(nowCycles
, gyro
->gyroLastEXTI
);
138 // This detects the short (~79us) EXTI interval of an MPU6xxx gyro
139 if ((gyro
->gyroShortPeriod
== 0) || (gyroLastPeriod
< gyro
->gyroShortPeriod
)) {
140 gyro
->gyroSyncEXTI
= gyro
->gyroLastEXTI
+ gyro
->gyroDmaMaxDuration
;
142 gyro
->gyroLastEXTI
= nowCycles
;
144 if (gyro
->gyroModeSPI
== GYRO_EXTI_INT_DMA
) {
145 spiSequence(&gyro
->dev
, gyro
->segments
);
148 gyro
->detectedEXTI
++;
151 static void mpuIntExtiHandler(extiCallbackRec_t
*cb
)
153 gyroDev_t
*gyro
= container_of(cb
, gyroDev_t
, exti
);
154 gyro
->dataReady
= true;
158 static void mpuIntExtiInit(gyroDev_t
*gyro
)
160 if (gyro
->mpuIntExtiTag
== IO_TAG_NONE
) {
164 const IO_t mpuIntIO
= IOGetByTag(gyro
->mpuIntExtiTag
);
166 #ifdef ENSURE_MPU_DATA_READY_IS_LOW
167 uint8_t status
= IORead(mpuIntIO
);
173 IOInit(mpuIntIO
, OWNER_GYRO_EXTI
, 0);
174 EXTIHandlerInit(&gyro
->exti
, mpuIntExtiHandler
);
175 EXTIConfig(mpuIntIO
, &gyro
->exti
, NVIC_PRIO_MPU_INT_EXTI
, IOCFG_IN_FLOATING
, BETAFLIGHT_EXTI_TRIGGER_RISING
);
176 EXTIEnable(mpuIntIO
, true);
178 #endif // USE_GYRO_EXTI
180 bool mpuAccRead(accDev_t
*acc
)
184 const bool ack
= busReadRegisterBuffer(&acc
->gyro
->dev
, acc
->gyro
->accDataReg
, data
, 6);
189 acc
->ADCRaw
[X
] = (int16_t)((data
[0] << 8) | data
[1]);
190 acc
->ADCRaw
[Y
] = (int16_t)((data
[2] << 8) | data
[3]);
191 acc
->ADCRaw
[Z
] = (int16_t)((data
[4] << 8) | data
[5]);
196 bool mpuGyroRead(gyroDev_t
*gyro
)
200 const bool ack
= busReadRegisterBuffer(&gyro
->dev
, gyro
->gyroDataReg
, data
, 6);
205 gyro
->gyroADCRaw
[X
] = (int16_t)((data
[0] << 8) | data
[1]);
206 gyro
->gyroADCRaw
[Y
] = (int16_t)((data
[2] << 8) | data
[3]);
207 gyro
->gyroADCRaw
[Z
] = (int16_t)((data
[4] << 8) | data
[5]);
214 bool mpuAccReadSPI(accDev_t
*acc
)
216 switch (acc
->gyro
->gyroModeSPI
) {
218 case GYRO_EXTI_NO_INT
:
220 acc
->gyro
->dev
.txBuf
[0] = MPU_RA_ACCEL_XOUT_H
| 0x80;
222 busSegment_t segments
[] = {
223 {.u
.buffers
= {NULL
, NULL
}, 7, true, NULL
},
224 {.u
.buffers
= {NULL
, NULL
}, 0, true, NULL
},
226 segments
[0].u
.buffers
.txData
= acc
->gyro
->dev
.txBuf
;
227 segments
[0].u
.buffers
.rxData
= &acc
->gyro
->dev
.rxBuf
[1];
229 spiSequence(&acc
->gyro
->dev
, &segments
[0]);
231 // Wait for completion
232 spiWait(&acc
->gyro
->dev
);
238 case GYRO_EXTI_INT_DMA
:
240 // If read was triggered in interrupt don't bother waiting. The worst that could happen is that we pick
243 // This data was read from the gyro, which is the same SPI device as the acc
244 uint16_t *accData
= (uint16_t *)acc
->gyro
->dev
.rxBuf
;
245 acc
->ADCRaw
[X
] = __builtin_bswap16(accData
[1]);
246 acc
->ADCRaw
[Y
] = __builtin_bswap16(accData
[2]);
247 acc
->ADCRaw
[Z
] = __builtin_bswap16(accData
[3]);
259 bool mpuGyroReadSPI(gyroDev_t
*gyro
)
261 uint16_t *gyroData
= (uint16_t *)gyro
->dev
.rxBuf
;
262 switch (gyro
->gyroModeSPI
) {
265 // Initialise the tx buffer to all 0xff
266 memset(gyro
->dev
.txBuf
, 0xff, 16);
268 // Check that minimum number of interrupts have been detected
270 // We need some offset from the gyro interrupts to ensure sampling after the interrupt
271 gyro
->gyroDmaMaxDuration
= 5;
272 if (gyro
->detectedEXTI
> GYRO_EXTI_DETECT_THRESHOLD
) {
273 if (spiUseDMA(&gyro
->dev
)) {
274 gyro
->dev
.callbackArg
= (uint32_t)gyro
;
275 gyro
->dev
.txBuf
[0] = gyro
->accDataReg
| 0x80;
276 gyro
->segments
[0].len
= gyro
->gyroDataReg
- gyro
->accDataReg
+ 7;
277 gyro
->segments
[0].callback
= mpuIntcallback
;
278 gyro
->segments
[0].u
.buffers
.txData
= gyro
->dev
.txBuf
;
279 gyro
->segments
[0].u
.buffers
.rxData
= &gyro
->dev
.rxBuf
[1];
280 gyro
->segments
[0].negateCS
= true;
281 gyro
->gyroModeSPI
= GYRO_EXTI_INT_DMA
;
283 // Interrupts are present, but no DMA
284 gyro
->gyroModeSPI
= GYRO_EXTI_INT
;
289 gyro
->gyroModeSPI
= GYRO_EXTI_NO_INT
;
295 case GYRO_EXTI_NO_INT
:
297 gyro
->dev
.txBuf
[0] = MPU_RA_GYRO_XOUT_H
| 0x80;
299 busSegment_t segments
[] = {
300 {.u
.buffers
= {NULL
, NULL
}, 7, true, NULL
},
301 {.u
.buffers
= {NULL
, NULL
}, 0, true, NULL
},
303 segments
[0].u
.buffers
.txData
= gyro
->dev
.txBuf
;
304 segments
[0].u
.buffers
.rxData
= &gyro
->dev
.rxBuf
[1];
306 spiSequence(&gyro
->dev
, &segments
[0]);
308 // Wait for completion
311 gyro
->gyroADCRaw
[X
] = __builtin_bswap16(gyroData
[1]);
312 gyro
->gyroADCRaw
[Y
] = __builtin_bswap16(gyroData
[2]);
313 gyro
->gyroADCRaw
[Z
] = __builtin_bswap16(gyroData
[3]);
317 case GYRO_EXTI_INT_DMA
:
319 // Acc and gyro data may not be continuous (MPU6xxx has temperature in between)
320 const uint8_t gyroDataIndex
= ((gyro
->gyroDataReg
- gyro
->accDataReg
) >> 1) + 1;
322 // If read was triggered in interrupt don't bother waiting. The worst that could happen is that we pick
324 gyro
->gyroADCRaw
[X
] = __builtin_bswap16(gyroData
[gyroDataIndex
]);
325 gyro
->gyroADCRaw
[Y
] = __builtin_bswap16(gyroData
[gyroDataIndex
+ 1]);
326 gyro
->gyroADCRaw
[Z
] = __builtin_bswap16(gyroData
[gyroDataIndex
+ 2]);
337 typedef uint8_t (*gyroSpiDetectFn_t
)(const extDevice_t
*dev
);
339 static gyroSpiDetectFn_t gyroSpiDetectFnTable
[] = {
340 #ifdef USE_GYRO_SPI_MPU6000
343 #ifdef USE_GYRO_SPI_MPU6500
344 mpu6500SpiDetect
, // some targets using MPU_9250_SPI, ICM_20608_SPI or ICM_20602_SPI state sensor is MPU_65xx_SPI
346 #ifdef USE_GYRO_SPI_MPU9250
349 #ifdef USE_GYRO_SPI_ICM20689
350 icm20689SpiDetect
, // icm20689SpiDetect detects ICM20602 and ICM20689
352 #ifdef USE_ACCGYRO_LSM6DSO
355 #ifdef USE_ACCGYRO_BMI160
358 #ifdef USE_ACCGYRO_BMI270
361 #if defined(USE_GYRO_SPI_ICM42605) || defined(USE_GYRO_SPI_ICM42688P)
364 #ifdef USE_GYRO_SPI_ICM20649
367 #ifdef USE_GYRO_L3GD20
370 NULL
// Avoid an empty array
373 static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t
*gyro
, const gyroDeviceConfig_t
*config
)
375 if (!config
->csnTag
|| !spiSetBusInstance(&gyro
->dev
, config
->spiBus
)) {
379 gyro
->dev
.busType_u
.spi
.csnPin
= IOGetByTag(config
->csnTag
);
381 IOInit(gyro
->dev
.busType_u
.spi
.csnPin
, OWNER_GYRO_CS
, RESOURCE_INDEX(config
->index
));
382 IOConfigGPIO(gyro
->dev
.busType_u
.spi
.csnPin
, SPI_IO_CS_CFG
);
383 IOHi(gyro
->dev
.busType_u
.spi
.csnPin
); // Ensure device is disabled, important when two devices are on the same bus.
385 uint8_t sensor
= MPU_NONE
;
387 // It is hard to use hardware to optimize the detection loop here,
388 // as hardware type and detection function name doesn't match.
389 // May need a bitmap of hardware to detection function to do it right?
391 for (size_t index
= 0 ; gyroSpiDetectFnTable
[index
] ; index
++) {
392 sensor
= (gyroSpiDetectFnTable
[index
])(&gyro
->dev
);
393 if (sensor
!= MPU_NONE
) {
394 gyro
->mpuDetectionResult
.sensor
= sensor
;
395 busDeviceRegister(&gyro
->dev
);
400 // Detection failed, disable CS pin again
402 spiPreinitByTag(config
->csnTag
);
408 void mpuPreInit(const struct gyroDeviceConfig_s
*config
)
411 spiPreinitRegister(config
->csnTag
, IOCFG_IPU
, 1);
417 bool mpuDetect(gyroDev_t
*gyro
, const gyroDeviceConfig_t
*config
)
419 static busDevice_t bus
;
420 gyro
->dev
.bus
= &bus
;
422 // MPU datasheet specifies 30ms.
425 if (config
->busType
== BUS_TYPE_NONE
) {
429 if (config
->busType
== BUS_TYPE_GYRO_AUTO
) {
430 gyro
->dev
.bus
->busType
= BUS_TYPE_I2C
;
432 gyro
->dev
.bus
->busType
= config
->busType
;
436 if (gyro
->dev
.bus
->busType
== BUS_TYPE_I2C
) {
437 gyro
->dev
.bus
->busType_u
.i2c
.device
= I2C_CFG_TO_DEV(config
->i2cBus
);
438 gyro
->dev
.busType_u
.i2c
.address
= config
->i2cAddress
? config
->i2cAddress
: MPU_ADDRESS
;
441 bool ack
= busReadRegisterBuffer(&gyro
->dev
, MPU_RA_WHO_AM_I
, &sig
, 1);
444 busDeviceRegister(&gyro
->dev
);
445 // If an MPU3050 is connected sig will contain 0.
446 uint8_t inquiryResult
;
447 ack
= busReadRegisterBuffer(&gyro
->dev
, MPU_RA_WHO_AM_I_LEGACY
, &inquiryResult
, 1);
448 inquiryResult
&= MPU_INQUIRY_MASK
;
449 if (ack
&& inquiryResult
== MPUx0x0_WHO_AM_I_CONST
) {
450 gyro
->mpuDetectionResult
.sensor
= MPU_3050
;
454 sig
&= MPU_INQUIRY_MASK
;
455 if (sig
== MPUx0x0_WHO_AM_I_CONST
) {
456 gyro
->mpuDetectionResult
.sensor
= MPU_60x0
;
457 mpu6050FindRevision(gyro
);
458 } else if (sig
== MPU6500_WHO_AM_I_CONST
) {
459 gyro
->mpuDetectionResult
.sensor
= MPU_65xx_I2C
;
467 gyro
->dev
.bus
->busType
= BUS_TYPE_SPI
;
469 return detectSPISensorsAndUpdateDetectionResult(gyro
, config
);
475 void mpuGyroInit(gyroDev_t
*gyro
)
477 gyro
->accDataReg
= MPU_RA_ACCEL_XOUT_H
;
478 gyro
->gyroDataReg
= MPU_RA_GYRO_XOUT_H
;
480 mpuIntExtiInit(gyro
);
486 uint8_t mpuGyroDLPF(gyroDev_t
*gyro
)
490 // If gyro is in 32KHz mode then the DLPF bits aren't used
491 if (gyro
->gyroRateKHz
<= GYRO_RATE_8_kHz
) {
492 switch (gyro
->hardware_lpf
) {
493 #ifdef USE_GYRO_DLPF_EXPERIMENTAL
494 case GYRO_HARDWARE_LPF_EXPERIMENTAL
:
495 // experimental mode not supported for MPU60x0 family
496 if ((gyro
->gyroHardware
!= GYRO_MPU6050
) && (gyro
->gyroHardware
!= GYRO_MPU6000
)) {
504 case GYRO_HARDWARE_LPF_NORMAL
:
513 #ifdef USE_GYRO_REGISTER_DUMP
514 uint8_t mpuGyroReadRegister(const extDevice_t
*dev
, uint8_t reg
)
517 const bool ack
= busReadRegisterBuffer(dev
, reg
, &data
, 1);