diff --git a/make/mcu/STM32F1.mk b/make/mcu/STM32F1.mk index 362a893e53..f8d0f09d1e 100644 --- a/make/mcu/STM32F1.mk +++ b/make/mcu/STM32F1.mk @@ -61,6 +61,7 @@ VCP_SRC = \ MCU_COMMON_SRC = \ drivers/adc_stm32f10x.c \ drivers/bus_i2c_stm32f10x.c \ + drivers/bus_std_periph.c \ drivers/dma.c \ drivers/inverter.c \ drivers/light_ws2811strip_stdperiph.c \ diff --git a/make/mcu/STM32F3.mk b/make/mcu/STM32F3.mk index 4d1bdbe798..08fad13beb 100644 --- a/make/mcu/STM32F3.mk +++ b/make/mcu/STM32F3.mk @@ -72,6 +72,7 @@ MCU_COMMON_SRC = \ target/system_stm32f30x.c \ drivers/adc_stm32f30x.c \ drivers/bus_i2c_stm32f30x.c \ + drivers/bus_spi_stdperiph.c \ drivers/dma.c \ drivers/light_ws2811strip_stdperiph.c \ drivers/pwm_output_dshot.c \ diff --git a/make/mcu/STM32F4.mk b/make/mcu/STM32F4.mk index 7574afa63e..199152f8e9 100644 --- a/make/mcu/STM32F4.mk +++ b/make/mcu/STM32F4.mk @@ -157,6 +157,7 @@ MCU_COMMON_SRC = \ drivers/accgyro/accgyro_mpu.c \ drivers/adc_stm32f4xx.c \ drivers/bus_i2c_stm32f10x.c \ + drivers/bus_spi_stdperiph.c \ drivers/dma_stm32f4xx.c \ drivers/inverter.c \ drivers/light_ws2811strip_stdperiph.c \ diff --git a/make/mcu/STM32F7.mk b/make/mcu/STM32F7.mk index 7433e6cca9..29cb420ec0 100644 --- a/make/mcu/STM32F7.mk +++ b/make/mcu/STM32F7.mk @@ -157,7 +157,6 @@ MCU_COMMON_SRC = \ drivers/serial_uart_hal.c MCU_EXCLUDES = \ - drivers/bus_spi.c \ drivers/bus_i2c.c \ drivers/timer.c \ drivers/serial_uart.c diff --git a/src/main/drivers/bus_spi.c b/src/main/drivers/bus_spi.c index 770ab52312..c3ac21f924 100644 --- a/src/main/drivers/bus_spi.c +++ b/src/main/drivers/bus_spi.c @@ -66,69 +66,6 @@ SPI_TypeDef *spiInstanceByDevice(SPIDevice device) return spiDevice[device].dev; } -void spiInitDevice(SPIDevice device) -{ - spiDevice_t *spi = &(spiDevice[device]); - -#ifdef SDCARD_SPI_INSTANCE - if (spi->dev == SDCARD_SPI_INSTANCE) { - spi->leadingEdge = true; - } -#endif -#ifdef RX_SPI_INSTANCE - if (spi->dev == RX_SPI_INSTANCE) { - spi->leadingEdge = true; - } -#endif - - // Enable SPI clock - RCC_ClockCmd(spi->rcc, ENABLE); - RCC_ResetCmd(spi->rcc, ENABLE); - - IOInit(IOGetByTag(spi->sck), OWNER_SPI_SCK, RESOURCE_INDEX(device)); - IOInit(IOGetByTag(spi->miso), OWNER_SPI_MISO, RESOURCE_INDEX(device)); - IOInit(IOGetByTag(spi->mosi), OWNER_SPI_MOSI, RESOURCE_INDEX(device)); - -#if defined(STM32F3) || defined(STM32F4) - IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_CFG, spi->af); - IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_CFG, spi->af); - IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->af); -#endif -#if defined(STM32F10X) - IOConfigGPIO(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG); - IOConfigGPIO(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG); - IOConfigGPIO(IOGetByTag(spi->mosi), SPI_IO_AF_MOSI_CFG); -#endif - - // Init SPI hardware - SPI_I2S_DeInit(spi->dev); - - SPI_InitTypeDef spiInit; - spiInit.SPI_Mode = SPI_Mode_Master; - spiInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex; - spiInit.SPI_DataSize = SPI_DataSize_8b; - spiInit.SPI_NSS = SPI_NSS_Soft; - spiInit.SPI_FirstBit = SPI_FirstBit_MSB; - spiInit.SPI_CRCPolynomial = 7; - spiInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; - - if (spi->leadingEdge) { - spiInit.SPI_CPOL = SPI_CPOL_Low; - spiInit.SPI_CPHA = SPI_CPHA_1Edge; - } else { - spiInit.SPI_CPOL = SPI_CPOL_High; - spiInit.SPI_CPHA = SPI_CPHA_2Edge; - } - -#ifdef STM32F303xC - // Configure for 8-bit reads. - SPI_RxFIFOThresholdConfig(spi->dev, SPI_RxFIFOThreshold_QF); -#endif - - SPI_Init(spi->dev, &spiInit); - SPI_Cmd(spi->dev, ENABLE); -} - bool spiInit(SPIDevice device) { switch (device) { @@ -149,7 +86,7 @@ bool spiInit(SPIDevice device) break; #endif case SPIDEV_3: -#if defined(USE_SPI_DEVICE_3) && (defined(STM32F303xC) || defined(STM32F4)) +#if defined(USE_SPI_DEVICE_3) && !defined(STM32F1) spiInitDevice(device); return true; #else @@ -176,81 +113,6 @@ uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance) return spiDevice[device].errorCount; } -// return uint8_t value or -1 when failure -uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) -{ - uint16_t spiTimeout = 1000; - - while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) - if ((spiTimeout--) == 0) - return spiTimeoutUserCallback(instance); - -#ifdef STM32F303xC - SPI_SendData8(instance, txByte); -#else - SPI_I2S_SendData(instance, txByte); -#endif - spiTimeout = 1000; - while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) - if ((spiTimeout--) == 0) - return spiTimeoutUserCallback(instance); - -#ifdef STM32F303xC - return ((uint8_t)SPI_ReceiveData8(instance)); -#else - return ((uint8_t)SPI_I2S_ReceiveData(instance)); -#endif -} - -/** - * Return true if the bus is currently in the middle of a transmission. - */ -bool spiIsBusBusy(SPI_TypeDef *instance) -{ -#ifdef STM32F303xC - return SPI_GetTransmissionFIFOStatus(instance) != SPI_TransmissionFIFOStatus_Empty || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET; -#else - return SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET; -#endif - -} - -bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len) -{ - uint16_t spiTimeout = 1000; - - uint8_t b; - instance->DR; - while (len--) { - b = txData ? *(txData++) : 0xFF; - while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) { - if ((spiTimeout--) == 0) - return spiTimeoutUserCallback(instance); - } -#ifdef STM32F303xC - SPI_SendData8(instance, b); -#else - SPI_I2S_SendData(instance, b); -#endif - spiTimeout = 1000; - while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) { - if ((spiTimeout--) == 0) - return spiTimeoutUserCallback(instance); - } -#ifdef STM32F303xC - b = SPI_ReceiveData8(instance); -#else - b = SPI_I2S_ReceiveData(instance); -#endif - if (rxData) - *(rxData++) = b; - } - - return true; -} - -#include "build/debug.h" - bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length) { IOLo(bus->busdev_u.spi.csnPin); @@ -259,28 +121,6 @@ bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxDa return true; } -void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) -{ -#define BR_BITS ((BIT(5) | BIT(4) | BIT(3))) - -#if !(defined(STM32F1) || defined(STM32F3)) - // SPI2 and SPI3 are on APB1/AHB1 which PCLK is half that of APB2/AHB2. - - if (instance == SPI2 || instance == SPI3) { - divisor /= 2; // Safe for divisor == 0 or 1 - } -#endif - - SPI_Cmd(instance, DISABLE); - - const uint16_t tempRegister = (instance->CR1 & ~BR_BITS); - instance->CR1 = tempRegister | (divisor ? ((ffs(divisor | 0x100) - 2) << 3) : 0); - - SPI_Cmd(instance, ENABLE); - -#undef BR_BITS -} - uint16_t spiGetErrorCounter(SPI_TypeDef *instance) { SPIDevice device = spiDeviceByInstance(instance); diff --git a/src/main/drivers/bus_spi_impl.h b/src/main/drivers/bus_spi_impl.h index fe9ed35598..74c54725a6 100644 --- a/src/main/drivers/bus_spi_impl.h +++ b/src/main/drivers/bus_spi_impl.h @@ -70,3 +70,6 @@ typedef struct SPIDevice_s { } spiDevice_t; extern spiDevice_t spiDevice[SPIDEV_COUNT]; + +void spiInitDevice(SPIDevice device); +uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance); diff --git a/src/main/drivers/bus_spi_ll.c b/src/main/drivers/bus_spi_ll.c index 6e6e5b2993..b4a8ca8696 100644 --- a/src/main/drivers/bus_spi_ll.c +++ b/src/main/drivers/bus_spi_ll.c @@ -71,40 +71,6 @@ spiDevice_t spiDevice[SPIDEV_COUNT]; #define SPI_DEFAULT_TIMEOUT 10 -SPIDevice spiDeviceByInstance(SPI_TypeDef *instance) -{ -#ifdef USE_SPI_DEVICE_1 - if (instance == SPI1) - return SPIDEV_1; -#endif - -#ifdef USE_SPI_DEVICE_2 - if (instance == SPI2) - return SPIDEV_2; -#endif - -#ifdef USE_SPI_DEVICE_3 - if (instance == SPI3) - return SPIDEV_3; -#endif - -#ifdef USE_SPI_DEVICE_4 - if (instance == SPI4) - return SPIDEV_4; -#endif - - return SPIINVALID; -} - -SPI_TypeDef *spiInstanceByDevice(SPIDevice device) -{ - if (device >= SPIDEV_COUNT) { - return NULL; - } - - return spiDevice[device].dev; -} - void spiInitDevice(SPIDevice device) { spiDevice_t *spi = &(spiDevice[device]); @@ -157,53 +123,6 @@ void spiInitDevice(SPIDevice device) LL_SPI_Enable(spi->dev); } -bool spiInit(SPIDevice device) -{ - switch (device) { - case SPIINVALID: - return false; - case SPIDEV_1: -#if defined(USE_SPI_DEVICE_1) - spiInitDevice(device); - return true; -#else - break; -#endif - case SPIDEV_2: -#if defined(USE_SPI_DEVICE_2) - spiInitDevice(device); - return true; -#else - break; -#endif - case SPIDEV_3: -#if defined(USE_SPI_DEVICE_3) - spiInitDevice(device); - return true; -#else - break; -#endif - case SPIDEV_4: -#if defined(USE_SPI_DEVICE_4) - spiInitDevice(device); - return true; -#else - break; -#endif - } - return false; -} - -uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance) -{ - SPIDevice device = spiDeviceByInstance(instance); - if (device == SPIINVALID) { - return -1; - } - spiDevice[device].errorCount++; - return spiDevice[device].errorCount; -} - uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) { uint16_t spiTimeout = 1000; @@ -292,14 +211,6 @@ bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, return true; } -bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length) -{ - IOLo(bus->busdev_u.spi.csnPin); - spiTransfer(bus->busdev_u.spi.instance, txData, rxData, length); - IOHi(bus->busdev_u.spi.csnPin); - return true; -} - void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) { #if !(defined(STM32F1) || defined(STM32F3)) @@ -314,59 +225,4 @@ void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) LL_SPI_SetBaudRatePrescaler(instance, divisor ? (ffs(divisor | 0x100) - 2) << SPI_CR1_BR_Pos : 0); LL_SPI_Enable(instance); } - -uint16_t spiGetErrorCounter(SPI_TypeDef *instance) -{ - SPIDevice device = spiDeviceByInstance(instance); - if (device == SPIINVALID) { - return 0; - } - return spiDevice[device].errorCount; -} - -void spiResetErrorCounter(SPI_TypeDef *instance) -{ - SPIDevice device = spiDeviceByInstance(instance); - if (device != SPIINVALID) { - spiDevice[device].errorCount = 0; - } -} - -bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) -{ - IOLo(bus->busdev_u.spi.csnPin); - spiTransferByte(bus->busdev_u.spi.instance, reg); - spiTransferByte(bus->busdev_u.spi.instance, data); - IOHi(bus->busdev_u.spi.csnPin); - - return true; -} - -bool spiBusReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length) -{ - IOLo(bus->busdev_u.spi.csnPin); - spiTransferByte(bus->busdev_u.spi.instance, reg | 0x80); // read transaction - spiTransfer(bus->busdev_u.spi.instance, NULL, data, length); - IOHi(bus->busdev_u.spi.csnPin); - - return true; -} - -uint8_t spiBusReadRegister(const busDevice_t *bus, uint8_t reg) -{ - uint8_t data; - IOLo(bus->busdev_u.spi.csnPin); - spiTransferByte(bus->busdev_u.spi.instance, reg | 0x80); // read transaction - spiTransfer(bus->busdev_u.spi.instance, NULL, &data, 1); - IOHi(bus->busdev_u.spi.csnPin); - - return data; -} - -void spiBusSetInstance(busDevice_t *bus, SPI_TypeDef *instance) -{ - bus->bustype = BUSTYPE_SPI; - bus->busdev_u.spi.instance = instance; -} - #endif diff --git a/src/main/drivers/bus_spi_stdperiph.c b/src/main/drivers/bus_spi_stdperiph.c new file mode 100644 index 0000000000..22adb3a8a6 --- /dev/null +++ b/src/main/drivers/bus_spi_stdperiph.c @@ -0,0 +1,193 @@ +/* + * 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 + +#ifdef USE_SPI + +#include "drivers/bus.h" +#include "drivers/bus_spi.h" +#include "drivers/bus_spi_impl.h" +#include "drivers/exti.h" +#include "drivers/io.h" +#include "drivers/rcc.h" + +spiDevice_t spiDevice[SPIDEV_COUNT]; + +void spiInitDevice(SPIDevice device) +{ + spiDevice_t *spi = &(spiDevice[device]); + +#ifdef SDCARD_SPI_INSTANCE + if (spi->dev == SDCARD_SPI_INSTANCE) { + spi->leadingEdge = true; + } +#endif +#ifdef RX_SPI_INSTANCE + if (spi->dev == RX_SPI_INSTANCE) { + spi->leadingEdge = true; + } +#endif + + // Enable SPI clock + RCC_ClockCmd(spi->rcc, ENABLE); + RCC_ResetCmd(spi->rcc, ENABLE); + + IOInit(IOGetByTag(spi->sck), OWNER_SPI_SCK, RESOURCE_INDEX(device)); + IOInit(IOGetByTag(spi->miso), OWNER_SPI_MISO, RESOURCE_INDEX(device)); + IOInit(IOGetByTag(spi->mosi), OWNER_SPI_MOSI, RESOURCE_INDEX(device)); + +#if defined(STM32F3) || defined(STM32F4) + IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_CFG, spi->af); + IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_CFG, spi->af); + IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->af); +#elif defined(STM32F10X) + IOConfigGPIO(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG); + IOConfigGPIO(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG); + IOConfigGPIO(IOGetByTag(spi->mosi), SPI_IO_AF_MOSI_CFG); +#else +#error Undefined MCU architecture +#endif + + // Init SPI hardware + SPI_I2S_DeInit(spi->dev); + + SPI_InitTypeDef spiInit; + spiInit.SPI_Mode = SPI_Mode_Master; + spiInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex; + spiInit.SPI_DataSize = SPI_DataSize_8b; + spiInit.SPI_NSS = SPI_NSS_Soft; + spiInit.SPI_FirstBit = SPI_FirstBit_MSB; + spiInit.SPI_CRCPolynomial = 7; + spiInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; + + if (spi->leadingEdge) { + spiInit.SPI_CPOL = SPI_CPOL_Low; + spiInit.SPI_CPHA = SPI_CPHA_1Edge; + } else { + spiInit.SPI_CPOL = SPI_CPOL_High; + spiInit.SPI_CPHA = SPI_CPHA_2Edge; + } + +#ifdef STM32F303xC + // Configure for 8-bit reads. + SPI_RxFIFOThresholdConfig(spi->dev, SPI_RxFIFOThreshold_QF); +#endif + + SPI_Init(spi->dev, &spiInit); + SPI_Cmd(spi->dev, ENABLE); +} + +// return uint8_t value or -1 when failure +uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) +{ + uint16_t spiTimeout = 1000; + + while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) + if ((spiTimeout--) == 0) + return spiTimeoutUserCallback(instance); + +#ifdef STM32F303xC + SPI_SendData8(instance, txByte); +#else + SPI_I2S_SendData(instance, txByte); +#endif + spiTimeout = 1000; + while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) + if ((spiTimeout--) == 0) + return spiTimeoutUserCallback(instance); + +#ifdef STM32F303xC + return ((uint8_t)SPI_ReceiveData8(instance)); +#else + return ((uint8_t)SPI_I2S_ReceiveData(instance)); +#endif +} + +/** + * Return true if the bus is currently in the middle of a transmission. + */ +bool spiIsBusBusy(SPI_TypeDef *instance) +{ +#ifdef STM32F303xC + return SPI_GetTransmissionFIFOStatus(instance) != SPI_TransmissionFIFOStatus_Empty || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET; +#else + return SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET; +#endif + +} + +bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len) +{ + uint16_t spiTimeout = 1000; + + uint8_t b; + instance->DR; + while (len--) { + b = txData ? *(txData++) : 0xFF; + while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) { + if ((spiTimeout--) == 0) + return spiTimeoutUserCallback(instance); + } +#ifdef STM32F303xC + SPI_SendData8(instance, b); +#else + SPI_I2S_SendData(instance, b); +#endif + spiTimeout = 1000; + while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) { + if ((spiTimeout--) == 0) + return spiTimeoutUserCallback(instance); + } +#ifdef STM32F303xC + b = SPI_ReceiveData8(instance); +#else + b = SPI_I2S_ReceiveData(instance); +#endif + if (rxData) + *(rxData++) = b; + } + + return true; +} + +void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor) +{ +#define BR_BITS ((BIT(5) | BIT(4) | BIT(3))) + +#if !(defined(STM32F1) || defined(STM32F3)) + // SPI2 and SPI3 are on APB1/AHB1 which PCLK is half that of APB2/AHB2. + + if (instance == SPI2 || instance == SPI3) { + divisor /= 2; // Safe for divisor == 0 or 1 + } +#endif + + SPI_Cmd(instance, DISABLE); + + const uint16_t tempRegister = (instance->CR1 & ~BR_BITS); + instance->CR1 = tempRegister | (divisor ? ((ffs(divisor | 0x100) - 2) << 3) : 0); + + SPI_Cmd(instance, ENABLE); + +#undef BR_BITS +} +#endif