diff --git a/Makefile b/Makefile index e9681780b..1ec2918c1 100644 --- a/Makefile +++ b/Makefile @@ -134,6 +134,8 @@ GROUP_2_TARGETS := \ FF_PIKOBLX \ FF_PIKOF4 \ FF_RADIANCE \ + FRSKYF3 \ + FRSKYF4 \ FURYF3 \ FURYF4 \ FURYF7 \ @@ -675,6 +677,7 @@ COMMON_SRC = \ config/config_streamer.c \ drivers/adc.c \ drivers/buf_writer.c \ + drivers/bus_i2c_config.c \ drivers/bus_i2c_soft.c \ drivers/bus_spi.c \ drivers/bus_spi_soft.c \ @@ -892,7 +895,11 @@ SPEED_OPTIMISED_SRC := $(SPEED_OPTIMISED_SRC) \ io/osd_slave.c SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \ + drivers/bus_i2c_config.c \ drivers/serial_escserial.c \ + drivers/serial_pinconfig.c \ + drivers/serial_uart_init.c \ + drivers/serial_uart_pinconfig.c \ drivers/vtx_rtc6705_soft_spi.c \ drivers/vtx_rtc6705.c \ drivers/vtx_common.c \ @@ -903,9 +910,6 @@ SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \ config/feature.c \ config/parameter_group.c \ config/config_streamer.c \ - drivers/serial_pinconfig.c \ - drivers/serial_uart_init.c \ - drivers/serial_uart_pinconfig.c \ io/serial_4way.c \ io/serial_4way_avrootloader.c \ io/serial_4way_stk500v2.c \ @@ -1019,6 +1023,7 @@ SITLEXCLUDES = \ drivers/adc.c \ drivers/bus_spi.c \ drivers/bus_i2c.c \ + drivers/bus_i2c_config.c \ drivers/dma.c \ drivers/pwm_output.c \ drivers/timer.c \ diff --git a/src/main/config/parameter_group_ids.h b/src/main/config/parameter_group_ids.h index 77895849d..e4b0bb3f5 100644 --- a/src/main/config/parameter_group_ids.h +++ b/src/main/config/parameter_group_ids.h @@ -106,7 +106,8 @@ #define PG_VTX_CONFIG 515 #define PG_SONAR_CONFIG 516 #define PG_ESC_SENSOR_CONFIG 517 -#define PG_BETAFLIGHT_END 517 +#define PG_I2C_CONFIG 518 +#define PG_BETAFLIGHT_END 518 // OSD configuration (subject to change) diff --git a/src/main/target/ALIENFLIGHTF3/initialisation.c b/src/main/drivers/bus.h similarity index 55% rename from src/main/target/ALIENFLIGHTF3/initialisation.c rename to src/main/drivers/bus.h index f435cb994..d1c196189 100644 --- a/src/main/target/ALIENFLIGHTF3/initialisation.c +++ b/src/main/drivers/bus.h @@ -15,34 +15,10 @@ * along with Cleanflight. If not, see . */ -#include -#include +#pragma once #include "platform.h" -#include "drivers/bus_i2c.h" -#include "drivers/bus_spi.h" -#include "hardware_revision.h" -void targetBusInit(void) -{ - #ifdef USE_SPI - #ifdef USE_SPI_DEVICE_1 - spiInit(SPIDEV_1); - #endif - #ifdef USE_SPI_DEVICE_2 - spiInit(SPIDEV_2); - #endif - #ifdef USE_SPI_DEVICE_3 - if (hardwareRevision == AFF3_REV_2) { - spiInit(SPIDEV_3); - } - #endif - #ifdef USE_SPI_DEVICE_4 - spiInit(SPIDEV_4); - #endif - #endif - - #ifdef USE_I2C - i2cInit(I2C_DEVICE); - #endif -} \ No newline at end of file +#ifdef TARGET_BUS_INIT +void targetBusInit(void); +#endif diff --git a/src/main/drivers/bus_i2c.h b/src/main/drivers/bus_i2c.h index dd5ee8a8e..bd2712599 100644 --- a/src/main/drivers/bus_i2c.h +++ b/src/main/drivers/bus_i2c.h @@ -19,14 +19,10 @@ #include "platform.h" +#include "config/parameter_group.h" #include "drivers/io_types.h" #include "drivers/rcc_types.h" -#define I2C_SHORT_TIMEOUT ((uint32_t)0x1000) -#define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT)) -#define I2C_DEFAULT_TIMEOUT I2C_SHORT_TIMEOUT - - #ifndef I2C_DEVICE #define I2C_DEVICE I2CINVALID #endif @@ -36,39 +32,27 @@ typedef enum I2CDevice { I2CDEV_1 = 0, I2CDEV_2, I2CDEV_3, -#ifdef USE_I2C_DEVICE_4 I2CDEV_4, -#endif - I2CDEV_COUNT } I2CDevice; -typedef struct i2cDevice_s { - I2C_TypeDef *dev; - ioTag_t scl; - ioTag_t sda; - rccPeriphTag_t rcc; - bool overClock; -#if !defined(STM32F303xC) - uint8_t ev_irq; - uint8_t er_irq; +#if defined(STM32F1) || defined(STM32F3) +#define I2CDEV_COUNT 2 +#elif defined(STM32F4) +#define I2CDEV_COUNT 3 +#elif defined(STM32F7) +#define I2CDEV_COUNT 4 +#else +#define I2CDEV_COUNT 4 #endif -#if defined(STM32F7) - uint8_t af; -#endif -} i2cDevice_t; -typedef struct i2cState_s { - volatile bool error; - volatile bool busy; - volatile uint8_t addr; - volatile uint8_t reg; - volatile uint8_t bytes; - volatile uint8_t writing; - volatile uint8_t reading; - volatile uint8_t* write_p; - volatile uint8_t* read_p; -} i2cState_t; +typedef struct i2cConfig_s { + ioTag_t ioTagScl[I2CDEV_COUNT]; + ioTag_t ioTagSda[I2CDEV_COUNT]; + bool overClock[I2CDEV_COUNT]; + bool pullUp[I2CDEV_COUNT]; +} i2cConfig_t; +void i2cHardwareConfigure(void); void i2cInit(I2CDevice device); bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, uint8_t *data); bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data); diff --git a/src/main/drivers/bus_i2c_config.c b/src/main/drivers/bus_i2c_config.c new file mode 100644 index 000000000..74af3f76f --- /dev/null +++ b/src/main/drivers/bus_i2c_config.c @@ -0,0 +1,262 @@ +/* + * 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 . + */ + +/* + * Created by jflyper + */ + +#include +#include +#include + +#include "platform.h" + +#include "build/build_config.h" +#include "build/debug.h" + +#include "drivers/io.h" +#include "drivers/bus_i2c.h" +#include "drivers/bus_i2c_impl.h" + +#include "config/parameter_group.h" +#include "config/parameter_group_ids.h" + +#if defined(USE_I2C) && !defined(SOFT_I2C) + +#ifdef I2C_FULL_RECONFIGURABILITY +#if I2CDEV_COUNT >= 1 +#ifndef I2C1_SCL +#define I2C1_SCL NONE +#endif +#ifndef I2C1_SDA +#define I2C1_SDA NONE +#endif +#endif + +#if I2CDEV_COUNT >= 2 +#ifndef I2C2_SCL +#define I2C2_SCL NONE +#endif +#ifndef I2C2_SDA +#define I2C2_SDA NONE +#endif +#endif + +#if I2CDEV_COUNT >= 3 +#ifndef I2C3_SCL +#define I2C3_SCL NONE +#endif +#ifndef I2C3_SDA +#define I2C3_SDA NONE +#endif +#endif + +#if I2CDEV_COUNT >= 4 +#ifndef I2C4_SCL +#define I2C4_SCL NONE +#endif +#ifndef I2C4_SDA +#define I2C4_SDA NONE +#endif +#endif + +#else // I2C_FULL_RECONFIGURABILITY + +// Backward compatibility for exisiting targets + +#ifdef STM32F1 +#ifndef I2C1_SCL +#define I2C1_SCL PB8 +#endif +#ifndef I2C1_SDA +#define I2C1_SDA PB9 +#endif +#ifndef I2C2_SCL +#define I2C2_SCL PB10 +#endif +#ifndef I2C2_SDA +#define I2C2_SDA PB11 +#endif +#endif // STM32F1 + +#ifdef STM32F3 +#ifndef I2C1_SCL +#define I2C1_SCL PB6 +#endif +#ifndef I2C1_SDA +#define I2C1_SDA PB7 +#endif +#ifndef I2C2_SCL +#define I2C2_SCL PA9 +#endif +#ifndef I2C2_SDA +#define I2C2_SDA PA10 +#endif +#endif // STM32F3 + +#ifdef STM32F4 +#ifndef I2C1_SCL +#define I2C1_SCL PB6 +#endif +#ifndef I2C1_SDA +#define I2C1_SDA PB7 +#endif +#ifndef I2C2_SCL +#define I2C2_SCL PB10 +#endif +#ifndef I2C2_SDA +#define I2C2_SDA PB11 +#endif +#ifndef I2C3_SCL +#define I2C3_SCL PA8 +#endif +#ifndef I2C3_SDA +#define I2C3_SDA PC9 +#endif +#endif // STM32F4 + +#ifdef STM32F7 +#ifndef I2C1_SCL +#define I2C1_SCL PB6 +#endif +#ifndef I2C1_SDA +#define I2C1_SDA PB7 +#endif +#ifndef I2C2_SCL +#define I2C2_SCL PB10 +#endif +#ifndef I2C2_SDA +#define I2C2_SDA PB11 +#endif +#ifndef I2C3_SCL +#define I2C3_SCL PA8 +#endif +#ifndef I2C3_SDA +#define I2C3_SDA PB4 +#endif +#ifndef I2C4_SCL +#define I2C4_SCL PD12 +#endif +#ifndef I2C4_SDA +#define I2C4_SDA PD13 +#endif +#endif // STM32F7 + +#endif // I2C_FULL_RECONFIGURABILITY + +// Backward compatibility for overclocking and internal pullup. +// These will eventually be configurable through PG-based configurator +// (and/or probably through some cli extension). + +#ifndef I2C1_OVERCLOCK +#define I2C1_OVERCLOCK false +#endif +#ifndef I2C2_OVERCLOCK +#define I2C2_OVERCLOCK false +#endif +#ifndef I2C3_OVERCLOCK +#define I2C3_OVERCLOCK false +#endif +#ifndef I2C4_OVERCLOCK +#define I2C4_OVERCLOCK false +#endif + +// Default values for internal pullup + +#if defined(USE_I2C_PULLUP) +#define I2C1_PULLUP true +#define I2C2_PULLUP true +#define I2C3_PULLUP true +#define I2C4_PULLUP true +#else +#define I2C1_PULLUP false +#define I2C2_PULLUP false +#define I2C3_PULLUP false +#define I2C4_PULLUP false +#endif + +typedef struct i2cDefaultConfig_s { + I2CDevice device; + ioTag_t ioTagScl, ioTagSda; + bool overClock; + bool pullUp; +} i2cDefaultConfig_t; + +static const i2cDefaultConfig_t i2cDefaultConfig[] = { +#ifdef USE_I2C_DEVICE_1 + { I2CDEV_1, IO_TAG(I2C1_SCL), IO_TAG(I2C1_SDA), I2C1_OVERCLOCK, I2C1_PULLUP }, +#endif +#ifdef USE_I2C_DEVICE_2 + { I2CDEV_2, IO_TAG(I2C2_SCL), IO_TAG(I2C2_SDA), I2C2_OVERCLOCK, I2C2_PULLUP }, +#endif +#ifdef USE_I2C_DEVICE_3 + { I2CDEV_3, IO_TAG(I2C3_SCL), IO_TAG(I2C3_SDA), I2C3_OVERCLOCK, I2C3_PULLUP }, +#endif +#ifdef USE_I2C_DEVICE_4 + { I2CDEV_4, IO_TAG(I2C4_SCL), IO_TAG(I2C4_SDA), I2C4_OVERCLOCK, I2C4_PULLUP }, +#endif +}; + +PG_DECLARE(i2cConfig_t, i2cConfig); +PG_REGISTER_WITH_RESET_FN(i2cConfig_t, i2cConfig, PG_I2C_CONFIG, 0); + +void pgResetFn_i2cConfig(i2cConfig_t *i2cConfig) +{ + memset(i2cConfig, 0, sizeof(*i2cConfig)); + + for (size_t index = 0 ; index < ARRAYLEN(i2cDefaultConfig) ; index++) { + const i2cDefaultConfig_t *defconf = &i2cDefaultConfig[index]; + i2cConfig->ioTagScl[defconf->device] = defconf->ioTagScl; + i2cConfig->ioTagSda[defconf->device] = defconf->ioTagSda; + i2cConfig->overClock[defconf->device] = defconf->overClock; + i2cConfig->pullUp[defconf->device] = defconf->pullUp; + } +} + +void i2cHardwareConfigure(void) +{ + const i2cConfig_t *pConfig = i2cConfig(); + + for (int index = 0 ; index < I2CDEV_COUNT ; index++) { + const i2cHardware_t *hardware = &i2cHardware[index]; + + if (!hardware->reg) { + continue; + } + + I2CDevice device = hardware->device; + i2cDevice_t *pDev = &i2cDevice[device]; + + memset(pDev, 0, sizeof(*pDev)); + + for (int pindex = 0 ; pindex < I2C_PIN_SEL_MAX ; pindex++) { + if (pConfig->ioTagScl[device] == hardware->sclPins[pindex]) + pDev->scl = IOGetByTag(pConfig->ioTagScl[device]); + if (pConfig->ioTagSda[device] == hardware->sdaPins[pindex]) + pDev->sda = IOGetByTag(pConfig->ioTagSda[device]); + } + + if (pDev->scl && pDev->sda) { + pDev->hardware = hardware; + pDev->reg = hardware->reg; + pDev->overClock = pConfig->overClock[device]; + pDev->pullUp = pConfig->pullUp[device]; + } + } +} + +#endif // defined(USE_I2C) && !defined(USE_SOFT_I2C) diff --git a/src/main/drivers/bus_i2c_hal.c b/src/main/drivers/bus_i2c_hal.c index 006a19c1a..ac8508447 100644 --- a/src/main/drivers/bus_i2c_hal.c +++ b/src/main/drivers/bus_i2c_hal.c @@ -17,114 +17,118 @@ #include #include +#include #include -#include "drivers/bus_i2c.h" #include "drivers/io.h" +#include "drivers/io_impl.h" #include "drivers/nvic.h" #include "drivers/time.h" +#include "drivers/rcc.h" -#include "io_impl.h" -#include "rcc.h" +#include "drivers/bus_i2c.h" +#include "drivers/bus_i2c_impl.h" - -#if !defined(SOFT_I2C) && defined(USE_I2C) +#if defined(USE_I2C) && !defined(SOFT_I2C) #define CLOCKSPEED 800000 // i2c clockspeed 400kHz default (conform specs), 800kHz and 1200kHz (Betaflight default) static void i2cUnstick(IO_t scl, IO_t sda); -#if defined(USE_I2C_PULLUP) -#define IOCFG_I2C IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP) -#else -#define IOCFG_I2C IOCFG_AF_OD -#endif +#define IOCFG_I2C_PU IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP) +#define IOCFG_I2C IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL) -#ifndef I2C1_SCL -#define I2C1_SCL PB6 -#endif +#define GPIO_AF4_I2C GPIO_AF4_I2C1 -#ifndef I2C1_SDA -#define I2C1_SDA PB7 +const i2cHardware_t i2cHardware[I2CDEV_COUNT] = { +#ifdef USE_I2C_DEVICE_1 + { + .device = I2CDEV_1, + .reg = I2C1, + .sclPins = { DEFIO_TAG_E(PB6), DEFIO_TAG_E(PB8) }, + .sdaPins = { DEFIO_TAG_E(PB7), DEFIO_TAG_E(PB9) }, + .rcc = RCC_APB1(I2C1), + .ev_irq = I2C1_EV_IRQn, + .er_irq = I2C1_ER_IRQn, + }, #endif - -#ifndef I2C2_SCL -#define I2C2_SCL PB10 +#ifdef USE_I2C_DEVICE_2 + { + .device = I2CDEV_2, + .reg = I2C2, + .sclPins = { DEFIO_TAG_E(PB10), DEFIO_TAG_E(PF1) }, + .sdaPins = { DEFIO_TAG_E(PB11), DEFIO_TAG_E(PF0) }, + .rcc = RCC_APB1(I2C2), + .ev_irq = I2C2_EV_IRQn, + .er_irq = I2C2_ER_IRQn, + }, #endif -#ifndef I2C2_SDA -#define I2C2_SDA PB11 +#ifdef USE_I2C_DEVICE_3 + { + .device = I2CDEV_3, + .reg = I2C3, + .sclPins = { DEFIO_TAG_E(PA8) }, + .sdaPins = { DEFIO_TAG_E(PC9) }, + .rcc = RCC_APB1(I2C3), + .ev_irq = I2C3_EV_IRQn, + .er_irq = I2C3_ER_IRQn, + }, #endif - -#ifndef I2C3_SCL -#define I2C3_SCL PA8 -#endif -#ifndef I2C3_SDA -#define I2C3_SDA PB4 -#endif - -#if defined(USE_I2C_DEVICE_4) -#ifndef I2C4_SCL -#define I2C4_SCL PD12 -#endif -#ifndef I2C4_SDA -#define I2C4_SDA PD13 -#endif -#endif - -static i2cDevice_t i2cHardwareMap[] = { - { .dev = I2C1, .scl = IO_TAG(I2C1_SCL), .sda = IO_TAG(I2C1_SDA), .rcc = RCC_APB1(I2C1), .overClock = I2C1_OVERCLOCK, .ev_irq = I2C1_EV_IRQn, .er_irq = I2C1_ER_IRQn, .af = GPIO_AF4_I2C1 }, - { .dev = I2C2, .scl = IO_TAG(I2C2_SCL), .sda = IO_TAG(I2C2_SDA), .rcc = RCC_APB1(I2C2), .overClock = I2C2_OVERCLOCK, .ev_irq = I2C2_EV_IRQn, .er_irq = I2C2_ER_IRQn, .af = GPIO_AF4_I2C2 }, - { .dev = I2C3, .scl = IO_TAG(I2C3_SCL), .sda = IO_TAG(I2C3_SDA), .rcc = RCC_APB1(I2C3), .overClock = I2C2_OVERCLOCK, .ev_irq = I2C3_EV_IRQn, .er_irq = I2C3_ER_IRQn, .af = GPIO_AF4_I2C3 }, -#if defined(USE_I2C_DEVICE_4) - { .dev = I2C4, .scl = IO_TAG(I2C4_SCL), .sda = IO_TAG(I2C4_SDA), .rcc = RCC_APB1(I2C4), .overClock = I2C2_OVERCLOCK, .ev_irq = I2C4_EV_IRQn, .er_irq = I2C4_ER_IRQn, .af = GPIO_AF4_I2C4 } +#ifdef USE_I2C_DEVICE_4 + { + .device = I2CDEV_4, + .reg = I2C4, + .sclPins = { DEFIO_TAG_E(PD12), DEFIO_TAG_E(PF14) }, + .sdaPins = { DEFIO_TAG_E(PD13), DEFIO_TAG_E(PF15) }, + .rcc = RCC_APB1(I2C4), + .ev_irq = I2C4_EV_IRQn, + .er_irq = I2C4_ER_IRQn, + }, #endif }; -typedef struct{ - I2C_HandleTypeDef Handle; -}i2cHandle_t; -static i2cHandle_t i2cHandle[I2CDEV_COUNT]; +i2cDevice_t i2cDevice[I2CDEV_COUNT]; void I2C1_ER_IRQHandler(void) { - HAL_I2C_ER_IRQHandler(&i2cHandle[I2CDEV_1].Handle); + HAL_I2C_ER_IRQHandler(&i2cDevice[I2CDEV_1].handle); } void I2C1_EV_IRQHandler(void) { - HAL_I2C_EV_IRQHandler(&i2cHandle[I2CDEV_1].Handle); + HAL_I2C_EV_IRQHandler(&i2cDevice[I2CDEV_1].handle); } void I2C2_ER_IRQHandler(void) { - HAL_I2C_ER_IRQHandler(&i2cHandle[I2CDEV_2].Handle); + HAL_I2C_ER_IRQHandler(&i2cDevice[I2CDEV_2].handle); } void I2C2_EV_IRQHandler(void) { - HAL_I2C_EV_IRQHandler(&i2cHandle[I2CDEV_2].Handle); + HAL_I2C_EV_IRQHandler(&i2cDevice[I2CDEV_2].handle); } void I2C3_ER_IRQHandler(void) { - HAL_I2C_ER_IRQHandler(&i2cHandle[I2CDEV_3].Handle); + HAL_I2C_ER_IRQHandler(&i2cDevice[I2CDEV_3].handle); } void I2C3_EV_IRQHandler(void) { - HAL_I2C_EV_IRQHandler(&i2cHandle[I2CDEV_3].Handle); + HAL_I2C_EV_IRQHandler(&i2cDevice[I2CDEV_3].handle); } #ifdef USE_I2C_DEVICE_4 void I2C4_ER_IRQHandler(void) { - HAL_I2C_ER_IRQHandler(&i2cHandle[I2CDEV_4].Handle); + HAL_I2C_ER_IRQHandler(&i2cDevice[I2CDEV_4].handle); } void I2C4_EV_IRQHandler(void) { - HAL_I2C_EV_IRQHandler(&i2cHandle[I2CDEV_4].Handle); + HAL_I2C_EV_IRQHandler(&i2cDevice[I2CDEV_4].handle); } #endif @@ -147,12 +151,22 @@ static bool i2cHandleHardwareFailure(I2CDevice device) bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, uint8_t *data) { + if (device == I2CINVALID || device > I2CDEV_COUNT) { + return false; + } + + I2C_HandleTypeDef *pHandle = &i2cDevice[device].handle; + + if (!pHandle->Instance) { + return false; + } + HAL_StatusTypeDef status; if(reg_ == 0xFF) - status = HAL_I2C_Master_Transmit(&i2cHandle[device].Handle,addr_ << 1,data, len_, I2C_DEFAULT_TIMEOUT); + status = HAL_I2C_Master_Transmit(pHandle ,addr_ << 1, data, len_, I2C_DEFAULT_TIMEOUT); else - status = HAL_I2C_Mem_Write(&i2cHandle[device].Handle,addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,data, len_, I2C_DEFAULT_TIMEOUT); + status = HAL_I2C_Mem_Write(pHandle ,addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,data, len_, I2C_DEFAULT_TIMEOUT); if(status != HAL_OK) return i2cHandleHardwareFailure(device); @@ -167,12 +181,22 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t data) bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf) { + if (device == I2CINVALID || device > I2CDEV_COUNT) { + return false; + } + + I2C_HandleTypeDef *pHandle = &i2cDevice[device].handle; + + if (!pHandle->Instance) { + return false; + } + HAL_StatusTypeDef status; if(reg_ == 0xFF) - status = HAL_I2C_Master_Receive(&i2cHandle[device].Handle,addr_ << 1,buf, len, I2C_DEFAULT_TIMEOUT); + status = HAL_I2C_Master_Receive(pHandle ,addr_ << 1, buf, len, I2C_DEFAULT_TIMEOUT); else - status = HAL_I2C_Mem_Read(&i2cHandle[device].Handle,addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,buf, len, I2C_DEFAULT_TIMEOUT); + status = HAL_I2C_Mem_Read(pHandle, addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,buf, len, I2C_DEFAULT_TIMEOUT); if(status != HAL_OK) return i2cHandleHardwareFailure(device); @@ -182,87 +206,72 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t void i2cInit(I2CDevice device) { - /*## Configure the I2C clock source. The clock is derived from the SYSCLK #*/ -// RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct; -// RCC_PeriphCLKInitStruct.PeriphClockSelection = i2cHardwareMap[device].clk; -// RCC_PeriphCLKInitStruct.I2c1ClockSelection = i2cHardwareMap[device].clk_src; -// HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct); - - switch (device) { - case I2CDEV_1: - __HAL_RCC_I2C1_CLK_ENABLE(); - break; - case I2CDEV_2: - __HAL_RCC_I2C2_CLK_ENABLE(); - break; - case I2CDEV_3: - __HAL_RCC_I2C3_CLK_ENABLE(); - break; -#ifdef USE_I2C_DEVICE_4 - case I2CDEV_4: - __HAL_RCC_I2C4_CLK_ENABLE(); - break; -#endif - default: - break; + if (device == I2CINVALID) { + return; } - if (device == I2CINVALID) - return; - i2cDevice_t *i2c; - i2c = &(i2cHardwareMap[device]); + i2cDevice_t *pDev = &i2cDevice[device]; - //I2C_InitTypeDef i2cInit; + const i2cHardware_t *hardware = pDev->hardware; - IO_t scl = IOGetByTag(i2c->scl); - IO_t sda = IOGetByTag(i2c->sda); + if (!hardware) { + return; + } - IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device)); - IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device)); + IO_t scl = pDev->scl; + IO_t sda = pDev->sda; - // Enable RCC - RCC_ClockCmd(i2c->rcc, ENABLE); + IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device)); + IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device)); + // Enable RCC + RCC_ClockCmd(hardware->rcc, ENABLE); - i2cUnstick(scl, sda); + i2cUnstick(scl, sda); + + // Init pins +#ifdef STM32F7 + IOConfigGPIOAF(scl, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF4_I2C); + IOConfigGPIOAF(sda, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF4_I2C); +#else + IOConfigGPIO(scl, IOCFG_AF_OD); + IOConfigGPIO(sda, IOCFG_AF_OD); +#endif - // Init pins - #ifdef STM32F7 - IOConfigGPIOAF(scl, IOCFG_I2C, i2c->af); - IOConfigGPIOAF(sda, IOCFG_I2C, i2c->af); - #else - IOConfigGPIO(scl, IOCFG_AF_OD); - IOConfigGPIO(sda, IOCFG_AF_OD); - #endif // Init I2C peripheral - i2cHandle[device].Handle.Instance = i2cHardwareMap[device].dev; + I2C_HandleTypeDef *pHandle = &pDev->handle; + + memset(pHandle, 0, sizeof(*pHandle)); + + pHandle->Instance = pDev->hardware->reg; + /// TODO: HAL check if I2C timing is correct - if (i2c->overClock) { + if (pDev->overClock) { // 800khz Maximum speed tested on various boards without issues - i2cHandle[device].Handle.Init.Timing = 0x00500D1D; + pHandle->Init.Timing = 0x00500D1D; } else { - //i2cHandle[device].Handle.Init.Timing = 0x00500B6A; - i2cHandle[device].Handle.Init.Timing = 0x00500C6F; + pHandle->Init.Timing = 0x00500C6F; } - //i2cHandle[device].Handle.Init.Timing = 0x00D00E28; /* (Rise time = 120ns, Fall time = 25ns) */ - i2cHandle[device].Handle.Init.OwnAddress1 = 0x0; - i2cHandle[device].Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - i2cHandle[device].Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - i2cHandle[device].Handle.Init.OwnAddress2 = 0x0; - i2cHandle[device].Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - i2cHandle[device].Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + pHandle->Init.OwnAddress1 = 0x0; + pHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + pHandle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + pHandle->Init.OwnAddress2 = 0x0; + pHandle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + pHandle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - HAL_I2C_Init(&i2cHandle[device].Handle); - /* Enable the Analog I2C Filter */ - HAL_I2CEx_ConfigAnalogFilter(&i2cHandle[device].Handle,I2C_ANALOGFILTER_ENABLE); + HAL_I2C_Init(pHandle); - HAL_NVIC_SetPriority(i2cHardwareMap[device].er_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_ER)); - HAL_NVIC_EnableIRQ(i2cHardwareMap[device].er_irq); - HAL_NVIC_SetPriority(i2cHardwareMap[device].ev_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_EV), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_EV)); - HAL_NVIC_EnableIRQ(i2cHardwareMap[device].ev_irq); + // Enable the Analog I2C Filter + HAL_I2CEx_ConfigAnalogFilter(pHandle, I2C_ANALOGFILTER_ENABLE); + + // Setup interrupt handlers + HAL_NVIC_SetPriority(hardware->er_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_ER)); + HAL_NVIC_EnableIRQ(hardware->er_irq); + HAL_NVIC_SetPriority(hardware->ev_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_EV), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_EV)); + HAL_NVIC_EnableIRQ(hardware->ev_irq); } uint16_t i2cGetErrorCounter(void) diff --git a/src/main/drivers/bus_i2c_impl.h b/src/main/drivers/bus_i2c_impl.h new file mode 100644 index 000000000..839584593 --- /dev/null +++ b/src/main/drivers/bus_i2c_impl.h @@ -0,0 +1,76 @@ +/* + * 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 "platform.h" + +#include "drivers/io_types.h" +#include "drivers/rcc_types.h" + +#define I2C_SHORT_TIMEOUT ((uint32_t)0x1000) +#define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT)) +#define I2C_DEFAULT_TIMEOUT I2C_SHORT_TIMEOUT + +#define I2C_PIN_SEL_MAX 3 + +typedef struct i2cHardware_s { + I2CDevice device; + I2C_TypeDef *reg; + ioTag_t sclPins[I2C_PIN_SEL_MAX]; + ioTag_t sdaPins[I2C_PIN_SEL_MAX]; + rccPeriphTag_t rcc; +#if !defined(STM32F303xC) + uint8_t ev_irq; + uint8_t er_irq; +#endif +} i2cHardware_t; + +extern const i2cHardware_t i2cHardware[]; + +#if defined(STM32F1) || defined(STM32F4) +typedef struct i2cState_s { + volatile bool error; + volatile bool busy; + volatile uint8_t addr; + volatile uint8_t reg; + volatile uint8_t bytes; + volatile uint8_t writing; + volatile uint8_t reading; + volatile uint8_t* write_p; + volatile uint8_t* read_p; +} i2cState_t; +#endif + +typedef struct i2cDevice_s { + const i2cHardware_t *hardware; + I2C_TypeDef *reg; + IO_t scl; + IO_t sda; + bool overClock; + bool pullUp; + + // MCU/Driver dependent member follows +#if defined(STM32F1) || defined(STM32F4) + i2cState_t state; +#endif +#ifdef USE_HAL_DRIVER + I2C_HandleTypeDef handle; +#endif +} i2cDevice_t; + +extern i2cDevice_t i2cDevice[]; diff --git a/src/main/drivers/bus_i2c_stm32f10x.c b/src/main/drivers/bus_i2c_stm32f10x.c index 7cd909d54..026864239 100644 --- a/src/main/drivers/bus_i2c_stm32f10x.c +++ b/src/main/drivers/bus_i2c_stm32f10x.c @@ -18,18 +18,19 @@ #include #include #include +#include #include #include "drivers/io.h" #include "drivers/time.h" +#include "drivers/nvic.h" +#include "drivers/rcc.h" #include "drivers/bus_i2c.h" -#include "drivers/nvic.h" -#include "io_impl.h" -#include "rcc.h" +#include "drivers/bus_i2c_impl.h" -#ifndef SOFT_I2C +#if defined(USE_I2C) && !defined(SOFT_I2C) #define CLOCKSPEED 800000 // i2c clockspeed 400kHz default (conform specs), 800kHz and 1200kHz (Betaflight default) @@ -40,65 +41,52 @@ static void i2cUnstick(IO_t scl, IO_t sda); #define GPIO_AF_I2C GPIO_AF_I2C1 #ifdef STM32F4 - -#if defined(USE_I2C_PULLUP) -#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_UP) -#else -#define IOCFG_I2C IOCFG_AF_OD -#endif - -#ifndef I2C1_SCL -#define I2C1_SCL PB8 -#endif -#ifndef I2C1_SDA -#define I2C1_SDA PB9 -#endif - -#else - -#ifndef I2C1_SCL -#define I2C1_SCL PB6 -#endif -#ifndef I2C1_SDA -#define I2C1_SDA PB7 -#endif +#define IOCFG_I2C_PU IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_UP) +#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL) +#else // STM32F4 #define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF_OD, GPIO_Speed_50MHz) - #endif -#ifndef I2C2_SCL -#define I2C2_SCL PB10 +const i2cHardware_t i2cHardware[I2CDEV_COUNT] = { +#ifdef USE_I2C_DEVICE_1 + { + .device = I2CDEV_1, + .reg = I2C1, + .sclPins = { DEFIO_TAG_E(PB6), DEFIO_TAG_E(PB8) }, + .sdaPins = { DEFIO_TAG_E(PB7), DEFIO_TAG_E(PB9) }, + .rcc = RCC_APB1(I2C1), + .ev_irq = I2C1_EV_IRQn, + .er_irq = I2C1_ER_IRQn, + }, #endif - -#ifndef I2C2_SDA -#define I2C2_SDA PB11 +#ifdef USE_I2C_DEVICE_2 + { + .device = I2CDEV_2, + .reg = I2C2, + .sclPins = { DEFIO_TAG_E(PB10), DEFIO_TAG_E(PF1) }, + .sdaPins = { DEFIO_TAG_E(PB11), DEFIO_TAG_E(PF0) }, + .rcc = RCC_APB1(I2C2), + .ev_irq = I2C2_EV_IRQn, + .er_irq = I2C2_ER_IRQn, + }, #endif - -#ifdef STM32F4 -#ifndef I2C3_SCL -#define I2C3_SCL PA8 -#endif -#ifndef I2C3_SDA -#define I2C3_SDA PC9 -#endif -#endif - -static i2cDevice_t i2cHardwareMap[] = { - { .dev = I2C1, .scl = IO_TAG(I2C1_SCL), .sda = IO_TAG(I2C1_SDA), .rcc = RCC_APB1(I2C1), .overClock = I2C1_OVERCLOCK, .ev_irq = I2C1_EV_IRQn, .er_irq = I2C1_ER_IRQn }, - { .dev = I2C2, .scl = IO_TAG(I2C2_SCL), .sda = IO_TAG(I2C2_SDA), .rcc = RCC_APB1(I2C2), .overClock = I2C2_OVERCLOCK, .ev_irq = I2C2_EV_IRQn, .er_irq = I2C2_ER_IRQn }, -#ifdef STM32F4 - { .dev = I2C3, .scl = IO_TAG(I2C3_SCL), .sda = IO_TAG(I2C3_SDA), .rcc = RCC_APB1(I2C3), .overClock = I2C2_OVERCLOCK, .ev_irq = I2C3_EV_IRQn, .er_irq = I2C3_ER_IRQn } +#ifdef USE_I2C_DEVICE_3 + { + .device = I2CDEV_3, + .reg = I2C3, + .sclPins = { DEFIO_TAG_E(PA8) }, + .sdaPins = { DEFIO_TAG_E(PC9) }, + .rcc = RCC_APB1(I2C3), + .ev_irq = I2C3_EV_IRQn, + .er_irq = I2C3_ER_IRQn, + }, #endif }; +i2cDevice_t i2cDevice[I2CDEV_COUNT]; + static volatile uint16_t i2cErrorCount = 0; -static i2cState_t i2cState[] = { - { false, false, 0, 0, 0, 0, 0, 0, 0 }, - { false, false, 0, 0, 0, 0, 0, 0, 0 }, - { false, false, 0, 0, 0, 0, 0, 0, 0 } -}; - void I2C1_ER_IRQHandler(void) { i2c_er_handler(I2CDEV_1); } @@ -135,18 +123,19 @@ static bool i2cHandleHardwareFailure(I2CDevice device) bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, uint8_t *data) { - - if (device == I2CINVALID) + if (device == I2CINVALID || device > I2CDEV_COUNT) { return false; + } + I2C_TypeDef *I2Cx = i2cDevice[device].reg; + + if (!I2Cx) { + return false; + } + + i2cState_t *state = &i2cDevice[device].state; uint32_t timeout = I2C_DEFAULT_TIMEOUT; - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; - - i2cState_t *state; - state = &(i2cState[device]); - state->addr = addr_ << 1; state->reg = reg_; state->writing = 1; @@ -182,17 +171,19 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t data) bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf) { - if (device == I2CINVALID) + if (device == I2CINVALID || device > I2CDEV_COUNT) { return false; + } + I2C_TypeDef *I2Cx = i2cDevice[device].reg; + + if (!I2Cx) { + return false; + } + + i2cState_t *state = &i2cDevice[device].state; uint32_t timeout = I2C_DEFAULT_TIMEOUT; - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; - - i2cState_t *state; - state = &(i2cState[device]); - state->addr = addr_ << 1; state->reg = reg_; state->writing = 0; @@ -223,11 +214,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t static void i2c_er_handler(I2CDevice device) { - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; + I2C_TypeDef *I2Cx = i2cDevice[device].hardware->reg; - i2cState_t *state; - state = &(i2cState[device]); + i2cState_t *state = &i2cDevice[device].state; // Read the I2C1 status register volatile uint32_t SR1Register = I2Cx->SR1; @@ -258,11 +247,9 @@ static void i2c_er_handler(I2CDevice device) { void i2c_ev_handler(I2CDevice device) { - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; + I2C_TypeDef *I2Cx = i2cDevice[device].hardware->reg; - i2cState_t *state; - state = &(i2cState[device]); + i2cState_t *state = &i2cDevice[device].state; static uint8_t subaddress_sent, final_stop; // flag to indicate if subaddess sent, flag to indicate final bus condition static int8_t index; // index is signed -1 == send the subaddress @@ -378,65 +365,72 @@ void i2cInit(I2CDevice device) if (device == I2CINVALID) return; - i2cDevice_t *i2c; - i2c = &(i2cHardwareMap[device]); + i2cDevice_t *pDev = &i2cDevice[device]; + const i2cHardware_t *hw = pDev->hardware; + + if (!hw) { + return; + } + + I2C_TypeDef *I2Cx = hw->reg; + + memset(&pDev->state, 0, sizeof(pDev->state)); NVIC_InitTypeDef nvic; I2C_InitTypeDef i2cInit; - IO_t scl = IOGetByTag(i2c->scl); - IO_t sda = IOGetByTag(i2c->sda); + IO_t scl = pDev->scl; + IO_t sda = pDev->sda; IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device)); IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device)); // Enable RCC - RCC_ClockCmd(i2c->rcc, ENABLE); + RCC_ClockCmd(hw->rcc, ENABLE); - I2C_ITConfig(i2c->dev, I2C_IT_EVT | I2C_IT_ERR, DISABLE); + I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); i2cUnstick(scl, sda); // Init pins #ifdef STM32F4 - IOConfigGPIOAF(scl, IOCFG_I2C, GPIO_AF_I2C); - IOConfigGPIOAF(sda, IOCFG_I2C, GPIO_AF_I2C); + IOConfigGPIOAF(scl, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF_I2C); + IOConfigGPIOAF(sda, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF_I2C); #else IOConfigGPIO(scl, IOCFG_I2C); IOConfigGPIO(sda, IOCFG_I2C); #endif - I2C_DeInit(i2c->dev); + I2C_DeInit(I2Cx); I2C_StructInit(&i2cInit); - I2C_ITConfig(i2c->dev, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts - they are enabled by the first request + I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts - they are enabled by the first request i2cInit.I2C_Mode = I2C_Mode_I2C; i2cInit.I2C_DutyCycle = I2C_DutyCycle_2; i2cInit.I2C_OwnAddress1 = 0; i2cInit.I2C_Ack = I2C_Ack_Enable; i2cInit.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; - if (i2c->overClock) { + if (pDev->overClock) { i2cInit.I2C_ClockSpeed = 800000; // 800khz Maximum speed tested on various boards without issues } else { i2cInit.I2C_ClockSpeed = 400000; // 400khz Operation according specs } - I2C_Cmd(i2c->dev, ENABLE); - I2C_Init(i2c->dev, &i2cInit); - - I2C_StretchClockCmd(i2c->dev, ENABLE); + I2C_Cmd(I2Cx, ENABLE); + I2C_Init(I2Cx, &i2cInit); + I2C_StretchClockCmd(I2Cx, ENABLE); // I2C ER Interrupt - nvic.NVIC_IRQChannel = i2c->er_irq; + nvic.NVIC_IRQChannel = hw->er_irq; nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER); nvic.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_ER); nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); // I2C EV Interrupt - nvic.NVIC_IRQChannel = i2c->ev_irq; + nvic.NVIC_IRQChannel = hw->ev_irq; nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_EV); nvic.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_EV); NVIC_Init(&nvic); diff --git a/src/main/drivers/bus_i2c_stm32f30x.c b/src/main/drivers/bus_i2c_stm32f30x.c index 3869c179a..d1c5c9758 100644 --- a/src/main/drivers/bus_i2c_stm32f30x.c +++ b/src/main/drivers/bus_i2c_stm32f30x.c @@ -17,54 +17,57 @@ #include #include +#include #include +#include "build/debug.h" + #include "drivers/system.h" #include "drivers/io.h" -#include "io_impl.h" -#include "rcc.h" +#include "drivers/io_impl.h" +#include "drivers/rcc.h" #include "drivers/bus_i2c.h" +#include "drivers/bus_i2c_impl.h" -#ifndef SOFT_I2C +#if defined(USE_I2C) && !defined(SOFT_I2C) -#if defined(USE_I2C_PULLUP) -#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_UP) -#else -#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL) -#endif +#define IOCFG_I2C_PU IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_UP) +#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL) #define I2C_HIGHSPEED_TIMING 0x00500E30 // 1000 Khz, 72Mhz Clock, Analog Filter Delay ON, Setup 40, Hold 4. #define I2C_STANDARD_TIMING 0x00E0257A // 400 Khz, 72Mhz Clock, Analog Filter Delay ON, Rise 100, Fall 10. -#define I2C_SHORT_TIMEOUT ((uint32_t)0x1000) -#define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT)) #define I2C_GPIO_AF GPIO_AF_4 -#ifndef I2C1_SCL -#define I2C1_SCL PB6 -#endif -#ifndef I2C1_SDA -#define I2C1_SDA PB7 -#endif -#ifndef I2C2_SCL -#define I2C2_SCL PF4 -#endif -#ifndef I2C2_SDA -#define I2C2_SDA PA10 -#endif - static uint32_t i2cTimeout; static volatile uint16_t i2cErrorCount = 0; -//static volatile uint16_t i2c2ErrorCount = 0; -static i2cDevice_t i2cHardwareMap[] = { - { .dev = I2C1, .scl = IO_TAG(I2C1_SCL), .sda = IO_TAG(I2C1_SDA), .rcc = RCC_APB1(I2C1), .overClock = I2C1_OVERCLOCK }, - { .dev = I2C2, .scl = IO_TAG(I2C2_SCL), .sda = IO_TAG(I2C2_SDA), .rcc = RCC_APB1(I2C2), .overClock = I2C2_OVERCLOCK } +const i2cHardware_t i2cHardware[I2CDEV_COUNT] = { +#ifdef USE_I2C_DEVICE_1 + { + .device = I2CDEV_1, + .reg = I2C1, + .sclPins = { DEFIO_TAG_E(PA15), DEFIO_TAG_E(PB6), DEFIO_TAG_E(PB8) }, + .sdaPins = { DEFIO_TAG_E(PA14), DEFIO_TAG_E(PB7), DEFIO_TAG_E(PB9) }, + .rcc = RCC_APB1(I2C1), + }, +#endif +#ifdef USE_I2C_DEVICE_2 + { + .device = I2CDEV_2, + .reg = I2C2, + .sclPins = { DEFIO_TAG_E(PA9), DEFIO_TAG_E(PF6) }, + .sdaPins = { DEFIO_TAG_E(PA10) }, + .rcc = RCC_APB1(I2C2), + }, +#endif }; +i2cDevice_t i2cDevice[I2CDEV_COUNT]; + /////////////////////////////////////////////////////////////////////////////// // I2C TimeoutUserCallback /////////////////////////////////////////////////////////////////////////////// @@ -77,24 +80,30 @@ uint32_t i2cTimeoutUserCallback(void) void i2cInit(I2CDevice device) { + if (device == I2CINVALID || device > I2CDEV_COUNT) { + return; + } - i2cDevice_t *i2c; - i2c = &(i2cHardwareMap[device]); + i2cDevice_t *pDev = &i2cDevice[device]; + const i2cHardware_t *hw = pDev->hardware; - I2C_TypeDef *I2Cx; - I2Cx = i2c->dev; + if (!hw) { + return; + } - IO_t scl = IOGetByTag(i2c->scl); - IO_t sda = IOGetByTag(i2c->sda); + I2C_TypeDef *I2Cx = pDev->reg; - RCC_ClockCmd(i2c->rcc, ENABLE); + IO_t scl = pDev->scl; + IO_t sda = pDev->sda; + + RCC_ClockCmd(hw->rcc, ENABLE); RCC_I2CCLKConfig(I2Cx == I2C2 ? RCC_I2C2CLK_SYSCLK : RCC_I2C1CLK_SYSCLK); IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device)); - IOConfigGPIOAF(scl, IOCFG_I2C, GPIO_AF_4); + IOConfigGPIOAF(scl, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF_4); IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device)); - IOConfigGPIOAF(sda, IOCFG_I2C, GPIO_AF_4); + IOConfigGPIOAF(sda, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, GPIO_AF_4); I2C_InitTypeDef i2cInit = { .I2C_Mode = I2C_Mode_I2C, @@ -103,7 +112,7 @@ void i2cInit(I2CDevice device) .I2C_OwnAddress1 = 0x00, .I2C_Ack = I2C_Ack_Enable, .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_Timing = (i2c->overClock ? I2C_HIGHSPEED_TIMING : I2C_STANDARD_TIMING) + .I2C_Timing = (pDev->overClock ? I2C_HIGHSPEED_TIMING : I2C_STANDARD_TIMING) }; I2C_Init(I2Cx, &i2cInit); @@ -120,10 +129,17 @@ uint16_t i2cGetErrorCounter(void) bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data) { - addr_ <<= 1; + if (device == I2CINVALID || device > I2CDEV_COUNT) { + return false; + } - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; + I2C_TypeDef *I2Cx = i2cDevice[device].reg; + + if (!I2Cx) { + return false; + } + + addr_ <<= 1; /* Test on BUSY Flag */ i2cTimeout = I2C_LONG_TIMEOUT; @@ -186,10 +202,17 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data) bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf) { - addr_ <<= 1; + if (device == I2CINVALID || device > I2CDEV_COUNT) { + return false; + } - I2C_TypeDef *I2Cx; - I2Cx = i2cHardwareMap[device].dev; + I2C_TypeDef *I2Cx = i2cDevice[device].reg; + + if (!I2Cx) { + return false; + } + + addr_ <<= 1; /* Test on BUSY Flag */ i2cTimeout = I2C_LONG_TIMEOUT; diff --git a/src/main/drivers/display_ug2864hsweg01.c b/src/main/drivers/display_ug2864hsweg01.c index 9c14f1562..b9ac8528e 100644 --- a/src/main/drivers/display_ug2864hsweg01.c +++ b/src/main/drivers/display_ug2864hsweg01.c @@ -24,6 +24,8 @@ #include "display_ug2864hsweg01.h" +#ifdef USE_I2C_OLED_DISPLAY + #if !defined(OLED_I2C_INSTANCE) #if defined(I2C_DEVICE) #define OLED_I2C_INSTANCE I2C_DEVICE @@ -288,3 +290,4 @@ bool ug2864hsweg01InitI2C(void) return true; } +#endif // USE_I2C_OLED_DISPLAY diff --git a/src/main/fc/cli.c b/src/main/fc/cli.c index 4cadd6090..b75c7a56c 100755 --- a/src/main/fc/cli.c +++ b/src/main/fc/cli.c @@ -2749,6 +2749,10 @@ const cliResourceValue_t resourceTable[] = { #ifdef USE_INVERTER { OWNER_INVERTER, PG_SERIAL_PIN_CONFIG, offsetof(serialPinConfig_t, ioTagInverter[0]), SERIAL_PORT_MAX_INDEX }, #endif +#ifdef USE_I2C + { OWNER_I2C_SCL, PG_I2C_CONFIG, offsetof(i2cConfig_t, ioTagScl[0]), I2CDEV_COUNT }, + { OWNER_I2C_SDA, PG_I2C_CONFIG, offsetof(i2cConfig_t, ioTagSda[0]), I2CDEV_COUNT }, +#endif }; static ioTag_t *getIoTag(const cliResourceValue_t value, uint8_t index) diff --git a/src/main/fc/config.h b/src/main/fc/config.h index 4f2ee925b..4ced00ee2 100644 --- a/src/main/fc/config.h +++ b/src/main/fc/config.h @@ -27,6 +27,7 @@ #include "drivers/rx_pwm.h" #include "drivers/sdcard.h" #include "drivers/serial.h" +#include "drivers/bus_i2c.h" #include "drivers/sound_beeper.h" #include "drivers/vcd.h" diff --git a/src/main/fc/fc_init.c b/src/main/fc/fc_init.c index d546deb37..53a72e11e 100644 --- a/src/main/fc/fc_init.c +++ b/src/main/fc/fc_init.c @@ -54,6 +54,7 @@ #include "drivers/rx_pwm.h" #include "drivers/pwm_output.h" #include "drivers/adc.h" +#include "drivers/bus.h" #include "drivers/bus_i2c.h" #include "drivers/bus_spi.h" #include "drivers/buttons.h" @@ -135,10 +136,6 @@ void targetPreInit(void); #endif -#ifdef TARGET_BUS_INIT -void targetBusInit(void); -#endif - extern uint8_t motorControlEnable; #ifdef SOFTSERIAL_LOOPBACK @@ -367,6 +364,11 @@ void init(void) #endif /* USE_SPI */ #ifdef USE_I2C + i2cHardwareConfigure(); + + // Note: Unlike UARTs which are configured when client is present, + // I2C buses are initialized unconditionally if they are configured. + #ifdef USE_I2C_DEVICE_1 i2cInit(I2CDEV_1); #endif diff --git a/src/main/osd_slave/osd_slave_init.c b/src/main/osd_slave/osd_slave_init.c index 4bdb23e62..77a305e85 100644 --- a/src/main/osd_slave/osd_slave_init.c +++ b/src/main/osd_slave/osd_slave_init.c @@ -34,6 +34,7 @@ #include "config/parameter_group_ids.h" #include "drivers/adc.h" +#include "drivers/bus.h" #include "drivers/bus_i2c.h" #include "drivers/bus_spi.h" #include "drivers/dma.h" @@ -92,10 +93,6 @@ void targetPreInit(void); #endif -#ifdef TARGET_BUS_INIT -void targetBusInit(void); -#endif - uint8_t systemState = SYSTEM_STATE_INITIALISING; void processLoopback(void) @@ -195,6 +192,11 @@ void init(void) #endif /* USE_SPI */ #ifdef USE_I2C + i2cHardwareConfigure(); + + // Note: Unlike UARTs which are configured when client is present, + // I2C buses are initialized unconditionally if they are configured. + #ifdef USE_I2C_DEVICE_1 i2cInit(I2CDEV_1); #endif diff --git a/src/main/target/ALIENFLIGHTF3/target.h b/src/main/target/ALIENFLIGHTF3/target.h index 8e1ecf53e..ef8d085ee 100644 --- a/src/main/target/ALIENFLIGHTF3/target.h +++ b/src/main/target/ALIENFLIGHTF3/target.h @@ -19,7 +19,6 @@ #define TARGET_BOARD_IDENTIFIER "AFF3" // AlienFlight F3. #define TARGET_CONFIG -#define TARGET_BUS_INIT #define REMAP_TIM17_DMA #define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT diff --git a/src/main/target/BEEROTORF4/target.h b/src/main/target/BEEROTORF4/target.h index 409bf7510..aeb813826 100644 --- a/src/main/target/BEEROTORF4/target.h +++ b/src/main/target/BEEROTORF4/target.h @@ -127,6 +127,7 @@ //#define SPI_RX_CS_PIN PD2 #define USE_I2C +#define USE_I2C_DEVICE_1 #define I2C_DEVICE (I2CDEV_1) #define I2C1_SCL PB6 #define I2C1_SDA PB7 diff --git a/src/main/target/CJMCU/initialisation.c b/src/main/target/CJMCU/initialisation.c index 884ea0335..01986ce33 100644 --- a/src/main/target/CJMCU/initialisation.c +++ b/src/main/target/CJMCU/initialisation.c @@ -19,18 +19,20 @@ #include #include "platform.h" +#include "drivers/bus.h" #include "drivers/bus_i2c.h" #include "drivers/bus_spi.h" #include "io/serial.h" void targetBusInit(void) { - #if defined(USE_SPI) && defined(USE_SPI_DEVICE_1) - spiInit(SPIDEV_1); - #endif +#if defined(USE_SPI) && defined(USE_SPI_DEVICE_1) + spiInit(SPIDEV_1); +#endif if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { serialRemovePort(SERIAL_PORT_USART3); + i2cHardwareConfigure(); i2cInit(I2C_DEVICE); } -} \ No newline at end of file +} diff --git a/src/main/target/CLRACINGF7/target.h b/src/main/target/CLRACINGF7/target.h index 7d025fd3e..b9b781f84 100644 --- a/src/main/target/CLRACINGF7/target.h +++ b/src/main/target/CLRACINGF7/target.h @@ -87,7 +87,8 @@ #define SERIAL_PORT_COUNT 5 -#define USE_I2C +// XXX To target maintainer: Bus device to configure must be specified. +//#define USE_I2C #define USE_SPI #define USE_SPI_DEVICE_1 diff --git a/src/main/target/COLIBRI_RACE/target.c b/src/main/target/COLIBRI_RACE/target.c index 2e17b07b8..12d4cdeeb 100644 --- a/src/main/target/COLIBRI_RACE/target.c +++ b/src/main/target/COLIBRI_RACE/target.c @@ -16,9 +16,11 @@ */ #include +#include #include +#include "drivers/bus_i2c.h" #include "drivers/io.h" #include "drivers/dma.h" #include "drivers/timer.h" @@ -46,10 +48,12 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { }; - +// XXX Requires some additional work here. +// XXX Can't do this now without proper semantics about I2C on this target. #ifdef USE_BST void targetBusInit(void) { + i2cHardwareConfigure(); bstInit(BST_DEVICE); } #endif diff --git a/src/main/target/FRSKYF3/config.c b/src/main/target/FRSKYF3/config.c new file mode 100644 index 000000000..1ba41e1a5 --- /dev/null +++ b/src/main/target/FRSKYF3/config.c @@ -0,0 +1,30 @@ +/* + * 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 + +#ifdef TARGET_CONFIG +#include "rx/rx.h" +#include "io/serial.h" + +void targetConfiguration(void) +{ + serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(TELEMETRY_UART)].functionMask = FUNCTION_TELEMETRY_SMARTPORT; + rxConfigMutable()->rssi_channel = 8; +} +#endif diff --git a/src/main/target/FRSKYF3/target.c b/src/main/target/FRSKYF3/target.c new file mode 100644 index 000000000..0e9830300 --- /dev/null +++ b/src/main/target/FRSKYF3/target.c @@ -0,0 +1,37 @@ +/* + * 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 "drivers/io.h" +#include "drivers/timer.h" +#include "drivers/dma.h" +#include "drivers/timer_def.h" + +const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { + DEF_TIM(TIM8, CH3, PB9, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM1 + DEF_TIM(TIM8, CH2, PB8, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM2 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM3 + DEF_TIM(TIM2, CH2, PA1, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM4 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM5 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM6 + DEF_TIM(TIM2, CH1, PA0, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM7 + DEF_TIM(TIM3, CH3, PB0, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD), // PWM8 + + DEF_TIM(TIM1, CH1, PA8, TIM_USE_LED|TIM_USE_TRANSPONDER, TIMER_OUTPUT_ENABLED), // LED +}; diff --git a/src/main/target/FRSKYF3/target.h b/src/main/target/FRSKYF3/target.h new file mode 100644 index 000000000..e3d4484e0 --- /dev/null +++ b/src/main/target/FRSKYF3/target.h @@ -0,0 +1,151 @@ +/* + * 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 + +#define TARGET_BOARD_IDENTIFIER "FRF3" +#define TARGET_CONFIG +#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_NONE + +#define LED0 PB3 +#define BEEPER PC15 +#define BEEPER_INVERTED + +#define USE_EXTI +#define MPU_INT_EXTI PC13 +#define USE_MPU_DATA_READY_SIGNAL +#define EXTI15_10_CALLBACK_HANDLER_COUNT 1 // MPU_INT, SDCardDetect +#define MPU_ADDRESS 0x69 + +#ifdef MYMPU6000 +#define MPU6000_SPI_INSTANCE SPI2 +#define MPU6000_CS_PIN PB12 +#define GYRO +#define USE_GYRO_SPI_MPU6000 +#define GYRO_MPU6000_ALIGN CW270_DEG + +#define ACC +#define USE_ACC_SPI_MPU6000 +#define ACC_MPU6000_ALIGN CW270_DEG +#else +#define GYRO +#define USE_GYRO_MPU6050 +#define GYRO_MPU6050_ALIGN CW270_DEG + +#define ACC +#define USE_ACC_MPU6050 +#define ACC_MPU6050_ALIGN CW270_DEG +#endif + +#define USE_VCP +#define USE_UART1 +#define USE_UART2 +#define USE_UART3 +#define USE_SOFTSERIAL1 +#define USE_SOFTSERIAL2 + +#define SERIAL_PORT_COUNT 6 +#define UART1_TX_PIN PA9 +#define UART1_RX_PIN PA10 + +#define UART2_TX_PIN PA14 +#define UART2_RX_PIN PA15 + +#define UART3_TX_PIN PB10 +#define UART3_RX_PIN PB11 + +#define USE_I2C +#define USE_I2C_DEVICE_1 +#define I2C_DEVICE (I2CDEV_1) +#define I2C1_SCL PB6 +#define I2C1_SDA PB7 + + +#define USE_ESCSERIAL +#define ESCSERIAL_TIMER_TX_HARDWARE 0 +#define USE_SPI +#define OSD + +// include the max7456 driver +#define USE_MAX7456 +#define MAX7456_SPI_INSTANCE SPI2 +#define MAX7456_SPI_CS_PIN PB4 +#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD*2) +#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) + +#define USE_SPI +#define USE_SPI_DEVICE_2 +#define USE_SPI_DEVICE_1 + +#define SPI2_NSS_PIN PB12 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 + +#define SPI1_NSS_PIN PC14 +#define SPI1_SCK_PIN PA5 +#define SPI1_MISO_PIN PA6 +#define SPI1_MOSI_PIN PA7 + +#define USE_SDCARD +#define USE_SDCARD_SPI1 + +#define SDCARD_DETECT_INVERTED + +#define SDCARD_DETECT_PIN PB5 +#define SDCARD_SPI_INSTANCE SPI1 +#define SDCARD_SPI_CS_PIN SPI1_NSS_PIN + +#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 256 +#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 4 + +#define USE_ESC_SENSOR + +#define DEFAULT_VOLTAGE_METER_SOURCE VOLTAGE_METER_ADC +#define DEFAULT_CURRENT_METER_SOURCE CURRENT_METER_NONE + +#define USE_ADC +#define VBAT_ADC_PIN PA4 +#define CURRENT_METER_ADC_PIN PB2 +#define ADC_INSTANCE ADC2 +#define ADC24_DMA_REMAP + +#define TRANSPONDER +#define REDUCE_TRANSPONDER_CURRENT_DRAW_WHEN_USB_CABLE_PRESENT + +#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT + +#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL +#define SERIALRX_PROVIDER SERIALRX_SBUS + +#define DEFAULT_FEATURES ( FEATURE_TELEMETRY | FEATURE_LED_STRIP | FEATURE_OSD) +#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL +#define SERIALRX_PROVIDER SERIALRX_SBUS +#define TELEMETRY_UART SERIAL_PORT_USART3 +#define SERIALRX_UART SERIAL_PORT_USART2 + +#define SPEKTRUM_BIND_PIN UART3_RX_PIN + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +#define TARGET_IO_PORTA 0xffff +#define TARGET_IO_PORTB 0xffff +#define TARGET_IO_PORTC (BIT(13)|BIT(14)|BIT(15)) +#define TARGET_IO_PORTF (BIT(0)|BIT(1)|BIT(4)) + +#define USABLE_TIMER_CHANNEL_COUNT 9 +#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(8) | TIM_N(17)) diff --git a/src/main/target/FRSKYF3/target.mk b/src/main/target/FRSKYF3/target.mk new file mode 100644 index 000000000..f6cc48327 --- /dev/null +++ b/src/main/target/FRSKYF3/target.mk @@ -0,0 +1,13 @@ +F3_TARGETS += $(TARGET) +FEATURES = VCP SDCARD + +TARGET_SRC = \ + drivers/accgyro/accgyro_mpu.c \ + drivers/accgyro/accgyro_spi_mpu6000.c \ + drivers/barometer/barometer_bmp280.c \ + drivers/barometer/barometer_spi_bmp280.c \ + drivers/compass/compass_ak8963.c \ + drivers/compass/compass_ak8975.c \ + drivers/compass/compass_hmc5883l.c \ + drivers/accgyro/accgyro_mpu6050.c \ + drivers/max7456.c diff --git a/src/main/target/FRSKYF4/config.c b/src/main/target/FRSKYF4/config.c new file mode 100644 index 000000000..1ba41e1a5 --- /dev/null +++ b/src/main/target/FRSKYF4/config.c @@ -0,0 +1,30 @@ +/* + * 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 + +#ifdef TARGET_CONFIG +#include "rx/rx.h" +#include "io/serial.h" + +void targetConfiguration(void) +{ + serialConfigMutable()->portConfigs[findSerialPortIndexByIdentifier(TELEMETRY_UART)].functionMask = FUNCTION_TELEMETRY_SMARTPORT; + rxConfigMutable()->rssi_channel = 8; +} +#endif diff --git a/src/main/target/FRSKYF4/target.c b/src/main/target/FRSKYF4/target.c new file mode 100644 index 000000000..64f97511d --- /dev/null +++ b/src/main/target/FRSKYF4/target.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 "drivers/io.h" + +#include "drivers/dma.h" +#include "drivers/timer.h" +#include "drivers/timer_def.h" + +const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { + DEF_TIM(TIM4, CH3, PB8, TIM_USE_PWM | TIM_USE_PPM, TIMER_OUTPUT_NONE, 0), // PPM + DEF_TIM(TIM4, CH4, PB9, TIM_USE_PWM, TIMER_OUTPUT_NONE, 0), // S2_IN + DEF_TIM(TIM8, CH1, PC6, TIM_USE_PWM, TIMER_OUTPUT_NONE, 0), // S3_IN, UART6_TX + DEF_TIM(TIM8, CH2, PC7, TIM_USE_PWM, TIMER_OUTPUT_NONE, 0), // S4_IN, UART6_RX + DEF_TIM(TIM8, CH3, PC8, TIM_USE_PWM, TIMER_OUTPUT_NONE, 0), // S5_IN + DEF_TIM(TIM8, CH4, PC9, TIM_USE_PWM, TIMER_OUTPUT_NONE, 0), // S6_IN + + DEF_TIM(TIM3, CH3, PB0, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 0), // S1_OUT D1_ST7 + DEF_TIM(TIM3, CH4, PB1, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 0), // S2_OUT D1_ST2 + DEF_TIM(TIM2, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 1), // S3_OUT D1_ST6 + DEF_TIM(TIM2, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 0), // S4_OUT D1_ST1 + + DEF_TIM(TIM5, CH2, PA1, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 0), // S5_OUT + DEF_TIM(TIM1, CH1, PA8, TIM_USE_MOTOR, TIMER_OUTPUT_STANDARD, 0), // S6_OUT + DEF_TIM(TIM4, CH1, PB6, TIM_USE_LED, TIMER_OUTPUT_STANDARD, 0), // LED strip for F4 V2 / F4-Pro-0X and later (RCD_CS for F4) +}; diff --git a/src/main/target/FRSKYF4/target.h b/src/main/target/FRSKYF4/target.h new file mode 100644 index 000000000..f715d723d --- /dev/null +++ b/src/main/target/FRSKYF4/target.h @@ -0,0 +1,140 @@ +/* + * This 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. + * + * This software 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 software. If not, see . + */ + +#pragma once + +#define TARGET_BOARD_IDENTIFIER "FRF4" +#define USBD_PRODUCT_STRING "FRSKYF4" +#define TARGET_CONFIG + +#define LED0 PB5 +#define BEEPER PB4 +#define BEEPER_INVERTED + +#define INVERTER_PIN_UART6 PC8 + +#define MPU6000_CS_PIN PA4 +#define MPU6000_SPI_INSTANCE SPI1 + +#define ACC +#define USE_ACC_SPI_MPU6000 + +#define GYRO +#define USE_GYRO_SPI_MPU6000 + +#define GYRO_MPU6000_ALIGN CW270_DEG +#define ACC_MPU6000_ALIGN CW270_DEG + +#define USE_EXTI +#define MPU_INT_EXTI PC4 +#define USE_MPU_DATA_READY_SIGNAL + +//#define MAG +//#define USE_MAG_HMC5883 +//#define MAG_HMC5883_ALIGN CW90_DEG + +#define BARO +//#define USE_BARO_MS5611 + +#define USE_BARO_BMP280 +#define USE_BARO_SPI_BMP280 +#define BMP280_SPI_INSTANCE SPI3 +#define BMP280_CS_PIN PB3 + +#define OSD +#define USE_MAX7456 +#define MAX7456_SPI_INSTANCE SPI3 +#define MAX7456_SPI_CS_PIN PA15 +#define MAX7456_SPI_CLK (SPI_CLOCK_STANDARD*2) +#define MAX7456_RESTORE_CLK (SPI_CLOCK_FAST) + +#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT +#define USE_SDCARD +#define USE_SDCARD_SPI2 + +#define SDCARD_DETECT_INVERTED + +#define SDCARD_DETECT_PIN PB7 +#define SDCARD_SPI_INSTANCE SPI2 +#define SDCARD_SPI_CS_PIN SPI2_NSS_PIN +#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 256 // 328kHz +#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 4 // 21MHz + +#define SDCARD_DMA_CHANNEL_TX DMA1_Stream4 +#define SDCARD_DMA_CHANNEL_TX_COMPLETE_FLAG DMA_FLAG_TCIF4 +#define SDCARD_DMA_CLK RCC_AHB1Periph_DMA1 +#define SDCARD_DMA_CHANNEL DMA_Channel_0 + +#define USE_VCP +#define VBUS_SENSING_PIN PC5 + +#define USE_UART1 +#define UART1_RX_PIN PA10 +#define UART1_TX_PIN PA9 +#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 + +#define USE_UART3 +#define UART3_RX_PIN PB11 +#define UART3_TX_PIN PB10 + +#define USE_UART6 +#define UART6_RX_PIN PC7 +#define UART6_TX_PIN PC6 + +#define USE_SOFTSERIAL1 +#define USE_SOFTSERIAL2 + +#define SERIAL_PORT_COUNT 6 + +#define USE_ESCSERIAL +#define ESCSERIAL_TIMER_TX_HARDWARE 0 + +#define USE_SPI +#define USE_SPI_DEVICE_1 + +#define USE_SPI_DEVICE_2 +#define SPI2_NSS_PIN PB12 +#define SPI2_SCK_PIN PB13 +#define SPI2_MISO_PIN PB14 +#define SPI2_MOSI_PIN PB15 + +#define USE_SPI_DEVICE_3 +#define SPI3_NSS_PIN PA15 +#define SPI3_SCK_PIN PC10 +#define SPI3_MISO_PIN PC11 +#define SPI3_MOSI_PIN PC12 + +#define USE_ADC +#define CURRENT_METER_ADC_PIN PC1 +#define VBAT_ADC_PIN PC2 + +#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL +#define DEFAULT_FEATURES (FEATURE_OSD) +#define AVOID_UART1_FOR_PWM_PPM +#define SPEKTRUM_BIND_PIN UART1_RX_PIN + +#define SERIALRX_PROVIDER SERIALRX_SBUS +#define TELEMETRY_UART SERIAL_PORT_USART6 +#define SERIALRX_UART SERIAL_PORT_USART1 + +#define USE_SERIAL_4WAY_BLHELI_INTERFACE + +#define TARGET_IO_PORTA (0xffff & ~(BIT(14)|BIT(13))) +#define TARGET_IO_PORTB (0xffff & ~(BIT(2))) +#define TARGET_IO_PORTC (0xffff & ~(BIT(15)|BIT(14)|BIT(13))) +#define TARGET_IO_PORTD BIT(2) + +#define USABLE_TIMER_CHANNEL_COUNT 13 +#define USED_TIMERS ( TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9)) diff --git a/src/main/target/FRSKYF4/target.mk b/src/main/target/FRSKYF4/target.mk new file mode 100644 index 000000000..c156b5777 --- /dev/null +++ b/src/main/target/FRSKYF4/target.mk @@ -0,0 +1,11 @@ +F405_TARGETS += $(TARGET) + +FEATURES = VCP SDCARD + +TARGET_SRC = \ + drivers/accgyro/accgyro_spi_mpu6000.c \ + drivers/barometer/barometer_ms5611.c \ + drivers/barometer/barometer_bmp280.c \ + drivers/barometer/barometer_spi_bmp280.c \ + drivers/compass/compass_hmc5883l.c \ + drivers/max7456.c diff --git a/src/main/target/FURYF3/target.h b/src/main/target/FURYF3/target.h index a58c27a13..464d7e2cc 100644 --- a/src/main/target/FURYF3/target.h +++ b/src/main/target/FURYF3/target.h @@ -127,6 +127,7 @@ #endif #define USE_I2C +#define USE_I2C_DEVICE_1 #define I2C_DEVICE (I2CDEV_1) // SDA (PB9/AF4), SCL (PB8/AF4) #define I2C1_SCL PB8 #define I2C1_SDA PB9 diff --git a/src/main/target/KROOZX/initialisation.c b/src/main/target/KROOZX/initialisation.c index 624615f97..d6b8c009c 100755 --- a/src/main/target/KROOZX/initialisation.c +++ b/src/main/target/KROOZX/initialisation.c @@ -21,33 +21,6 @@ #include "drivers/bus_i2c.h" #include "drivers/bus_spi.h" -void targetBusInit(void) -{ -#ifdef USE_SPI - #ifdef USE_SPI_DEVICE_1 - spiInit(SPIDEV_1); - #endif - #ifdef USE_SPI_DEVICE_2 - spiInit(SPIDEV_2); - #endif - #ifdef USE_SPI_DEVICE_3 - spiInit(SPIDEV_3); - #endif - #ifdef USE_SPI_DEVICE_4 - spiInit(SPIDEV_4); - #endif -#endif - -#ifdef USE_I2C - #ifdef USE_I2C_DEVICE_1 - i2cInit(I2CDEV_1); - #endif - #ifdef USE_I2C_DEVICE_3 - i2cInit(I2CDEV_3); - #endif -#endif -} - void targetPreInit(void) { IO_t osdChSwitch = IOGetByTag(IO_TAG(OSD_CH_SWITCH)); diff --git a/src/main/target/KROOZX/target.h b/src/main/target/KROOZX/target.h index a493c79b2..8d8e4e291 100755 --- a/src/main/target/KROOZX/target.h +++ b/src/main/target/KROOZX/target.h @@ -25,7 +25,6 @@ #define USBD_PRODUCT_STRING "KroozX" #define TARGET_CONFIG -#define TARGET_BUS_INIT #define TARGET_PREINIT #define LED0 PA14 // Red LED diff --git a/src/main/target/LUMBAF3/target.h b/src/main/target/LUMBAF3/target.h index cdcf2ea74..2fcc9369f 100644 --- a/src/main/target/LUMBAF3/target.h +++ b/src/main/target/LUMBAF3/target.h @@ -88,8 +88,3 @@ #define USABLE_TIMER_CHANNEL_COUNT 8 #define USED_TIMERS ( TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(8) | TIM_N(15) ) - -#define USE_I2C -#define I2C_DEVICE (I2CDEV_2) -#define I2C2_SCL PB2 -#define I2C2_SDA PB1 diff --git a/src/main/target/NAZE/initialisation.c b/src/main/target/NAZE/initialisation.c index 0d75c2c69..6f30d3260 100644 --- a/src/main/target/NAZE/initialisation.c +++ b/src/main/target/NAZE/initialisation.c @@ -19,6 +19,7 @@ #include #include "platform.h" +#include "drivers/bus.h" #include "drivers/bus_i2c.h" #include "drivers/bus_spi.h" #include "io/serial.h" @@ -26,20 +27,22 @@ void targetBusInit(void) { - #ifdef USE_SPI - #ifdef USE_SPI_DEVICE_2 - spiInit(SPIDEV_2); - #endif - #endif +#ifdef USE_SPI +#ifdef USE_SPI_DEVICE_2 + spiInit(SPIDEV_2); +#endif +#endif if (hardwareRevision == NAZE32_SP) { serialRemovePort(SERIAL_PORT_SOFTSERIAL2); if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { serialRemovePort(SERIAL_PORT_USART3); + i2cHardwareConfigure(); i2cInit(I2C_DEVICE); } } else { + i2cHardwareConfigure(); i2cInit(I2C_DEVICE); } } diff --git a/src/main/target/OMNIBUS/target.h b/src/main/target/OMNIBUS/target.h index d7a1b5664..52d0572d2 100644 --- a/src/main/target/OMNIBUS/target.h +++ b/src/main/target/OMNIBUS/target.h @@ -78,13 +78,14 @@ #define UART2_TX_PIN PA14 // PA14 / SWCLK #define UART2_RX_PIN PA15 -#define UART3_TX_PIN PB10 // PB10 (AF7) -#define UART3_RX_PIN PB11 // PB11 (AF7) +#define UART3_TX_PIN PB10 // PB10 (PWM5) +#define UART3_RX_PIN PB11 // PB11 (PWM6) -#undef USE_I2C -//#define USE_I2C -//#define USE_I2C_DEVICE_1 -//#define I2C_DEVICE (I2CDEV_1) +#define USE_I2C +#define USE_I2C_DEVICE_1 +#define I2C1_SCL NONE // PB6 (PWM8) +#define I2C1_SDA NONE // PB7 (PWM7) +#define I2C_DEVICE (I2CDEV_1) #define USE_ESCSERIAL #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1 diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index bf8ea7bd3..a01578570 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -185,6 +185,18 @@ #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 +#define USE_I2C +#define USE_I2C_DEVICE_2 +#define I2C2_SCL NONE // PB10, shared with UART3TX +#define I2C2_SDA NONE // PB11, shared with UART3RX +#if defined(OMNIBUSF4) || defined(OMNIBUSF4SD) +#define USE_I2C_DEVICE_3 +#define I2C3_SCL NONE // PA8, PWM6 +#define I2C3_SDA NONE // PC9, CH6 +#endif +#define I2C_DEVICE (I2CDEV_2) +#define OLED_I2C_INSTANCE (I2CDEV_3) + #define USE_ADC #define CURRENT_METER_ADC_PIN PC1 #define VBAT_ADC_PIN PC2 diff --git a/src/main/target/OMNIBUSF7/target.h b/src/main/target/OMNIBUSF7/target.h index d62348e72..12fabe952 100644 --- a/src/main/target/OMNIBUSF7/target.h +++ b/src/main/target/OMNIBUSF7/target.h @@ -134,7 +134,9 @@ #define USE_I2C #define USE_I2C_DEVICE_2 -#define I2C_DEVICE (I2CDEV_2) +#define I2C_DEVICE (I2CDEV_2) +#define I2C2_SCL NONE // PB10 (UART3_TX) +#define I2C2_SDA NONE // PB11 (UART3_RX) #define BARO #define USE_BARO_BMP280 diff --git a/src/main/target/REVO/target.h b/src/main/target/REVO/target.h index 572e56134..ce07ae4d6 100644 --- a/src/main/target/REVO/target.h +++ b/src/main/target/REVO/target.h @@ -136,7 +136,7 @@ #define MPU_INT_EXTI PC4 #define USE_MPU_DATA_READY_SIGNAL -#if !defined(AIRBOTF4) && !defined(REVOLT) && !defined(SOULF4) && !defined(PODIUMF4) +#if defined(AIRBOTF4) || defined(AIRBOTF4SD) #define MAG #define USE_MAG_HMC5883 #define MAG_HMC5883_ALIGN CW90_DEG @@ -224,9 +224,17 @@ #define SPI3_MISO_PIN PC11 #define SPI3_MOSI_PIN PC12 +#if defined(AIRBOTF4) || defined(AIRBOTF4SD) +// On AIRBOTF4 and AIRBOTF4SD, I2C2 and I2C3 are configurable #define USE_I2C -#define USE_I2C_DEVICE_1 -#define I2C_DEVICE (I2CDEV_1) +#define USE_I2C_DEVICE_2 +#define I2C2_SCL NONE // PB10, shared with UART3TX +#define I2C2_SDA NONE // PB11, shared with UART3RX +#define USE_I2C_DEVICE_3 +#define I2C3_SCL NONE // PA8, PWM6 +#define I2C3_SDA NONE // PC9, CH6 +#define I2C_DEVICE (I2CDEV_2) +#endif #define USE_ADC #if !defined(PODIUMF4) diff --git a/src/main/target/SPRACINGF4EVO/target.h b/src/main/target/SPRACINGF4EVO/target.h index b404e149b..33061f23b 100644 --- a/src/main/target/SPRACINGF4EVO/target.h +++ b/src/main/target/SPRACINGF4EVO/target.h @@ -89,6 +89,7 @@ // #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1 #define USE_I2C +#define USE_I2C_DEVICE_1 #define I2C_DEVICE (I2CDEV_1) #if (SPRACINGF4EVO_REV >= 2) #define I2C1_SCL PB8 diff --git a/src/main/target/SPRACINGF4NEO/target.h b/src/main/target/SPRACINGF4NEO/target.h index 8377d59ae..4a1aac48d 100644 --- a/src/main/target/SPRACINGF4NEO/target.h +++ b/src/main/target/SPRACINGF4NEO/target.h @@ -102,6 +102,7 @@ #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1 #define USE_I2C +#define USE_I2C_DEVICE_1 #define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA #if (SPRACINGF4NEO_REV >= 3) diff --git a/src/main/target/common_fc_post.h b/src/main/target/common_fc_post.h index 8479caa24..84001a41d 100644 --- a/src/main/target/common_fc_post.h +++ b/src/main/target/common_fc_post.h @@ -28,3 +28,14 @@ #if defined(USE_QUAD_MIXER_ONLY) && defined(USE_SERVOS) #undef USE_SERVOS #endif + +// XXX Followup implicit dependencies among DASHBOARD, display_xxx and USE_I2C. +// XXX This should eventually be cleaned up. +#ifndef USE_I2C +#undef USE_I2C_OLED_DISPLAY +#undef USE_DASHBOARD +#else +#ifdef USE_DASHBOARD +#define USE_I2C_OLED_DISPLAY +#endif +#endif