diff --git a/Makefile b/Makefile index 4404a03a550..a7300e690e1 100644 --- a/Makefile +++ b/Makefile @@ -557,6 +557,9 @@ COMMON_SRC = \ config/parameter_group.c \ drivers/adc.c \ drivers/buf_writer.c \ + drivers/bus.c \ + drivers/bus_busdev_i2c.c \ + drivers/bus_busdev_spi.c \ drivers/bus_i2c_soft.c \ drivers/bus_spi.c \ drivers/bus_spi_soft.c \ diff --git a/src/main/drivers/accgyro/accgyro_mpu.c b/src/main/drivers/accgyro/accgyro_mpu.c index cb4d872ce90..456f05d0172 100644 --- a/src/main/drivers/accgyro/accgyro_mpu.c +++ b/src/main/drivers/accgyro/accgyro_mpu.c @@ -232,7 +232,7 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro) #ifdef USE_GYRO_SPI_MPU6000 #ifdef MPU6000_CS_PIN - gyro->bus.spi.csnPin = gyro->bus.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU6000_CS_PIN)) : gyro->bus.spi.csnPin; + gyro->bus.busdev.spi.csnPin = gyro->bus.busdev.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU6000_CS_PIN)) : gyro->bus.busdev.spi.csnPin; #endif sensor = mpu6000SpiDetect(&gyro->bus); if (sensor != MPU_NONE) { @@ -246,7 +246,7 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro) #ifdef USE_GYRO_SPI_MPU6500 #ifdef MPU6500_CS_PIN - gyro->bus.spi.csnPin = gyro->bus.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU6500_CS_PIN)) : gyro->bus.spi.csnPin; + gyro->bus.busdev.spi.csnPin = gyro->bus.busdev.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU6500_CS_PIN)) : gyro->bus.busdev.spi.csnPin; #endif sensor = mpu6500SpiDetect(&gyro->bus); // some targets using MPU_9250_SPI, ICM_20608_SPI or ICM_20602_SPI state sensor is MPU_65xx_SPI @@ -261,7 +261,7 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro) #ifdef USE_GYRO_SPI_MPU9250 #ifdef MPU9250_CS_PIN - gyro->bus.spi.csnPin = gyro->bus.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU9250_CS_PIN)) : gyro->bus.spi.csnPin; + gyro->bus.busdev.spi.csnPin = gyro->bus.busdev.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(MPU9250_CS_PIN)) : gyro->bus.busdev.spi.csnPin; #endif sensor = mpu9250SpiDetect(&gyro->bus); if (sensor != MPU_NONE) { @@ -276,7 +276,7 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro) #ifdef USE_GYRO_SPI_ICM20608 #ifdef ICM20608_CS_PIN - gyro->bus.spi.csnPin = gyro->bus.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(ICM20608_CS_PIN)) : gyro->bus.spi.csnPin; + gyro->bus.busdev.spi.csnPin = gyro->bus.busdev.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(ICM20608_CS_PIN)) : gyro->bus.busdev.spi.csnPin; #endif sensor = icm20608SpiDetect(&gyro->bus); if (sensor != MPU_NONE) { @@ -290,7 +290,7 @@ static bool detectSPISensorsAndUpdateDetectionResult(gyroDev_t *gyro) #ifdef USE_GYRO_SPI_ICM20689 #ifdef ICM20689_CS_PIN - gyro->bus.spi.csnPin = gyro->bus.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(ICM20689_CS_PIN)) : gyro->bus.spi.csnPin; + gyro->bus.busdev.spi.csnPin = gyro->bus.busdev.spi.csnPin == IO_NONE ? IOGetByTag(IO_TAG(ICM20689_CS_PIN)) : gyro->bus.busdev.spi.csnPin; #endif sensor = icm20689SpiDetect(&gyro->bus); if (sensor != MPU_NONE) { diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu6000.c b/src/main/drivers/accgyro/accgyro_spi_mpu6000.c index ebe18401130..aa103c8e15f 100644 --- a/src/main/drivers/accgyro/accgyro_spi_mpu6000.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu6000.c @@ -105,11 +105,11 @@ static bool mpuSpi6000InitDone = false; bool mpu6000SpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) { - ENABLE_MPU6000(bus->spi.csnPin); + ENABLE_MPU6000(bus->busdev.spi.csnPin); delayMicroseconds(1); spiTransferByte(MPU6000_SPI_INSTANCE, reg); spiTransferByte(MPU6000_SPI_INSTANCE, data); - DISABLE_MPU6000(bus->spi.csnPin); + DISABLE_MPU6000(bus->busdev.spi.csnPin); delayMicroseconds(1); return true; @@ -117,10 +117,10 @@ bool mpu6000SpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) bool mpu6000SpiReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t length, uint8_t *data) { - ENABLE_MPU6000(bus->spi.csnPin); + ENABLE_MPU6000(bus->busdev.spi.csnPin); spiTransferByte(MPU6000_SPI_INSTANCE, reg | 0x80); // read transaction spiTransfer(MPU6000_SPI_INSTANCE, data, NULL, length); - DISABLE_MPU6000(bus->spi.csnPin); + DISABLE_MPU6000(bus->busdev.spi.csnPin); return true; } @@ -156,8 +156,8 @@ bool mpu6000SpiDetect(const busDevice_t *bus) uint8_t in; uint8_t attemptsRemaining = 5; - IOInit(bus->spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); - IOConfigGPIO(bus->spi.csnPin, SPI_IO_CS_CFG); + IOInit(bus->busdev.spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); + IOConfigGPIO(bus->busdev.spi.csnPin, SPI_IO_CS_CFG); spiSetSpeed(MPU6000_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu6500.c b/src/main/drivers/accgyro/accgyro_spi_mpu6500.c index 66acffced77..a6567890a2d 100755 --- a/src/main/drivers/accgyro/accgyro_spi_mpu6500.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu6500.c @@ -44,11 +44,11 @@ bool mpu6500SpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) { - ENABLE_MPU6500(bus->spi.csnPin); + ENABLE_MPU6500(bus->busdev.spi.csnPin); delayMicroseconds(1); spiTransferByte(MPU6500_SPI_INSTANCE, reg); spiTransferByte(MPU6500_SPI_INSTANCE, data); - DISABLE_MPU6500(bus->spi.csnPin); + DISABLE_MPU6500(bus->busdev.spi.csnPin); delayMicroseconds(1); return true; @@ -56,10 +56,10 @@ bool mpu6500SpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) bool mpu6500SpiReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t length, uint8_t *data) { - ENABLE_MPU6500(bus->spi.csnPin); + ENABLE_MPU6500(bus->busdev.spi.csnPin); spiTransferByte(MPU6500_SPI_INSTANCE, reg | 0x80); // read transaction spiTransfer(MPU6500_SPI_INSTANCE, data, NULL, length); - DISABLE_MPU6500(bus->spi.csnPin); + DISABLE_MPU6500(bus->busdev.spi.csnPin); return true; } @@ -72,8 +72,8 @@ static void mpu6500SpiInit(const busDevice_t *bus) return; } - IOInit(bus->spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); - IOConfigGPIO(bus->spi.csnPin, SPI_IO_CS_CFG); + IOInit(bus->busdev.spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); + IOConfigGPIO(bus->busdev.spi.csnPin, SPI_IO_CS_CFG); spiSetSpeed(MPU6500_SPI_INSTANCE, SPI_CLOCK_FAST); diff --git a/src/main/drivers/accgyro/accgyro_spi_mpu9250.c b/src/main/drivers/accgyro/accgyro_spi_mpu9250.c index bf7a49cbfc4..9cd43acac6b 100644 --- a/src/main/drivers/accgyro/accgyro_spi_mpu9250.c +++ b/src/main/drivers/accgyro/accgyro_spi_mpu9250.c @@ -54,21 +54,21 @@ static bool mpuSpi9250InitDone = false; bool mpu9250SpiReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t length, uint8_t *data) { - ENABLE_MPU9250(bus->spi.csnPin); + ENABLE_MPU9250(bus->busdev.spi.csnPin); spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length); - DISABLE_MPU9250(bus->spi.csnPin); + DISABLE_MPU9250(bus->busdev.spi.csnPin); return true; } bool mpu9250SpiSlowReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t length, uint8_t *data) { - ENABLE_MPU9250(bus->spi.csnPin); + ENABLE_MPU9250(bus->busdev.spi.csnPin); delayMicroseconds(1); spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length); - DISABLE_MPU9250(bus->spi.csnPin); + DISABLE_MPU9250(bus->busdev.spi.csnPin); delayMicroseconds(1); return true; @@ -76,11 +76,11 @@ bool mpu9250SpiSlowReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t len bool mpu9250SpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) { - ENABLE_MPU9250(bus->spi.csnPin); + ENABLE_MPU9250(bus->busdev.spi.csnPin); delayMicroseconds(1); spiTransferByte(MPU9250_SPI_INSTANCE, reg); spiTransferByte(MPU9250_SPI_INSTANCE, data); - DISABLE_MPU9250(bus->spi.csnPin); + DISABLE_MPU9250(bus->busdev.spi.csnPin); delayMicroseconds(1); return true; @@ -158,8 +158,8 @@ static void mpu9250AccAndGyroInit(gyroDev_t *gyro) bool mpu9250SpiDetect(const busDevice_t *bus) { /* not the best place for this - should really have an init method */ - IOInit(bus->spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); - IOConfigGPIO(bus->spi.csnPin, SPI_IO_CS_CFG); + IOInit(bus->busdev.spi.csnPin, OWNER_MPU, RESOURCE_SPI_CS, 0); + IOConfigGPIO(bus->busdev.spi.csnPin, SPI_IO_CS_CFG); spiSetSpeed(MPU9250_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); //low speed mpu9250SpiWriteRegister(bus, MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET); diff --git a/src/main/drivers/barometer/barometer_spi_bmp280.c b/src/main/drivers/barometer/barometer_spi_bmp280.c index c2b798d848f..70a837b7ed2 100644 --- a/src/main/drivers/barometer/barometer_spi_bmp280.c +++ b/src/main/drivers/barometer/barometer_spi_bmp280.c @@ -21,7 +21,7 @@ #include #include "drivers/io.h" -#include "drivers/bus_spi.h" +#include "drivers/bus.h" #include "drivers/barometer/barometer.h" #include "drivers/barometer/barometer_bmp280.h" @@ -35,6 +35,8 @@ extern int32_t bmp280_ut; static IO_t bmp280CsPin = IO_NONE; +BUSDEV_REGISTER_SPI(bmp280_busdev, DEVHW_BMP280, 0, BMP280_CS_PIN); + bool bmp280WriteRegister(uint8_t reg, uint8_t data) { ENABLE_BMP280; diff --git a/src/main/drivers/bus.c b/src/main/drivers/bus.c new file mode 100755 index 00000000000..21277e8c932 --- /dev/null +++ b/src/main/drivers/bus.c @@ -0,0 +1,158 @@ +/* + * This file is part of INAV. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License Version 3, as described below: + * + * This file is free software: you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +#include "platform.h" + +#include "drivers/bus.h" +#include "drivers/io.h" + +static void busDevPreInit_SPI(const busDeviceDescriptor_t * descriptor) +{ + // Pre-initialize SPI device chip-select line to input with weak pull-up + IO_t io = IOGetByTag(descriptor->busdev.spi.csnPin); + if (io) { + IOInit(io, OWNER_SPI_PREINIT, RESOURCE_SPI_CS, 0); + IOConfigGPIO(io, IOCFG_IPU); + } +} + +void busInit(void) +{ + /* Pre-initialize bus devices */ + for (const busDeviceDescriptor_t * descriptor = __busdev_registry_start; (descriptor) < __busdev_registry_end; descriptor++) { + switch (descriptor->busType) { + case BUSTYPE_NONE: + break; + + case BUSTYPE_I2C: + break; + + case BUSTYPE_SPI: + busDevPreInit_SPI(descriptor); + break; + } + } +} + +static bool busDevInit_I2C(busDevice_t * dev, const busDeviceDescriptor_t * descriptor) +{ + dev->busType = descriptor->busType; + dev->busdev.i2c.i2cBus = descriptor->busdev.i2c.i2cBus; + dev->busdev.i2c.address = descriptor->busdev.i2c.address; + return true; +} + +static bool busDevInit_SPI(busDevice_t * dev, const busDeviceDescriptor_t * descriptor, resourceOwner_e owner) +{ + dev->busType = descriptor->busType; + dev->busdev.spi.spiBus = descriptor->busdev.spi.spiBus; + dev->busdev.spi.csnPin = IOGetByTag(descriptor->busdev.spi.csnPin); + + if (dev->busdev.spi.csnPin) { + IOInit(dev->busdev.spi.csnPin, owner, RESOURCE_SPI_CS, 0); + IOConfigGPIO(dev->busdev.spi.csnPin, SPI_IO_CS_CFG); + IOHi(dev->busdev.spi.csnPin); + return true; + } + + return false; +} + +bool busDeviceInit(busDevice_t * dev, busType_e bus, devHardwareType_e hw, resourceOwner_e owner) +{ + for (const busDeviceDescriptor_t * descriptor = __busdev_registry_start; (descriptor) < __busdev_registry_end; descriptor++) { + if (hw == descriptor->devHwType && (bus == descriptor->busType || bus == BUSTYPE_ANY)) { + switch (descriptor->busType) { + case BUSTYPE_NONE: + dev->busType = BUSTYPE_NONE; + return false; + + case BUSTYPE_I2C: + return busDevInit_I2C(dev, descriptor); + + case BUSTYPE_SPI: + return busDevInit_SPI(dev, descriptor, owner); + break; + } + } + } + + return false; +} + +/* +bool busWriteBuf(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length) +{ + switch (dev->busType) { + case BUSTYPE_NONE: + return false; + case BUSTYPE_SPI: + return spiBusWriteBuffer(dev, reg & 0x7f, data, length); + case BUSTYPE_I2C: + return i2cBusWriteBuffer(dev, reg, data); + } +} +*/ + +bool busWrite(const busDevice_t * dev, uint8_t reg, uint8_t data) +{ + switch (dev->busType) { + case BUSTYPE_NONE: + return false; + case BUSTYPE_SPI: + return spiBusWriteRegister(dev, reg & 0x7f, data); + case BUSTYPE_I2C: + return i2cBusWriteRegister(dev, reg, data); + } + + return false; +} + +bool busReadBuf(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length) +{ + switch (dev->busType) { + case BUSTYPE_NONE: + return false; + case BUSTYPE_SPI: + return spiBusReadBuffer(dev, reg | 0x80, data, length); + case BUSTYPE_I2C: + return i2cBusReadBuffer(dev, reg, data, length); + } + + return false; +} + +bool busRead(const busDevice_t * dev, uint8_t reg, uint8_t * data) +{ + switch (dev->busType) { + case BUSTYPE_SPI: + return spiBusReadRegister(dev, reg | 0x80, data); + case BUSTYPE_I2C: + return i2cBusReadRegister(dev, reg, data); + case BUSTYPE_NONE: + return false; + } + + return false; +} diff --git a/src/main/drivers/bus.h b/src/main/drivers/bus.h new file mode 100755 index 00000000000..601317a9636 --- /dev/null +++ b/src/main/drivers/bus.h @@ -0,0 +1,115 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#pragma once + +#include +#include + +#include "platform.h" + +#include "drivers/resource.h" +#include "drivers/bus_i2c.h" +#include "drivers/bus_spi.h" + +typedef enum { + BUSTYPE_ANY = 0, + BUSTYPE_NONE = 0, + BUSTYPE_I2C = 1, + BUSTYPE_SPI = 2 +} busType_e; + +/* Ultimately all hardware descriptors will go to target definition files. + * Driver code will merely query for it's HW descriptor and initialize it */ +typedef enum { + DEVHW_NONE, + DEVHW_MAX7456, + DEVHW_BMP280 +} devHardwareType_e; + +typedef struct busDeviceDescriptor_s { + busType_e busType; + devHardwareType_e devHwType; + union { + struct { + SPIDevice spiBus; + ioTag_t csnPin; + } spi; + struct { + I2CDevice i2cBus; + uint8_t address; + } i2c; + } busdev; +} busDeviceDescriptor_t; + +typedef struct busDevice_s { + busType_e busType; + union { + struct { + SPIDevice spiBus; + IO_t csnPin; + } spi; + struct { + I2CDevice i2cBus; + uint8_t address; + } i2c; + } busdev; +} busDevice_t; + +#ifdef __APPLE__ +extern const busDeviceDescriptor_t __busdev_registry_start[] __asm("section$start$__DATA$__busdev_registry"); +extern const busDeviceDescriptor_t __busdev_registry_end[] __asm("section$end$__DATA$__busdev_registry"); +#define BUSDEV_REGISTER_ATTRIBUTES __attribute__ ((section("__DATA,__busdev_registry"), used, aligned(4))) +#else +extern const busDeviceDescriptor_t __busdev_registry_start[]; +extern const busDeviceDescriptor_t __busdev_registry_end[]; +#define BUSDEV_REGISTER_ATTRIBUTES __attribute__ ((section(".busdev_registry"), used, aligned(4))) +#endif + +#define BUSDEV_REGISTER_SPI(_name, _devHw, _spiBus, _csnPin) \ + extern const busDeviceDescriptor_t _name; \ + const busDeviceDescriptor_t _name BUSDEV_REGISTER_ATTRIBUTES = { \ + .busType = BUSTYPE_SPI, \ + .devHwType = _devHw, \ + .busdev.spi = { \ + .spiBus = _spiBus, \ + .csnPin = IO_TAG(_csnPin) \ + } \ + }; \ + /**/ + + +/* Internal abstraction function */ +bool i2cBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data); +bool i2cBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length); +bool i2cBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data); + +bool spiBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data); +bool spiBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length); +bool spiBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data); + +/* Pre-initialize all known device descriptors to make sure hardware state is consistent and known + * Initialize bus hardware */ +void busInit(void); + +/* Finds a device in registry. First matching device is returned. Also performs the low-level initialization of the hardware (CS line for SPI) */ +bool busDeviceInit(busDevice_t * dev, busType_e bus, devHardwareType_e hw, resourceOwner_e owner); + +bool busWriteBuf(const busDevice_t * busdev, uint8_t reg, uint8_t * data, uint8_t length); +bool busWrite(const busDevice_t * busdev, uint8_t reg, uint8_t data); +bool busReadBuf(const busDevice_t * busdev, uint8_t reg, uint8_t * data, uint8_t length); +bool busRead(const busDevice_t * busdev, uint8_t reg, uint8_t * data); \ No newline at end of file diff --git a/src/main/drivers/bus_busdev_i2c.c b/src/main/drivers/bus_busdev_i2c.c new file mode 100755 index 00000000000..70e42e87baf --- /dev/null +++ b/src/main/drivers/bus_busdev_i2c.c @@ -0,0 +1,43 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include +#include +#include + +#include + +#if defined(USE_I2C) + +#include "drivers/bus.h" +#include "drivers/bus_i2c.h" + +bool i2cBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data) +{ + return i2cWrite(dev->busdev.i2c.i2cBus, dev->busdev.i2c.address, reg, data); +} + +bool i2cBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length) +{ + return i2cRead(dev->busdev.i2c.i2cBus, dev->busdev.i2c.address, reg, length, data); +} + +bool i2cBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data) +{ + return i2cRead(dev->busdev.i2c.i2cBus, dev->busdev.i2c.address, reg, 1, data); +} +#endif diff --git a/src/main/drivers/bus_busdev_spi.c b/src/main/drivers/bus_busdev_spi.c new file mode 100755 index 00000000000..85817f00ec7 --- /dev/null +++ b/src/main/drivers/bus_busdev_spi.c @@ -0,0 +1,65 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include +#include +#include + +#include + +#if defined(USE_SPI) + +#include "drivers/io.h" +#include "drivers/bus.h" +#include "drivers/bus_spi.h" + +bool spiBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data) +{ + SPI_TypeDef * instance = spiInstanceByDevice(dev->busdev.spi.spiBus); + + IOLo(dev->busdev.spi.csnPin); + spiTransferByte(instance, reg); + spiTransferByte(instance, data); + IOHi(dev->busdev.spi.csnPin); + + return true; +} + +bool spiBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length) +{ + SPI_TypeDef * instance = spiInstanceByDevice(dev->busdev.spi.spiBus); + + IOLo(dev->busdev.spi.csnPin); + spiTransferByte(instance, reg); + spiTransfer(instance, NULL, data, length); + IOHi(dev->busdev.spi.csnPin); + + return true; +} + +bool spiBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data) +{ + SPI_TypeDef * instance = spiInstanceByDevice(dev->busdev.spi.spiBus); + + IOLo(dev->busdev.spi.csnPin); + spiTransferByte(instance, reg); + spiTransfer(instance, NULL, data, 1); + IOHi(dev->busdev.spi.csnPin); + + return true; +} +#endif diff --git a/src/main/drivers/bus_spi.c b/src/main/drivers/bus_spi.c index f4a765edf70..12a07967406 100644 --- a/src/main/drivers/bus_spi.c +++ b/src/main/drivers/bus_spi.c @@ -368,4 +368,9 @@ void spiResetErrorCounter(SPI_TypeDef *instance) spiHardwareMap[device].errorCount = 0; } } + +SPI_TypeDef * spiInstanceByDevice(SPIDevice device) +{ + return spiHardwareMap[device].dev; +} #endif // USE_SPI diff --git a/src/main/drivers/bus_spi.h b/src/main/drivers/bus_spi.h index 1293a3306f1..fb9a6532a20 100644 --- a/src/main/drivers/bus_spi.h +++ b/src/main/drivers/bus_spi.h @@ -96,6 +96,7 @@ bool spiTransfer(SPI_TypeDef *instance, uint8_t *out, const uint8_t *in, int len uint16_t spiGetErrorCounter(SPI_TypeDef *instance); void spiResetErrorCounter(SPI_TypeDef *instance); SPIDevice spiDeviceByInstance(SPI_TypeDef *instance); +SPI_TypeDef * spiInstanceByDevice(SPIDevice device); #if defined(USE_HAL_DRIVER) SPI_HandleTypeDef* spiHandleByInstance(SPI_TypeDef *instance); diff --git a/src/main/drivers/bus_spi_hal.c b/src/main/drivers/bus_spi_hal.c index e39b0c3bd6e..4e5d0239774 100644 --- a/src/main/drivers/bus_spi_hal.c +++ b/src/main/drivers/bus_spi_hal.c @@ -371,3 +371,8 @@ DMA_HandleTypeDef* spiSetDMATransmit(DMA_Stream_TypeDef *Stream, uint32_t Channe return &spiHardwareMap[device].hdma; } + +SPI_TypeDef * spiInstanceByDevice(SPIDevice device) +{ + return spiHardwareMap[device].dev; +} diff --git a/src/main/drivers/bus_spi_soft.c b/src/main/drivers/bus_spi_soft.c index 5fea7d9c869..4a29de21abf 100644 --- a/src/main/drivers/bus_spi_soft.c +++ b/src/main/drivers/bus_spi_soft.c @@ -85,4 +85,9 @@ uint8_t softSpiTransferByte(const softSPIDevice_t *dev, uint8_t byte) } return byte; } + +SPI_TypeDef * spiInstanceByDevice(SPIDevice device) +{ + return NULL; +} #endif diff --git a/src/main/drivers/compass/compass_ak8963.c b/src/main/drivers/compass/compass_ak8963.c index 2367f8b34d6..726cb4e8fe6 100755 --- a/src/main/drivers/compass/compass_ak8963.c +++ b/src/main/drivers/compass/compass_ak8963.c @@ -110,11 +110,11 @@ static queuedReadState_t queuedRead = { false, 0, 0}; */ static bool mpuSpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) { - ENABLE_SPI_MPU(bus->spi.csnPin); + ENABLE_SPI_MPU(bus->busdev.spi.csnPin); delayMicroseconds(1); spiTransferByte(MPU_SPI_INSTANCE, reg); spiTransferByte(MPU_SPI_INSTANCE, data); - DISABLE_SPI_MPU(bus->spi.csnPin); + DISABLE_SPI_MPU(bus->busdev.spi.csnPin); delayMicroseconds(1); return true; @@ -122,10 +122,10 @@ static bool mpuSpiWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t dat static bool mpuSpiReadRegister(const busDevice_t *bus, uint8_t reg, uint8_t length, uint8_t *data) { - ENABLE_SPI_MPU(bus->spi.csnPin); + ENABLE_SPI_MPU(bus->busdev.spi.csnPin); spiTransferByte(MPU_SPI_INSTANCE, reg | 0x80); // read transaction spiTransfer(MPU_SPI_INSTANCE, data, NULL, length); - DISABLE_SPI_MPU(bus->spi.csnPin); + DISABLE_SPI_MPU(bus->busdev.spi.csnPin); return true; } diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index dd32195294c..cbe7d8dd332 100644 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -28,7 +28,7 @@ #include "common/printf.h" #include "common/utils.h" -#include "drivers/bus_spi.h" +#include "drivers/bus.h" #include "drivers/light_led.h" #include "drivers/io.h" #include "drivers/time.h" @@ -207,6 +207,8 @@ static bool max7456Lock = false; static bool fontIsLoading = false; static IO_t max7456CsPin = IO_NONE; +// Register bus device descriptor +BUSDEV_REGISTER_SPI(max7456_busdev, DEVHW_MAX7456, 0, MAX7456_SPI_CS_PIN); static uint8_t max7456Send(uint8_t add, uint8_t data) { diff --git a/src/main/drivers/resource.c b/src/main/drivers/resource.c index 7c1d601f73d..cca13ef7469 100644 --- a/src/main/drivers/resource.c +++ b/src/main/drivers/resource.c @@ -21,7 +21,7 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = { "FREE", "PWM", "PPM", "MOTOR", "SERVO", "SOFTSERIAL", "ADC", "SERIAL", "DEBUG", "TIMER", "RANGEFINDER", "SYSTEM", "SPI", "I2C", "SDCARD", "FLASH", "USB", "BEEPER", "OSD", "BARO", "MPU", "INVERTER", "LED STRIP", "LED", "RECEIVER", "TRANSMITTER", - "SOFTSPI", "NRF24", "VTX" + "SOFTSPI", "NRF24", "VTX", "SPI_PREINIT" }; const char * const resourceNames[RESOURCE_TOTAL_COUNT] = { diff --git a/src/main/drivers/resource.h b/src/main/drivers/resource.h index 4b3141abe33..0e223315a40 100644 --- a/src/main/drivers/resource.h +++ b/src/main/drivers/resource.h @@ -49,6 +49,7 @@ typedef enum { OWNER_SOFTSPI, OWNER_RX_SPI, OWNER_VTX, + OWNER_SPI_PREINIT, OWNER_TOTAL_COUNT } resourceOwner_e; diff --git a/src/main/drivers/sensor.h b/src/main/drivers/sensor.h index 28c404f3e46..3d2b92ebce8 100644 --- a/src/main/drivers/sensor.h +++ b/src/main/drivers/sensor.h @@ -21,6 +21,7 @@ #include #include "drivers/io_types.h" +#include "drivers/bus.h" typedef enum { ALIGN_DEFAULT = 0, // driver-provided alignment @@ -34,15 +35,6 @@ typedef enum { CW270_DEG_FLIP = 8 } sensor_align_e; -typedef union busDevice_u { - struct deviceSpi_s { - IO_t csnPin; - } spi; - struct deviceI2C_s { - uint8_t address; - } i2c; -} busDevice_t; - typedef bool (*sensorInitFuncPtr)(void); // sensor init prototype typedef bool (*sensorReadFuncPtr)(int16_t *data); // sensor read and align prototype typedef bool (*sensorInterruptFuncPtr)(void); diff --git a/src/main/fc/fc_init.c b/src/main/fc/fc_init.c index 8fc4c546c18..4cfa53614c0 100644 --- a/src/main/fc/fc_init.c +++ b/src/main/fc/fc_init.c @@ -43,8 +43,7 @@ #include "drivers/accgyro/accgyro.h" #include "drivers/adc.h" #include "drivers/compass/compass.h" -#include "drivers/bus_i2c.h" -#include "drivers/bus_spi.h" +#include "drivers/bus.h" #include "drivers/dma.h" #include "drivers/exti.h" #include "drivers/flash_m25p16.h" @@ -379,6 +378,8 @@ void init(void) initInverters(); #endif + // Initialize buses + busInit(); #ifdef USE_SPI #ifdef USE_SPI_DEVICE_1 diff --git a/src/main/sensors/gyro.c b/src/main/sensors/gyro.c index 1601be39d44..c447bfd9ebe 100644 --- a/src/main/sensors/gyro.c +++ b/src/main/sensors/gyro.c @@ -276,9 +276,9 @@ bool gyroInit(void) #ifdef USE_GYRO_MPU #ifdef USE_DUAL_GYRO // set cnsPin using GYRO_n_CS_PIN defined in target.h - gyroDev0.bus.spi.csnPin = gyroConfig()->gyro_to_use == 0 ? IOGetByTag(IO_TAG(GYRO_0_CS_PIN)) : IOGetByTag(IO_TAG(GYRO_1_CS_PIN)); + gyroDev0.bus.busdev.spi.csnPin = gyroConfig()->gyro_to_use == 0 ? IOGetByTag(IO_TAG(GYRO_0_CS_PIN)) : IOGetByTag(IO_TAG(GYRO_1_CS_PIN)); #else - gyroDev0.bus.spi.csnPin = IO_NONE; // set cnsPin to IO_NONE so mpuDetect will set it according to value defined in target.h + gyroDev0.bus.busdev.spi.csnPin = IO_NONE; // set cnsPin to IO_NONE so mpuDetect will set it according to value defined in target.h #endif // USE_DUAL_GYRO mpuDetect(&gyroDev0); mpuResetFn = gyroDev0.mpuConfiguration.resetFn; diff --git a/src/main/target/link/stm32_flash.ld b/src/main/target/link/stm32_flash.ld index e24c542d408..83f6aeb32c6 100644 --- a/src/main/target/link/stm32_flash.ld +++ b/src/main/target/link/stm32_flash.ld @@ -90,6 +90,13 @@ SECTIONS KEEP (*(.pg_resetdata)) PROVIDE_HIDDEN (__pg_resetdata_end = .); } >FLASH + .busdev_registry : + { + PROVIDE_HIDDEN (__busdev_registry_start = .); + KEEP (*(.busdev_registry)) + KEEP (*(SORT(.busdev_registry.*))) + PROVIDE_HIDDEN (__busdev_registry_end = .); + } >FLASH /* used by the startup to initialize data */ _sidata = .; diff --git a/src/main/target/link/stm32_flash_split.ld b/src/main/target/link/stm32_flash_split.ld index 3249c189b65..6e4148b075c 100644 --- a/src/main/target/link/stm32_flash_split.ld +++ b/src/main/target/link/stm32_flash_split.ld @@ -90,6 +90,13 @@ SECTIONS KEEP (*(.pg_resetdata)) PROVIDE_HIDDEN (__pg_resetdata_end = .); } >FLASH + .busdev_registry : + { + PROVIDE_HIDDEN (__busdev_registry_start = .); + KEEP (*(.busdev_registry)) + KEEP (*(SORT(.busdev_registry.*))) + PROVIDE_HIDDEN (__busdev_registry_end = .); + } >FLASH /* used by the startup to initialize data */ _sidata = .;