From 41a0ca43d1ca0ecd9d0164a38f17ae922e04749b Mon Sep 17 00:00:00 2001 From: Steve Evans Date: Tue, 25 Aug 2020 08:34:15 +0100 Subject: [PATCH] Run SPI FLASH at full speed --- src/main/drivers/accgyro/accgyro_spi_bmi160.c | 6 +- src/main/drivers/accgyro/accgyro_spi_bmi270.c | 6 +- .../drivers/accgyro/accgyro_spi_icm20649.c | 14 +- .../drivers/accgyro/accgyro_spi_icm20689.c | 16 +- .../drivers/accgyro/accgyro_spi_icm42605.c | 16 +- src/main/drivers/accgyro/accgyro_spi_l3gd20.c | 5 +- .../accgyro/accgyro_spi_lsm6dso_init.c | 5 +- .../drivers/accgyro/accgyro_spi_mpu6000.c | 17 +- .../drivers/accgyro/accgyro_spi_mpu6500.c | 11 +- .../drivers/accgyro/accgyro_spi_mpu9250.c | 15 +- src/main/drivers/barometer/barometer_bmp280.c | 7 +- src/main/drivers/barometer/barometer_bmp388.c | 4 +- src/main/drivers/barometer/barometer_dps310.c | 7 +- src/main/drivers/barometer/barometer_lps.c | 6 +- src/main/drivers/barometer/barometer_ms5611.c | 7 +- .../drivers/barometer/barometer_qmp6988.c | 7 +- src/main/drivers/bus_spi.c | 19 +++ src/main/drivers/bus_spi.h | 40 +---- src/main/drivers/bus_spi_ll.c | 2 +- src/main/drivers/bus_spi_stdperiph.c | 2 +- src/main/drivers/compass/compass_ak8963.c | 7 +- src/main/drivers/compass/compass_hmc5883l.c | 7 +- src/main/drivers/flash.c | 11 +- src/main/drivers/flash_m25p16.c | 148 +++++++++++------- src/main/drivers/flash_m25p16.h | 2 - src/main/drivers/flash_w25m.c | 1 + src/main/drivers/max7456.c | 18 ++- src/main/drivers/rx/rx_spi.c | 7 +- src/main/drivers/sdcard_spi.c | 18 +-- src/main/drivers/vtx_rtc6705.c | 7 +- src/main/target/AIRF7/target.h | 2 - src/main/target/IMPULSERCF3/target.h | 2 - src/main/target/NOX/target.h | 2 - src/main/target/STM32F3DISCOVERY/target.h | 3 - src/main/target/TMOTORF7/target.h | 2 - src/main/target/common_defaults_post.h | 8 - src/test/unit/baro_bmp280_unittest.cc | 4 + src/test/unit/baro_bmp388_unittest.cc | 4 + src/test/unit/baro_ms5611_unittest.cc | 4 + 39 files changed, 276 insertions(+), 193 deletions(-) diff --git a/src/main/drivers/accgyro/accgyro_spi_bmi160.c b/src/main/drivers/accgyro/accgyro_spi_bmi160.c index 4e46aea316..a0d785cfee 100644 --- a/src/main/drivers/accgyro/accgyro_spi_bmi160.c +++ b/src/main/drivers/accgyro/accgyro_spi_bmi160.c @@ -50,6 +50,9 @@ #include "accgyro_spi_bmi160.h" +// 10 MHz max SPI frequency +#define BMI160_MAX_SPI_CLK_HZ 10000000 + /* BMI160 Registers */ #define BMI160_REG_CHIPID 0x00 #define BMI160_REG_PMU_STAT 0x03 @@ -95,8 +98,7 @@ uint8_t bmi160Detect(const busDevice_t *bus) return BMI_160_SPI; } - - spiSetDivisor(bus->busdev_u.spi.instance, BMI160_SPI_DIVISOR); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(BMI160_MAX_SPI_CLK_HZ)); /* Read this address to activate SPI (see p. 84) */ spiBusReadRegister(bus, 0x7F); diff --git a/src/main/drivers/accgyro/accgyro_spi_bmi270.c b/src/main/drivers/accgyro/accgyro_spi_bmi270.c index 1d94ef91f5..9267f3e386 100644 --- a/src/main/drivers/accgyro/accgyro_spi_bmi270.c +++ b/src/main/drivers/accgyro/accgyro_spi_bmi270.c @@ -35,7 +35,9 @@ #include "drivers/sensor.h" #include "drivers/time.h" -#define BMI270_SPI_DIVISOR 16 +// 10 MHz max SPI frequency +#define BMI270_MAX_SPI_CLK_HZ 10000000 + #define BMI270_FIFO_FRAME_SIZE 6 #define BMI270_CONFIG_SIZE 8192 @@ -154,7 +156,7 @@ static void bmi270EnableSPI(const busDevice_t *bus) uint8_t bmi270Detect(const busDevice_t *bus) { - spiSetDivisor(bus->busdev_u.spi.instance, BMI270_SPI_DIVISOR); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(BMI270_MAX_SPI_CLK_HZ)); bmi270EnableSPI(bus); if (bmi270RegisterRead(bus, BMI270_REG_CHIP_ID) == BMI270_CHIP_ID) { diff --git a/src/main/drivers/accgyro/accgyro_spi_icm20649.c b/src/main/drivers/accgyro/accgyro_spi_icm20649.c index f793142938..4936b3bd0f 100644 --- a/src/main/drivers/accgyro/accgyro_spi_icm20649.c +++ b/src/main/drivers/accgyro/accgyro_spi_icm20649.c @@ -39,6 +39,9 @@ #include "drivers/time.h" +// 8 MHz max SPI frequency +#define ICM20649_MAX_SPI_CLK_HZ 8000000 + static void icm20649SpiInit(const busDevice_t *bus) { static bool hardwareInitialised = false; @@ -47,10 +50,7 @@ static void icm20649SpiInit(const busDevice_t *bus) return; } - - // all registers can be read/written at full speed (7MHz +-10%) - // TODO verify that this works at 9MHz and 10MHz on non F7 - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM20649_MAX_SPI_CLK_HZ)); hardwareInitialised = true; } @@ -59,7 +59,7 @@ uint8_t icm20649SpiDetect(const busDevice_t *bus) { icm20649SpiInit(bus); - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM20649_MAX_SPI_CLK_HZ)); spiBusWriteRegister(bus, ICM20649_RA_REG_BANK_SEL, 0 << 4); // select bank 0 just to be safe delay(15); @@ -94,7 +94,7 @@ void icm20649AccInit(accDev_t *acc) // 1,024 LSB/g 30g acc->acc_1G = acc->acc_high_fsr ? 1024 : 2048; - spiSetDivisor(acc->bus.busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(acc->bus.busdev_u.spi.instance, spiCalculateDivider(ICM20649_MAX_SPI_CLK_HZ)); spiBusWriteRegister(&acc->bus, ICM20649_RA_REG_BANK_SEL, 2 << 4); // config in bank 2 delay(15); @@ -122,7 +122,7 @@ void icm20649GyroInit(gyroDev_t *gyro) { mpuGyroInit(gyro); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_STANDARD); // ensure proper speed + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(ICM20649_MAX_SPI_CLK_HZ)); // ensure proper speed spiBusWriteRegister(&gyro->bus, ICM20649_RA_REG_BANK_SEL, 0 << 4); // select bank 0 just to be safe delay(15); diff --git a/src/main/drivers/accgyro/accgyro_spi_icm20689.c b/src/main/drivers/accgyro/accgyro_spi_icm20689.c index 7e5918d675..065a702451 100644 --- a/src/main/drivers/accgyro/accgyro_spi_icm20689.c +++ b/src/main/drivers/accgyro/accgyro_spi_icm20689.c @@ -37,6 +37,12 @@ #include "drivers/time.h" +// 10 MHz max SPI frequency +#define ICM20689_MAX_SPI_CLK_HZ 10000000 + +// 10 MHz max SPI frequency for intialisation +#define ICM20689_MAX_SPI_INIT_CLK_HZ 1000000 + static void icm20689SpiInit(const busDevice_t *bus) { static bool hardwareInitialised = false; @@ -46,7 +52,7 @@ static void icm20689SpiInit(const busDevice_t *bus) } - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ)); hardwareInitialised = true; } @@ -55,7 +61,7 @@ uint8_t icm20689SpiDetect(const busDevice_t *bus) { icm20689SpiInit(bus); - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); //low speed + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM20689_MAX_SPI_INIT_CLK_HZ)); // reset the device configuration spiBusWriteRegister(bus, MPU_RA_PWR_MGMT_1, ICM20689_BIT_RESET); @@ -87,7 +93,7 @@ uint8_t icm20689SpiDetect(const busDevice_t *bus) break; } - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ)); return icmDetected; } @@ -117,7 +123,7 @@ void icm20689GyroInit(gyroDev_t *gyro) { mpuGyroInit(gyro); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(ICM20689_MAX_SPI_INIT_CLK_HZ)); // Device was already reset during detection so proceed with configuration @@ -142,7 +148,7 @@ void icm20689GyroInit(gyroDev_t *gyro) spiBusWriteRegister(&gyro->bus, MPU_RA_INT_ENABLE, 0x01); // RAW_RDY_EN interrupt enable #endif - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(ICM20689_MAX_SPI_CLK_HZ)); } bool icm20689SpiGyroDetect(gyroDev_t *gyro) diff --git a/src/main/drivers/accgyro/accgyro_spi_icm42605.c b/src/main/drivers/accgyro/accgyro_spi_icm42605.c index 62535d5008..ea09ad85ba 100644 --- a/src/main/drivers/accgyro/accgyro_spi_icm42605.c +++ b/src/main/drivers/accgyro/accgyro_spi_icm42605.c @@ -43,6 +43,12 @@ #include "drivers/sensor.h" #include "drivers/time.h" +// 24 MHz max SPI frequency +#define ICM42605_MAX_SPI_CLK_HZ 24000000 + +// 10 MHz max SPI frequency for intialisation +#define ICM42605_MAX_SPI_INIT_CLK_HZ 1000000 + #define ICM42605_RA_PWR_MGMT0 0x4E #define ICM42605_PWR_MGMT0_ACCEL_MODE_LN (3 << 0) @@ -98,7 +104,7 @@ static void icm42605SpiInit(const busDevice_t *bus) } - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM42605_MAX_SPI_CLK_HZ)); hardwareInitialised = true; } @@ -107,7 +113,7 @@ uint8_t icm42605SpiDetect(const busDevice_t *bus) { icm42605SpiInit(bus); - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); //low speed + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM42605_MAX_SPI_INIT_CLK_HZ)); spiBusWriteRegister(bus, ICM42605_RA_PWR_MGMT0, 0x00); @@ -132,7 +138,7 @@ uint8_t icm42605SpiDetect(const busDevice_t *bus) } } while (attemptsRemaining--); - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(ICM42605_MAX_SPI_CLK_HZ)); return icmDetected; } @@ -188,7 +194,7 @@ void icm42605GyroInit(gyroDev_t *gyro) { mpuGyroInit(gyro); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(ICM42605_MAX_SPI_INIT_CLK_HZ)); spiBusWriteRegister(&gyro->bus, ICM42605_RA_PWR_MGMT0, ICM42605_PWR_MGMT0_TEMP_DISABLE_OFF | ICM42605_PWR_MGMT0_ACCEL_MODE_LN | ICM42605_PWR_MGMT0_GYRO_MODE_LN); delay(15); @@ -246,7 +252,7 @@ void icm42605GyroInit(gyroDev_t *gyro) #endif // - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(ICM42605_MAX_SPI_CLK_HZ)); } bool icm42605GyroReadSPI(gyroDev_t *gyro) diff --git a/src/main/drivers/accgyro/accgyro_spi_l3gd20.c b/src/main/drivers/accgyro/accgyro_spi_l3gd20.c index 4e508b6fb1..24ed2bfcbf 100644 --- a/src/main/drivers/accgyro/accgyro_spi_l3gd20.c +++ b/src/main/drivers/accgyro/accgyro_spi_l3gd20.c @@ -40,6 +40,9 @@ #include "accgyro_spi_l3gd20.h" +// 10 MHz max SPI frequency +#define L3GD20_MAX_SPI_CLK_HZ 10000000 + #define READ_CMD ((uint8_t)0x80) #define MULTIPLEBYTE_CMD ((uint8_t)0x40) #define DUMMY_BYTE ((uint8_t)0x00) @@ -98,7 +101,7 @@ static void l3gd20IntExtiInit(gyroDev_t *gyro) void l3gd20GyroInit(gyroDev_t *gyro) { - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(L3GD20_MAX_SPI_CLK_HZ)); spiBusWriteRegister(&gyro->bus, CTRL_REG5_ADDR, BOOT); diff --git a/src/main/drivers/accgyro/accgyro_spi_lsm6dso_init.c b/src/main/drivers/accgyro/accgyro_spi_lsm6dso_init.c index 6b82704276..032be8a48f 100644 --- a/src/main/drivers/accgyro/accgyro_spi_lsm6dso_init.c +++ b/src/main/drivers/accgyro/accgyro_spi_lsm6dso_init.c @@ -35,6 +35,9 @@ #include "drivers/sensor.h" #include "drivers/time.h" +// 10 MHz max SPI frequency +#define LSM6DSO_MAX_SPI_CLK_HZ 10000000 + #define LSM6DSO_CHIP_ID 0x6C // LSM6DSO register configuration values @@ -78,7 +81,7 @@ typedef enum { uint8_t lsm6dsoDetect(const busDevice_t *bus) { uint8_t chipID = 0; - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(LSM6DSO_MAX_SPI_CLK_HZ)); if (busReadRegisterBuffer(bus, LSM6DSO_REG_WHO_AM_I, &chipID, 1)) { if (chipID == LSM6DSO_CHIP_ID) { diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu6000.c b/src/main/drivers/accgyro/accgyro_spi_mpu6000.c index c1ae68a4ee..848807b205 100644 --- a/src/main/drivers/accgyro/accgyro_spi_mpu6000.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu6000.c @@ -47,7 +47,10 @@ static void mpu6000AccAndGyroInit(gyroDev_t *gyro); - +// 1 MHz max SPI frequency for initialisation +#define MPU6000_MAX_SPI_INIT_CLK_HZ 1000000 +// 20 MHz max SPI frequency +#define MPU6000_MAX_SPI_CLK_HZ 20000000 // Bits #define BIT_SLEEP 0x40 @@ -104,13 +107,13 @@ void mpu6000SpiGyroInit(gyroDev_t *gyro) mpu6000AccAndGyroInit(gyro); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_INIT_CLK_HZ)); // Accel and Gyro DLPF Setting spiBusWriteRegister(&gyro->bus, MPU6000_CONFIG, mpuGyroDLPF(gyro)); delayMicroseconds(1); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_FAST); // 18 MHz SPI clock + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_CLK_HZ)); mpuGyroRead(gyro); @@ -127,7 +130,7 @@ void mpu6000SpiAccInit(accDev_t *acc) uint8_t mpu6000SpiDetect(const busDevice_t *bus) { - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_INIT_CLK_HZ)); // reset the device configuration spiBusWriteRegister(bus, MPU_RA_PWR_MGMT_1, BIT_H_RESET); @@ -164,13 +167,13 @@ uint8_t mpu6000SpiDetect(const busDevice_t *bus) } } - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_STANDARD); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_CLK_HZ)); return detectedSensor; } static void mpu6000AccAndGyroInit(gyroDev_t *gyro) { - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_INIT_CLK_HZ)); // Device was already reset during detection so proceed with configuration @@ -206,7 +209,7 @@ static void mpu6000AccAndGyroInit(gyroDev_t *gyro) delayMicroseconds(15); #endif - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_FAST); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6000_MAX_SPI_CLK_HZ)); delayMicroseconds(1); } diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu6500.c b/src/main/drivers/accgyro/accgyro_spi_mpu6500.c index 8980830d6e..7801007fcc 100644 --- a/src/main/drivers/accgyro/accgyro_spi_mpu6500.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu6500.c @@ -37,12 +37,17 @@ #include "accgyro_mpu6500.h" #include "accgyro_spi_mpu6500.h" +// 1 MHz max SPI frequency for initialisation +#define MPU6500_MAX_SPI_INIT_CLK_HZ 1000000 +// 20 MHz max SPI frequency +#define MPU6500_MAX_SPI_CLK_HZ 20000000 + #define BIT_SLEEP 0x40 static void mpu6500SpiInit(const busDevice_t *bus) { - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_FAST); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(MPU6500_MAX_SPI_CLK_HZ)); } uint8_t mpu6500SpiDetect(const busDevice_t *bus) @@ -85,7 +90,7 @@ void mpu6500SpiAccInit(accDev_t *acc) void mpu6500SpiGyroInit(gyroDev_t *gyro) { - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_SLOW); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6500_MAX_SPI_INIT_CLK_HZ)); delayMicroseconds(1); mpu6500GyroInit(gyro); @@ -94,7 +99,7 @@ void mpu6500SpiGyroInit(gyroDev_t *gyro) spiBusWriteRegister(&gyro->bus, MPU_RA_USER_CTRL, MPU6500_BIT_I2C_IF_DIS); delay(100); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_FAST); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU6500_MAX_SPI_CLK_HZ)); delayMicroseconds(1); } diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu9250.c b/src/main/drivers/accgyro/accgyro_spi_mpu9250.c index 91ef27ad4c..4a74a74d90 100644 --- a/src/main/drivers/accgyro/accgyro_spi_mpu9250.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu9250.c @@ -47,6 +47,11 @@ #include "drivers/system.h" +// 1 MHz max SPI frequency for initialisation +#define MPU9250_MAX_SPI_INIT_CLK_HZ 1000000 +// 20 MHz max SPI frequency +#define MPU9250_MAX_SPI_CLK_HZ 20000000 + static void mpu9250AccAndGyroInit(gyroDev_t *gyro); @@ -82,7 +87,7 @@ void mpu9250SpiGyroInit(gyroDev_t *gyro) spiResetErrorCounter(gyro->bus.busdev_u.spi.instance); - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_FAST); //high speed now that we don't need to write to the slow registers + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU9250_MAX_SPI_CLK_HZ)); //high speed now that we don't need to write to the slow registers mpuGyroRead(gyro); @@ -119,7 +124,7 @@ bool mpu9250SpiWriteRegisterVerify(const busDevice_t *bus, uint8_t reg, uint8_t static void mpu9250AccAndGyroInit(gyroDev_t *gyro) { - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); //low speed for writing to slow registers + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU9250_MAX_SPI_INIT_CLK_HZ)); //low speed for writing to slow registers mpu9250SpiWriteRegister(&gyro->bus, MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET); delay(50); @@ -139,13 +144,13 @@ static void mpu9250AccAndGyroInit(gyroDev_t *gyro) { mpu9250SpiWriteRegisterVerify(&gyro->bus, MPU_RA_INT_ENABLE, 0x01); //this resets register MPU_RA_PWR_MGMT_1 and won't read back correctly. #endif - spiSetDivisor(gyro->bus.busdev_u.spi.instance, SPI_CLOCK_FAST); + spiSetDivisor(gyro->bus.busdev_u.spi.instance, spiCalculateDivider(MPU9250_MAX_SPI_CLK_HZ)); } uint8_t mpu9250SpiDetect(const busDevice_t *bus) { - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_INITIALIZATION); //low speed + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(MPU9250_MAX_SPI_INIT_CLK_HZ)); //low speed mpu9250SpiWriteRegister(bus, MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET); uint8_t attemptsRemaining = 20; @@ -160,7 +165,7 @@ uint8_t mpu9250SpiDetect(const busDevice_t *bus) } } while (attemptsRemaining--); - spiSetDivisor(bus->busdev_u.spi.instance, SPI_CLOCK_FAST); + spiSetDivisor(bus->busdev_u.spi.instance, spiCalculateDivider(MPU9250_MAX_SPI_CLK_HZ)); return MPU_9250_SPI; } diff --git a/src/main/drivers/barometer/barometer_bmp280.c b/src/main/drivers/barometer/barometer_bmp280.c index 3d130e0302..ee878311a9 100644 --- a/src/main/drivers/barometer/barometer_bmp280.c +++ b/src/main/drivers/barometer/barometer_bmp280.c @@ -37,6 +37,9 @@ #include "barometer_bmp280.h" +// 10 MHz max SPI frequency +#define BMP280_MAX_SPI_CLK_HZ 10000000 + #if defined(USE_BARO) && (defined(USE_BARO_BMP280) || defined(USE_BARO_SPI_BMP280)) @@ -123,9 +126,9 @@ void bmp280BusInit(busDevice_t *busdev) IOInit(busdev->busdev_u.spi.csnPin, OWNER_BARO_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, SPI_CLOCK_STANDARD); // BMP280 supports Mode 0 or 3 + spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, spiCalculateDivider(BMP280_MAX_SPI_CLK_HZ)); // BMP280 supports Mode 0 or 3 #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(BMP280_MAX_SPI_CLK_HZ)); #endif } #else diff --git a/src/main/drivers/barometer/barometer_bmp388.c b/src/main/drivers/barometer/barometer_bmp388.c index 4919226bc4..58282a3c52 100644 --- a/src/main/drivers/barometer/barometer_bmp388.c +++ b/src/main/drivers/barometer/barometer_bmp388.c @@ -45,6 +45,8 @@ #include "barometer_bmp388.h" +// 10 MHz max SPI frequency +#define BMP388_MAX_SPI_CLK_HZ 10000000 #define BMP388_I2C_ADDR (0x76) // same as BMP280/BMP180 #define BMP388_DEFAULT_CHIP_ID (0x50) // from https://github.com/BoschSensortec/BMP3-Sensor-API/blob/master/bmp3_defs.h#L130 @@ -201,7 +203,7 @@ void bmp388BusInit(busDevice_t *busdev) IOHi(busdev->busdev_u.spi.csnPin); // Disable IOInit(busdev->busdev_u.spi.csnPin, OWNER_BARO_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(BMP388_MAX_SPI_CLK_HZ)); } #else UNUSED(busdev); diff --git a/src/main/drivers/barometer/barometer_dps310.c b/src/main/drivers/barometer/barometer_dps310.c index 142162d8d7..f614a15003 100644 --- a/src/main/drivers/barometer/barometer_dps310.c +++ b/src/main/drivers/barometer/barometer_dps310.c @@ -42,6 +42,9 @@ #include "drivers/barometer/barometer_dps310.h" #include "drivers/resource.h" +// 10 MHz max SPI frequency +#define DPS310_MAX_SPI_CLK_HZ 10000000 + #if defined(USE_BARO) && defined(USE_BARO_DPS310) #define DPS310_I2C_ADDR 0x76 @@ -325,9 +328,9 @@ static void busDeviceInit(busDevice_t *busdev, resourceOwner_e owner) IOInit(busdev->busdev_u.spi.csnPin, owner, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, SPI_CLOCK_STANDARD); // DPS310 supports Mode 0 or 3 + spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, spiCalculateDivider(DPS310_MAX_SPI_CLK_HZ)); // DPS310 supports Mode 0 or 3 #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(DPS310_MAX_SPI_CLK_HZ)); #endif } #else diff --git a/src/main/drivers/barometer/barometer_lps.c b/src/main/drivers/barometer/barometer_lps.c index e4239528ea..8f3dcb1979 100644 --- a/src/main/drivers/barometer/barometer_lps.c +++ b/src/main/drivers/barometer/barometer_lps.c @@ -34,6 +34,8 @@ #include "drivers/io.h" #include "drivers/time.h" +// 10 MHz max SPI frequency +#define LPS_MAX_SPI_CLK_HZ 10000000 //====================================Registers Addresses=========================================// #define LPS_REF_P_XL 0x08 #define LPS_REF_P_L 0x09 @@ -269,9 +271,9 @@ bool lpsDetect(baroDev_t *baro) IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); IOHi(busdev->busdev_u.spi.csnPin); // Disable #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_STANDARD); // Baro can work only on up to 10Mhz SPI bus + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(LPS_MAX_SPI_CLK_HZ)); // Baro can work only on up to 10Mhz SPI bus #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); // Baro can work only on up to 10Mhz SPI bus + spiBusSetDivisor(busdev, spiCalculateDivider(LPS_MAX_SPI_CLK_HZ)); // Baro can work only on up to 10Mhz SPI bus #endif uint8_t temp = 0x00; diff --git a/src/main/drivers/barometer/barometer_ms5611.c b/src/main/drivers/barometer/barometer_ms5611.c index 36cecbceee..9303320c9b 100644 --- a/src/main/drivers/barometer/barometer_ms5611.c +++ b/src/main/drivers/barometer/barometer_ms5611.c @@ -36,6 +36,9 @@ #include "drivers/io.h" #include "drivers/time.h" +// 10 MHz max SPI frequency +#define MS5611_MAX_SPI_CLK_HZ 10000000 + // MS5611, Standard address 0x77 #define MS5611_I2C_ADDR 0x77 @@ -67,9 +70,9 @@ void ms5611BusInit(busDevice_t *busdev) IOInit(busdev->busdev_u.spi.csnPin, OWNER_BARO_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_STANDARD); + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(MS5611_MAX_SPI_CLK_HZ)); #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); // XXX + spiBusSetDivisor(busdev, spiCalculateDivider(MS5611_MAX_SPI_CLK_HZ)); // XXX #endif } #else diff --git a/src/main/drivers/barometer/barometer_qmp6988.c b/src/main/drivers/barometer/barometer_qmp6988.c index 128fd44ada..065ade7806 100644 --- a/src/main/drivers/barometer/barometer_qmp6988.c +++ b/src/main/drivers/barometer/barometer_qmp6988.c @@ -37,6 +37,9 @@ #if defined(USE_BARO) && (defined(USE_BARO_QMP6988) || defined(USE_BARO_SPI_QMP6988)) +// 10 MHz max SPI frequency +#define QMP6988_MAX_SPI_CLK_HZ 10000000 + #define QMP6988_I2C_ADDR 0x70 #define QMP6988_DEFAULT_CHIP_ID 0x5c #define QMP6988_CHIP_ID_REG 0xD1 /* Chip ID Register */ @@ -110,9 +113,9 @@ void qmp6988BusInit(busDevice_t *busdev) IOInit(busdev->busdev_u.spi.csnPin, OWNER_BARO_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_STANDARD); + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(QMP6988_MAX_SPI_CLK_HZ)); #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(QMP6988_MAX_SPI_CLK_HZ)); #endif } #else diff --git a/src/main/drivers/bus_spi.c b/src/main/drivers/bus_spi.c index 19e5912abe..32ed269997 100644 --- a/src/main/drivers/bus_spi.c +++ b/src/main/drivers/bus_spi.c @@ -240,6 +240,25 @@ void spiBusSetInstance(busDevice_t *bus, SPI_TypeDef *instance) bus->busdev_u.spi.instance = instance; } +uint16_t spiCalculateDivider(uint32_t freq) +{ +#if defined(STM32F4) || defined(STM32G4) || defined(STM32F7) + uint32_t spiClk = SystemCoreClock / 2; +#elif defined(STM32H7) + uint32_t spiClk = 100000000; +#else +#error "Base SPI clock not defined for this architecture" +#endif + + uint16_t divisor = 2; + + spiClk >>= 1; + + for (; (spiClk > freq) && (divisor < 256); divisor <<= 1, spiClk >>= 1); + + return divisor; +} + void spiBusSetDivisor(busDevice_t *bus, uint16_t divisor) { spiSetDivisor(bus->busdev_u.spi.instance, divisor); diff --git a/src/main/drivers/bus_spi.h b/src/main/drivers/bus_spi.h index c7690139a0..f6abcb3e34 100644 --- a/src/main/drivers/bus_spi.h +++ b/src/main/drivers/bus_spi.h @@ -46,41 +46,6 @@ #define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_Out_PP, GPIO_Speed_50MHz) #endif -/* - Flash M25p16 tolerates 20mhz, SPI_CLOCK_FAST should sit around 20 or less. -*/ -typedef enum { - SPI_CLOCK_INITIALIZATION = 256, -#if defined(STM32F4) - SPI_CLOCK_SLOW = 128, //00.65625 MHz - SPI_CLOCK_STANDARD = 8, //10.50000 MHz - SPI_CLOCK_FAST = 4, //21.00000 MHz - SPI_CLOCK_ULTRAFAST = 2 //42.00000 MHz -#elif defined(STM32F7) - SPI_CLOCK_SLOW = 256, //00.42188 MHz - SPI_CLOCK_STANDARD = 16, //06.57500 MHz - SPI_CLOCK_FAST = 8, //13.50000 MHz - SPI_CLOCK_ULTRAFAST = 2 //54.00000 MHz -#elif defined(STM32H7) - // spi_ker_ck = 100MHz - SPI_CLOCK_SLOW = 128, //00.78125 MHz - SPI_CLOCK_STANDARD = 8, //12.00000 MHz - SPI_CLOCK_FAST = 4, //25.00000 MHz - SPI_CLOCK_ULTRAFAST = 2 //50.00000 MHz -#elif defined(STM32G4) - // @170MHz - SPI_CLOCK_SLOW = 128, //00.78125 MHz - SPI_CLOCK_STANDARD = 16, //10.62500 MHz - SPI_CLOCK_FAST = 8, //21.25000 MHz - SPI_CLOCK_ULTRAFAST = 4 //42.50000 MHz -#else - SPI_CLOCK_SLOW = 128, //00.56250 MHz - SPI_CLOCK_STANDARD = 4, //09.00000 MHz - SPI_CLOCK_FAST = 2, //18.00000 MHz - SPI_CLOCK_ULTRAFAST = 2 //18.00000 MHz -#endif -} SPIClockDivider_e; - // De facto standard mode // See https://en.wikipedia.org/wiki/Serial_Peripheral_Interface // @@ -160,9 +125,10 @@ void spiBusWriteRegisterBuffer(const busDevice_t *bus, uint8_t reg, const uint8_ uint8_t spiBusRawReadRegister(const busDevice_t *bus, uint8_t reg); uint8_t spiBusReadRegister(const busDevice_t *bus, uint8_t reg); void spiBusSetInstance(busDevice_t *bus, SPI_TypeDef *instance); -void spiBusSetDivisor(busDevice_t *bus, SPIClockDivider_e divider); +uint16_t spiCalculateDivider(uint32_t freq); +void spiBusSetDivisor(busDevice_t *bus, uint16_t divider); -void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, SPIClockDivider_e divider); +void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, uint16_t divider); void spiBusTransactionSetup(const busDevice_t *bus); void spiBusTransactionBegin(const busDevice_t *bus); void spiBusTransactionEnd(const busDevice_t *bus); diff --git a/src/main/drivers/bus_spi_ll.c b/src/main/drivers/bus_spi_ll.c index 6a22c7e2ba..1297361460 100644 --- a/src/main/drivers/bus_spi_ll.c +++ b/src/main/drivers/bus_spi_ll.c @@ -247,7 +247,7 @@ void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) } #ifdef USE_SPI_TRANSACTION -void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, SPIClockDivider_e divisor) +void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, uint16_t divisor) { switch (mode) { case SPI_MODE0_POL_LOW_EDGE_1ST: diff --git a/src/main/drivers/bus_spi_stdperiph.c b/src/main/drivers/bus_spi_stdperiph.c index d95a378cce..562e114c2f 100644 --- a/src/main/drivers/bus_spi_stdperiph.c +++ b/src/main/drivers/bus_spi_stdperiph.c @@ -212,7 +212,7 @@ void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) #ifdef USE_SPI_TRANSACTION -void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, SPIClockDivider_e divider) +void spiBusTransactionInit(busDevice_t *bus, SPIMode_e mode, uint16_t divider) { switch (mode) { case SPI_MODE0_POL_LOW_EDGE_1ST: diff --git a/src/main/drivers/compass/compass_ak8963.c b/src/main/drivers/compass/compass_ak8963.c index feb69d6805..6b1b15a1f8 100644 --- a/src/main/drivers/compass/compass_ak8963.c +++ b/src/main/drivers/compass/compass_ak8963.c @@ -54,6 +54,9 @@ // This sensor is also available also part of the MPU-9250 connected to the secondary I2C bus. +// 10 MHz max SPI frequency +#define AK8963_MAX_SPI_CLK_HZ 10000000 + // AK8963, mag sensor address #define AK8963_MAG_I2C_ADDRESS 0x0C #define AK8963_DEVICE_ID 0x48 @@ -383,9 +386,9 @@ void ak8963BusInit(busDevice_t *busdev) IOInit(busdev->busdev_u.spi.csnPin, OWNER_COMPASS_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_STANDARD); + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(AK8963_MAX_SPI_CLK_HZ)); #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(AK8963_MAX_SPI_CLK_HZ)); #endif break; #endif diff --git a/src/main/drivers/compass/compass_hmc5883l.c b/src/main/drivers/compass/compass_hmc5883l.c index b17c0bdd62..b76222258e 100644 --- a/src/main/drivers/compass/compass_hmc5883l.c +++ b/src/main/drivers/compass/compass_hmc5883l.c @@ -49,6 +49,9 @@ //#define DEBUG_MAG_DATA_READY_INTERRUPT +// 10 MHz max SPI frequency +#define HMC5883_MAX_SPI_CLK_HZ 10000000 + // HMC5883L, default address 0x1E // NAZE Target connections // PB12 connected to MAG_DRDY on rev4 hardware @@ -193,9 +196,9 @@ static void hmc5883SpiInit(busDevice_t *busdev) IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_STANDARD); + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(HMC5883_MAX_SPI_CLK_HZ)); #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(HMC5883_MAX_SPI_CLK_HZ)); #endif } #endif diff --git a/src/main/drivers/flash.c b/src/main/drivers/flash.c index 811eb2399a..935b851ee2 100644 --- a/src/main/drivers/flash.c +++ b/src/main/drivers/flash.c @@ -38,6 +38,11 @@ #include "drivers/io.h" #include "drivers/time.h" +// 20 MHz max SPI frequency +#define FLASH_MAX_SPI_CLK_HZ 20000000 +// 5 MHz max SPI init frequency +#define FLASH_MAX_SPI_INIT_CLK 5000000 + static busDevice_t busInstance; static busDevice_t *busdev; @@ -123,12 +128,10 @@ static bool flashSpiInit(const flashConfig_t *flashConfig) IOHi(busdev->busdev_u.spi.csnPin); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, SPI_CLOCK_FAST); + spiBusTransactionInit(busdev, SPI_MODE3_POL_HIGH_EDGE_2ND, spiCalculateDivider(FLASH_MAX_SPI_INIT_CLK)); #else #ifndef FLASH_SPI_SHARED - //Maximum speed for standard READ command is 20mHz, other commands tolerate 25mHz - //spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_FAST); - spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_STANDARD*2); + spiSetDivisor(busdev->busdev_u.spi.instance, spiCalculateDivider(FLASH_MAX_SPI_INIT_CLK)); #endif #endif diff --git a/src/main/drivers/flash_m25p16.c b/src/main/drivers/flash_m25p16.c index 8462a999d9..4a21782aa1 100644 --- a/src/main/drivers/flash_m25p16.c +++ b/src/main/drivers/flash_m25p16.c @@ -52,21 +52,62 @@ #define W25Q256_INSTRUCTION_ENTER_4BYTE_ADDRESS_MODE 0xB7 -// Format is manufacturer, memory type, then capacity -// See also flash_m25p16.h for additional JEDEC IDs. -#define JEDEC_ID_MACRONIX_MX25L3206E 0xC22016 -#define JEDEC_ID_MACRONIX_MX25L6406E 0xC22017 -#define JEDEC_ID_MACRONIX_MX25L25635E 0xC22019 -#define JEDEC_ID_MICRON_M25P16 0x202015 -#define JEDEC_ID_MICRON_N25Q064 0x20BA17 -#define JEDEC_ID_MICRON_N25Q128 0x20ba18 -#define JEDEC_ID_WINBOND_W25Q16 0xEF4015 -#define JEDEC_ID_WINBOND_W25Q32 0xEF4016 -#define JEDEC_ID_WINBOND_W25Q64 0xEF4017 -#define JEDEC_ID_WINBOND_W25Q128 0xEF4018 -#define JEDEC_ID_WINBOND_W25Q128_DTR 0xEF7018 -#define JEDEC_ID_CYPRESS_S25FL128L 0x016018 -#define JEDEC_ID_BERGMICRO_W25Q32 0xE04016 +static uint32_t maxClkSPIHz; +static uint32_t maxReadClkSPIHz; + +// Table of recognised FLASH devices +struct { + uint32_t jedecID; + uint16_t maxClkSPIMHz; + uint16_t maxReadClkSPIMHz; + flashSector_t sectors; + uint16_t pagesPerSector; +} m25p16FlashConfig[] = { + // Macronix MX25L3206E + // Datasheet: https://docs.rs-online.com/5c85/0900766b814ac6f9.pdf + { 0xC22016, 86, 33, 64, 256 }, + // Macronix MX25L6406E + // Datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7370/MX25L6406E,%203V,%2064Mb,%20v1.9.pdf + { 0xC22017, 86, 33, 128, 256 }, + // Macronix MX25L25635E + // Datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7331/MX25L25635E,%203V,%20256Mb,%20v1.3.pdf + { 0xC22019, 80, 50, 512, 256 }, + // Micron M25P16 + // Datasheet: https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p16.pdf + { 0x202015, 25, 20, 32, 256 }, + // Micron N25Q064 + // Datasheet: https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_64a_3v_65nm.pdf + { 0x20BA17, 108, 54, 128, 256 }, + // Micron N25Q128 + // Datasheet: https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_128mb_1_8v_65nm.pdf + { 0x20ba18, 108, 54, 256, 256 }, + // Winbond W25Q16 + // Datasheet: https://www.winbond.com/resource-files/w25q16dv_revi_nov1714_web.pdf + { 0xEF4015, 104, 50, 32, 256 }, + // Winbond W25Q32 + // Datasheet: https://www.winbond.com/resource-files/w25q32jv%20dtr%20revf%2002242017.pdf?__locale=zh_TW + { 0xEF4016, 133, 50, 64, 256 }, + // Winbond W25Q64 + // Datasheet: https://www.winbond.com/resource-files/w25q64jv%20spi%20%20%20revc%2006032016%20kms.pdf + { 0xEF4017, 133, 50, 128, 256 }, + // Winbond W25Q128 + // Datasheet: https://www.winbond.com/resource-files/w25q128fv%20rev.l%2008242015.pdf + { 0xEF4018, 104, 50, 256, 256 }, + // Winbond W25Q128_DTR + // Datasheet: https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf + { 0xEF7018, 66, 50, 256, 256 }, + // Winbond W25Q256 + // Datasheet: https://www.winbond.com/resource-files/w25q256jv%20spi%20revb%2009202016.pdf + { 0xEF4019, 133, 50, 512, 256 }, + // Cypress S25FL128L + // Datasheet: https://www.cypress.com/file/316171/download + { 0x016018, 133, 50, 256, 256 }, + // BergMicro W25Q32 + // Datasheet: https://www.winbond.com/resource-files/w25q32jv%20dtr%20revf%2002242017.pdf?__locale=zh_TW + { 0xE04016, 133, 50, 1024, 16 }, + // End of list + { 0x000000, 0, 0, 0, 0 } +}; // IMPORTANT: Timeout values are currently required to be set to the highest value required by any of the supported flash chips by this driver. @@ -179,52 +220,37 @@ static bool m25p16_waitForReady(flashDevice_t *fdevice) bool m25p16_detect(flashDevice_t *fdevice, uint32_t chipID) { - switch (chipID) { - case JEDEC_ID_WINBOND_W25Q16: - case JEDEC_ID_MICRON_M25P16: - fdevice->geometry.sectors = 32; - fdevice->geometry.pagesPerSector = 256; - break; - case JEDEC_ID_BERGMICRO_W25Q32: - fdevice->geometry.sectors = 1024; - fdevice->geometry.pagesPerSector = 16; - break; - case JEDEC_ID_WINBOND_W25Q32: - case JEDEC_ID_MACRONIX_MX25L3206E: - fdevice->geometry.sectors = 64; - fdevice->geometry.pagesPerSector = 256; - break; - case JEDEC_ID_MICRON_N25Q064: - case JEDEC_ID_WINBOND_W25Q64: - case JEDEC_ID_MACRONIX_MX25L6406E: - fdevice->geometry.sectors = 128; - fdevice->geometry.pagesPerSector = 256; - break; - case JEDEC_ID_MICRON_N25Q128: - case JEDEC_ID_WINBOND_W25Q128: - case JEDEC_ID_WINBOND_W25Q128_DTR: - case JEDEC_ID_CYPRESS_S25FL128L: - fdevice->geometry.sectors = 256; - fdevice->geometry.pagesPerSector = 256; - break; - case JEDEC_ID_WINBOND_W25Q256: - case JEDEC_ID_MACRONIX_MX25L25635E: - fdevice->geometry.sectors = 512; - fdevice->geometry.pagesPerSector = 256; - break; - default: + flashGeometry_t *geometry = &fdevice->geometry; + uint8_t index; + + for (index = 0; m25p16FlashConfig[index].jedecID; index++) { + if (m25p16FlashConfig[index].jedecID == chipID) { + maxClkSPIHz = m25p16FlashConfig[index].maxClkSPIMHz * 1000000; + maxReadClkSPIHz = m25p16FlashConfig[index].maxReadClkSPIMHz * 1000000; + geometry->sectors = m25p16FlashConfig[index].sectors; + geometry->pagesPerSector = m25p16FlashConfig[index].pagesPerSector; + break; + } + } + + if (m25p16FlashConfig[index].jedecID == 0) { // Unsupported chip or not an SPI NOR flash - fdevice->geometry.sectors = 0; - fdevice->geometry.pagesPerSector = 0; - fdevice->geometry.sectorSize = 0; - fdevice->geometry.totalSize = 0; + geometry->sectors = 0; + geometry->pagesPerSector = 0; + geometry->sectorSize = 0; + geometry->totalSize = 0; return false; } - fdevice->geometry.flashType = FLASH_TYPE_NOR; - fdevice->geometry.pageSize = M25P16_PAGESIZE; - fdevice->geometry.sectorSize = fdevice->geometry.pagesPerSector * fdevice->geometry.pageSize; - fdevice->geometry.totalSize = fdevice->geometry.sectorSize * fdevice->geometry.sectors; + geometry->flashType = FLASH_TYPE_NOR; + geometry->pageSize = M25P16_PAGESIZE; + geometry->sectorSize = geometry->pagesPerSector * geometry->pageSize; + geometry->totalSize = geometry->sectorSize * geometry->sectors; + + // Adjust the SPI bus clock frequency +#ifndef FLASH_SPI_SHARED + spiSetDivisor(fdevice->io.handle.busdev->busdev_u.spi.instance, spiCalculateDivider(maxReadClkSPIHz)); +#endif if (fdevice->geometry.totalSize > 16 * 1024 * 1024) { fdevice->isLargeFlash = true; @@ -357,6 +383,10 @@ static int m25p16_readBytes(flashDevice_t *fdevice, uint32_t address, uint8_t *b return 0; } +#ifndef FLASH_SPI_SHARED + spiSetDivisor(fdevice->io.handle.busdev->busdev_u.spi.instance, spiCalculateDivider(maxReadClkSPIHz)); +#endif + #ifdef USE_SPI_TRANSACTION spiBusTransactionBegin(fdevice->io.handle.busdev); #else @@ -372,6 +402,10 @@ static int m25p16_readBytes(flashDevice_t *fdevice, uint32_t address, uint8_t *b m25p16_disable(fdevice->io.handle.busdev); #endif +#ifndef FLASH_SPI_SHARED + spiSetDivisor(fdevice->io.handle.busdev->busdev_u.spi.instance, spiCalculateDivider(maxClkSPIHz)); +#endif + m25p16_setTimeout(fdevice, DEFAULT_TIMEOUT_MILLIS); return length; diff --git a/src/main/drivers/flash_m25p16.h b/src/main/drivers/flash_m25p16.h index dc78fe0da6..fa606a4947 100644 --- a/src/main/drivers/flash_m25p16.h +++ b/src/main/drivers/flash_m25p16.h @@ -22,6 +22,4 @@ #include "flash_impl.h" -#define JEDEC_ID_WINBOND_W25Q256 0xEF4019 - bool m25p16_detect(flashDevice_t *fdevice, uint32_t chipID); diff --git a/src/main/drivers/flash_w25m.c b/src/main/drivers/flash_w25m.c index 70a090c7e2..473413b46f 100644 --- a/src/main/drivers/flash_w25m.c +++ b/src/main/drivers/flash_w25m.c @@ -51,6 +51,7 @@ #define JEDEC_ID_WINBOND_W25M512 0xEF7119 // W25Q256 x 2 #define JEDEC_ID_WINBOND_W25M02G 0xEFAB21 // W25N01G x 2 +#define JEDEC_ID_WINBOND_W25Q256 0xEF4019 static const flashVTable_t w25m_vTable; diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index e3359639f1..d445a4dbce 100644 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -42,6 +42,11 @@ #include "drivers/time.h" +// 20 MHz max SPI frequency +#define MAX7456_MAX_SPI_CLK_HZ 10000000 +// 1 MHz restore SPI frequency for shared SPI bus +#define MAX7456_MAX_SPI_SHARED_CLK 1000000 + // DEBUG_MAX7456_SIGNAL #define DEBUG_MAX7456_SIGNAL_MODEREG 0 #define DEBUG_MAX7456_SIGNAL_SENSE 1 @@ -179,7 +184,7 @@ #define __spiBusTransactionEnd(busdev) spiBusTransactionEnd(busdev) #else #define __spiBusTransactionBegin(busdev) {spiBusSetDivisor(busdev, max7456SpiClock);IOLo((busdev)->busdev_u.spi.csnPin);} - #define __spiBusTransactionEnd(busdev) {IOHi((busdev)->busdev_u.spi.csnPin);spiSetDivisor((busdev)->busdev_u.spi.instance, MAX7456_RESTORE_CLK);} + #define __spiBusTransactionEnd(busdev) {IOHi((busdev)->busdev_u.spi.csnPin);spiSetDivisor((busdev)->busdev_u.spi.instance, spiCalculateDivider(MAX7456_MAX_SPI_SHARED_CLK));} #endif #define MAX7456_SUPPORTED_LAYER_COUNT (DISPLAYPORT_LAYER_BACKGROUND + 1) @@ -195,7 +200,7 @@ busDevice_t max7456BusDevice; busDevice_t *busdev = &max7456BusDevice; static bool max7456DeviceDetected = false; -static uint16_t max7456SpiClock = MAX7456_SPI_CLK; +static uint16_t max7456SpiClock; uint16_t maxScreenSize = VIDEO_BUFFER_CHARS_PAL; @@ -452,6 +457,7 @@ void max7456PreInit(const max7456Config_t *max7456Config) max7456InitStatus_e max7456Init(const max7456Config_t *max7456Config, const vcdProfile_t *pVcdProfile, bool cpuOverclock) { + max7456SpiClock = spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ); max7456DeviceDetected = false; // initialize all layers @@ -482,7 +488,7 @@ max7456InitStatus_e max7456Init(const max7456Config_t *max7456Config, const vcdP // Detect MAX7456 and compatible device by reading OSDM (OSD Insertion MUX) register. // This register is not modified in this driver, therefore ensured to remain at its default value (0x1B). - spiSetDivisor(busdev->busdev_u.spi.instance, MAX7456_SPI_CLK * 2); + spiSetDivisor(busdev->busdev_u.spi.instance, spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ) * 2); __spiBusTransactionBegin(busdev); @@ -519,15 +525,15 @@ max7456InitStatus_e max7456Init(const max7456Config_t *max7456Config, const vcdP switch (max7456Config->clockConfig) { case MAX7456_CLOCK_CONFIG_HALF: - max7456SpiClock = MAX7456_SPI_CLK * 2; + max7456SpiClock = spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ) * 2; break; case MAX7456_CLOCK_CONFIG_OC: - max7456SpiClock = (cpuOverclock && (max7456DeviceType == MAX7456_DEVICE_TYPE_MAX)) ? MAX7456_SPI_CLK * 2 : MAX7456_SPI_CLK; + max7456SpiClock = (cpuOverclock && (max7456DeviceType == MAX7456_DEVICE_TYPE_MAX)) ? spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ) * 2 : spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ); break; case MAX7456_CLOCK_CONFIG_FULL: - max7456SpiClock = MAX7456_SPI_CLK; + max7456SpiClock = spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ); break; } diff --git a/src/main/drivers/rx/rx_spi.c b/src/main/drivers/rx/rx_spi.c index bca4ba075b..6a2ab8c2db 100644 --- a/src/main/drivers/rx/rx_spi.c +++ b/src/main/drivers/rx/rx_spi.c @@ -43,6 +43,9 @@ #include "rx_spi.h" +// 10 MHz max SPI frequency +#define RX_MAX_SPI_CLK_HZ 10000000 + #define ENABLE_RX() IOLo(busdev->busdev_u.spi.csnPin) #define DISABLE_RX() IOHi(busdev->busdev_u.spi.csnPin) @@ -90,9 +93,9 @@ bool rxSpiDeviceInit(const rxSpiConfig_t *rxSpiConfig) IOHi(rxCsPin); #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, SPI_CLOCK_STANDARD); + spiBusTransactionInit(busdev, SPI_MODE0_POL_LOW_EDGE_1ST, spiCalculateDivider(RX_MAX_SPI_CLK_HZ)); #else - spiBusSetDivisor(busdev, SPI_CLOCK_STANDARD); + spiBusSetDivisor(busdev, spiCalculateDivider(RX_MAX_SPI_CLK_HZ)); #endif extiPin = IOGetByTag(rxSpiConfig->extiIoTag); diff --git a/src/main/drivers/sdcard_spi.c b/src/main/drivers/sdcard_spi.c index 10d325e271..79b79fc85f 100644 --- a/src/main/drivers/sdcard_spi.c +++ b/src/main/drivers/sdcard_spi.c @@ -49,11 +49,11 @@ // Chosen so that CMD8 will have the same CRC as CMD0: #define SDCARD_IF_COND_CHECK_PATTERN 0xAB -/* SPI_CLOCK_INITIALIZATION (256) is the slowest (Spec calls for under 400KHz) */ -#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER SPI_CLOCK_INITIALIZATION +/* Spec calls for under 400KHz */ +#define SDCARD_MAX_SPI_INIT_CLK_HZ 400000 /* Operational speed <= 25MHz */ -#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER SPI_CLOCK_FAST +#define SDCARD_MAX_SPI_CLK_HZ 25000000 #define SDCARD_SPI_MODE SPI_MODE0_POL_LOW_EDGE_1ST //#define SDCARD_SPI_MODE SPI_MODE3_POL_HIGH_EDGE_2ND @@ -112,9 +112,9 @@ static void sdcard_reset(void) if (sdcard.state >= SDCARD_STATE_READY) { #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); + spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, spiCalculateDivider(SDCARD_MAX_SPI_INIT_CLK_HZ)); #else - spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); + spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, spiCalculateDivider(SDCARD_MAX_SPI_INIT_CLK_HZ)); #endif } @@ -545,9 +545,9 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s // Max frequency is initially 400kHz #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); + spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, spiCalculateDivider(SDCARD_MAX_SPI_INIT_CLK_HZ)); #else - spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); + spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, spiCalculateDivider(SDCARD_MAX_SPI_INIT_CLK_HZ)); #endif // SDCard wants 1ms minimum delay after power is applied to it @@ -714,9 +714,9 @@ static bool sdcardSpi_poll(void) // Now we're done with init and we can switch to the full speed clock (<25MHz) #ifdef USE_SPI_TRANSACTION - spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER); + spiBusTransactionInit(&sdcard.busdev, SDCARD_SPI_MODE, spiCalculateDivider(SDCARD_MAX_SPI_CLK_HZ)); #else - spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER); + spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, spiCalculateDivider(SDCARD_MAX_SPI_CLK_HZ)); #endif sdcard.multiWriteBlocksRemain = 0; diff --git a/src/main/drivers/vtx_rtc6705.c b/src/main/drivers/vtx_rtc6705.c index 2cef64a6e0..3e60930528 100644 --- a/src/main/drivers/vtx_rtc6705.c +++ b/src/main/drivers/vtx_rtc6705.c @@ -42,6 +42,9 @@ #include "vtx_rtc6705.h" +// 1 MHz max SPI frequency - datasheet says 10MHz, but this is lower for some reason +#define RTC6705_MAX_SPI_CLK_HZ 1000000 + #define RTC6705_SET_HEAD 0x3210 //fosc=8mhz r=400 #define RTC6705_SET_R 400 //Reference clock #define RTC6705_SET_FDIV 1024 //128*(fosc/1000000) @@ -178,7 +181,7 @@ void rtc6705SetFrequency(uint16_t frequency) val_hex |= (val_a << 5); val_hex |= (val_n << 12); - spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_SLOW); + spiSetDivisor(busdev->busdev_u.spi.instance, spiCalculateDivider(RTC6705_MAX_SPI_CLK_HZ)); rtc6705Transfer(RTC6705_SET_HEAD); delayMicroseconds(10); @@ -201,7 +204,7 @@ void rtc6705SetRFPower(uint8_t rf_power) const uint32_t data = rf_power > 1 ? PA_CONTROL_DEFAULT : (PA_CONTROL_DEFAULT | PD_Q5G_MASK) & (~(PA5G_PW_MASK | PA5G_BS_MASK)); val_hex |= data << 5; // 4 address bits and 1 rw bit. - spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_SLOW); + spiSetDivisor(busdev->busdev_u.spi.instance, spiCalculateDivider(RTC6705_MAX_SPI_CLK_HZ)); rtc6705Transfer(val_hex); } diff --git a/src/main/target/AIRF7/target.h b/src/main/target/AIRF7/target.h index b03c9ad3e8..3eab48a6f0 100644 --- a/src/main/target/AIRF7/target.h +++ b/src/main/target/AIRF7/target.h @@ -67,8 +67,6 @@ #define SPI3_MOSI_PIN PB5 #define USE_MAX7456 -#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD) -#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) #define MAX7456_SPI_INSTANCE SPI3 #define MAX7456_SPI_CS_PIN PD2 diff --git a/src/main/target/IMPULSERCF3/target.h b/src/main/target/IMPULSERCF3/target.h index 677d757027..69978e9585 100644 --- a/src/main/target/IMPULSERCF3/target.h +++ b/src/main/target/IMPULSERCF3/target.h @@ -80,8 +80,6 @@ #define MAX7456_SPI_INSTANCE SPI1 #define MAX7456_SPI_CS_PIN PA3 #define MAX7456_NRST_PIN PC14 -#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD*2) -#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) #define DEFAULT_VOLTAGE_METER_SOURCE VOLTAGE_METER_ADC #define DEFAULT_CURRENT_METER_SOURCE CURRENT_METER_ADC diff --git a/src/main/target/NOX/target.h b/src/main/target/NOX/target.h index 3aa4795e23..970329c273 100644 --- a/src/main/target/NOX/target.h +++ b/src/main/target/NOX/target.h @@ -58,8 +58,6 @@ #define USE_MAX7456 #define MAX7456_SPI_INSTANCE SPI2 #define MAX7456_SPI_CS_PIN PA10 -#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD*2) -#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) #define USE_VCP #define USE_USB_DETECT diff --git a/src/main/target/STM32F3DISCOVERY/target.h b/src/main/target/STM32F3DISCOVERY/target.h index 9e64e3d2e5..07464fae5b 100644 --- a/src/main/target/STM32F3DISCOVERY/target.h +++ b/src/main/target/STM32F3DISCOVERY/target.h @@ -104,9 +104,6 @@ #define USE_GYRO_SPI_MPU6500 #define USE_GYRO_SPI_MPU9250 #define USE_ACCGYRO_BMI160 -#ifdef USE_ACCGYRO_BMI160 -#define BMI160_SPI_DIVISOR 16 -#endif #define USE_ACC diff --git a/src/main/target/TMOTORF7/target.h b/src/main/target/TMOTORF7/target.h index 507ca5f2e8..501f9d10b9 100644 --- a/src/main/target/TMOTORF7/target.h +++ b/src/main/target/TMOTORF7/target.h @@ -62,8 +62,6 @@ #define USE_MAX7456 #define MAX7456_SPI_INSTANCE SPI2 #define MAX7456_SPI_CS_PIN SPI2_NSS_PIN -#define MAX7456_SPI_CLK ( SPI_CLOCK_STANDARD ) -#define MAX7456_RESTORE_CLK ( SPI_CLOCK_FAST ) #define USE_FLASHFS #define USE_FLASH_M25P16 diff --git a/src/main/target/common_defaults_post.h b/src/main/target/common_defaults_post.h index 30c056be46..04e6d3577b 100644 --- a/src/main/target/common_defaults_post.h +++ b/src/main/target/common_defaults_post.h @@ -29,14 +29,6 @@ #define MAX7456_CLOCK_CONFIG_DEFAULT MAX7456_CLOCK_CONFIG_OC #endif -#ifndef MAX7456_SPI_CLK -#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD) -#endif - -#ifndef MAX7456_RESTORE_CLK -#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) -#endif - #ifndef MAX7456_SPI_CS_PIN #define MAX7456_SPI_CS_PIN NONE #endif diff --git a/src/test/unit/baro_bmp280_unittest.cc b/src/test/unit/baro_bmp280_unittest.cc index 812bc36611..ca600eb954 100644 --- a/src/test/unit/baro_bmp280_unittest.cc +++ b/src/test/unit/baro_bmp280_unittest.cc @@ -154,6 +154,10 @@ bool busWriteRegister(const busDevice_t*, uint8_t, uint8_t) {return true;} bool busWriteRegisterStart(const busDevice_t*, uint8_t, uint8_t) {return true;} void busDeviceRegister(const busDevice_t*) {} +uint16_t spiCalculateDivider() { + return 2; +} + void spiBusSetDivisor() { } diff --git a/src/test/unit/baro_bmp388_unittest.cc b/src/test/unit/baro_bmp388_unittest.cc index 2e74732622..1f35a4d553 100644 --- a/src/test/unit/baro_bmp388_unittest.cc +++ b/src/test/unit/baro_bmp388_unittest.cc @@ -150,6 +150,10 @@ bool busWriteRegister(const busDevice_t*, uint8_t, uint8_t) {return true;} bool busWriteRegisterStart(const busDevice_t*, uint8_t, uint8_t) {return true;} void busDeviceRegister(const busDevice_t*) {} +uint16_t spiCalculateDivider() { + return 2; +} + void spiBusSetDivisor() { } diff --git a/src/test/unit/baro_ms5611_unittest.cc b/src/test/unit/baro_ms5611_unittest.cc index d06a4c2271..b3918fb77a 100644 --- a/src/test/unit/baro_ms5611_unittest.cc +++ b/src/test/unit/baro_ms5611_unittest.cc @@ -153,6 +153,10 @@ bool busRawWriteRegister(const busDevice_t*, uint8_t, uint8_t) {return true;} bool busRawWriteRegisterStart(const busDevice_t*, uint8_t, uint8_t) {return true;} void busDeviceRegister(const busDevice_t*) {} +uint16_t spiCalculateDivider() { + return 2; +} + void spiBusSetDivisor() { }