diff --git a/cmake/stm32h7.cmake b/cmake/stm32h7.cmake index c936bf0db..70400fb9f 100644 --- a/cmake/stm32h7.cmake +++ b/cmake/stm32h7.cmake @@ -114,7 +114,7 @@ set(STM32H7_HAL_SRC # stm32h7xx_ll_rng.c # stm32h7xx_ll_rtc.c stm32h7xx_ll_sdmmc.c -# stm32h7xx_ll_spi.c + stm32h7xx_ll_spi.c # stm32h7xx_ll_swpmi.c stm32h7xx_ll_tim.c # stm32h7xx_ll_usart.c @@ -148,7 +148,7 @@ main_sources(STM32H7_SRC drivers/adc_stm32h7xx.c drivers/bus_i2c_hal.c drivers/dma_stm32h7xx.c - drivers/bus_spi_hal.c + drivers/bus_spi_hal_ll.c drivers/memprot.h drivers/memprot_hal.c drivers/memprot_stm32h7xx.c diff --git a/src/main/drivers/bus_spi_hal.c b/src/main/drivers/bus_spi_hal.c deleted file mode 100644 index 748dd25da..000000000 --- a/src/main/drivers/bus_spi_hal.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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 - -#include "build/debug.h" -#include "drivers/bus_spi.h" -#include "dma.h" -#include "drivers/io.h" -#include "io_impl.h" -#include "drivers/nvic.h" -#include "rcc.h" - -#ifndef SPI1_NSS_PIN -#define SPI1_NSS_PIN NONE -#endif -#ifndef SPI2_NSS_PIN -#define SPI2_NSS_PIN NONE -#endif -#ifndef SPI3_NSS_PIN -#define SPI3_NSS_PIN NONE -#endif -#ifndef SPI4_NSS_PIN -#define SPI4_NSS_PIN NONE -#endif - -#if defined(USE_SPI_DEVICE_1) -static const uint32_t spiDivisorMapFast[] = { - SPI_BAUDRATEPRESCALER_256, // SPI_CLOCK_INITIALIZATON 421.875 KBits/s - SPI_BAUDRATEPRESCALER_32, // SPI_CLOCK_SLOW 843.75 KBits/s - SPI_BAUDRATEPRESCALER_16, // SPI_CLOCK_STANDARD 6.75 MBits/s - SPI_BAUDRATEPRESCALER_8, // SPI_CLOCK_FAST 13.5 MBits/s - SPI_BAUDRATEPRESCALER_4 // SPI_CLOCK_ULTRAFAST 27.0 MBits/s -}; -#endif - -#if defined(USE_SPI_DEVICE_2) || defined(USE_SPI_DEVICE_3) || defined(USE_SPI_DEVICE_4) -static const uint32_t spiDivisorMapSlow[] = { - SPI_BAUDRATEPRESCALER_256, // SPI_CLOCK_INITIALIZATON 210.937 KBits/s - SPI_BAUDRATEPRESCALER_64, // SPI_CLOCK_SLOW 843.75 KBits/s - SPI_BAUDRATEPRESCALER_8, // SPI_CLOCK_STANDARD 6.75 MBits/s - SPI_BAUDRATEPRESCALER_4, // SPI_CLOCK_FAST 13.5 MBits/s - SPI_BAUDRATEPRESCALER_2 // SPI_CLOCK_ULTRAFAST 27.0 MBits/s -}; -#endif - -static spiDevice_t spiHardwareMap[SPIDEV_COUNT] = { -#ifdef USE_SPI_DEVICE_1 - { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .af = GPIO_AF5_SPI1, .divisorMap = spiDivisorMapFast }, -#else - { .dev = NULL }, // No SPI1 -#endif -#ifdef USE_SPI_DEVICE_2 - { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1L(SPI2), .af = GPIO_AF5_SPI2, .divisorMap = spiDivisorMapSlow }, -#else - { .dev = NULL }, // No SPI2 -#endif -#ifdef USE_SPI_DEVICE_3 - { .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1L(SPI3), .af = GPIO_AF6_SPI3, .divisorMap = spiDivisorMapSlow }, -#else - { .dev = NULL }, // No SPI3 -#endif -#ifdef USE_SPI_DEVICE_4 - { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .af = GPIO_AF5_SPI4, .divisorMap = spiDivisorMapSlow } -#else - { .dev = NULL } // No SPI4 -#endif -}; - -static SPI_HandleTypeDef spiHandle[SPIDEV_COUNT]; - -SPIDevice spiDeviceByInstance(SPI_TypeDef *instance) -{ - if (instance == SPI1) - return SPIDEV_1; - - if (instance == SPI2) - return SPIDEV_2; - - if (instance == SPI3) - return SPIDEV_3; - - if (instance == SPI4) - return SPIDEV_4; - - return SPIINVALID; -} - -void spiTimeoutUserCallback(SPI_TypeDef *instance) -{ - SPIDevice device = spiDeviceByInstance(instance); - if (device == SPIINVALID) { - return; - } - - spiHardwareMap[device].errorCount++; -} - -bool spiInitDevice(SPIDevice device, bool leadingEdge) -{ - spiDevice_t *spi = &spiHardwareMap[device]; - - if (!spi->dev) { - return false; - } - - if (spi->initDone) { - return true; - } - - // Enable SPI clock - RCC_ClockCmd(spi->rcc, ENABLE); - RCC_ResetCmd(spi->rcc, DISABLE); - - IOInit(IOGetByTag(spi->sck), OWNER_SPI, RESOURCE_SPI_SCK, device + 1); - IOInit(IOGetByTag(spi->miso), OWNER_SPI, RESOURCE_SPI_MISO, device + 1); - IOInit(IOGetByTag(spi->mosi), OWNER_SPI, RESOURCE_SPI_MOSI, device + 1); - - if (leadingEdge) { - IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_LOW, spi->af); - } else { - IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_HIGH, spi->af); - } - IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG, spi->af); - IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->af); - - if (spi->nss) { - IOInit(IOGetByTag(spi->nss), OWNER_SPI, RESOURCE_SPI_CS, device + 1); - IOConfigGPIO(IOGetByTag(spi->nss), SPI_IO_CS_CFG); - } - - SPI_HandleTypeDef * hspi = &spiHandle[device]; - memset(hspi, 0, sizeof(SPI_HandleTypeDef)); - hspi->Instance = spi->dev; - - HAL_SPI_DeInit(hspi); - - hspi->Init.Mode = SPI_MODE_MASTER; - hspi->Init.Direction = SPI_DIRECTION_2LINES; - hspi->Init.DataSize = SPI_DATASIZE_8BIT; - hspi->Init.NSS = SPI_NSS_SOFT; - hspi->Init.FirstBit = SPI_FIRSTBIT_MSB; - hspi->Init.CRCPolynomial = 7; - hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; - hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; - hspi->Init.TIMode = SPI_TIMODE_DISABLED; - hspi->Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; - hspi->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* Recommanded setting to avoid glitches */ - - if (leadingEdge) { - hspi->Init.CLKPolarity = SPI_POLARITY_LOW; - hspi->Init.CLKPhase = SPI_PHASE_1EDGE; - } - else { - hspi->Init.CLKPolarity = SPI_POLARITY_HIGH; - hspi->Init.CLKPhase = SPI_PHASE_2EDGE; - } - - if (spi->nss) { - IOHi(IOGetByTag(spi->nss)); - } - - HAL_SPI_Init(hspi); - - spi->initDone = true; - return true; -} - -uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) -{ - uint8_t rxData; - spiTransfer(instance, &rxData, &txByte, 1); - return rxData; -} - -/** - * Return true if the bus is currently in the middle of a transmission. - */ -bool spiIsBusBusy(SPI_TypeDef *instance) -{ - SPIDevice device = spiDeviceByInstance(instance); - return (spiHandle[device].State == HAL_SPI_STATE_BUSY); -} - -bool spiTransfer(SPI_TypeDef *instance, uint8_t *rxData, const uint8_t *txData, int len) -{ - SPIDevice device = spiDeviceByInstance(instance); - SPI_HandleTypeDef * hspi = &spiHandle[device]; - HAL_StatusTypeDef status; - - #define SPI_DEFAULT_TIMEOUT 10 - - if (!rxData) { - status = HAL_SPI_Transmit(hspi, txData, len, SPI_DEFAULT_TIMEOUT); - } else if(!txData) { - status = HAL_SPI_Receive(hspi, rxData, len, SPI_DEFAULT_TIMEOUT); - } else { - status = HAL_SPI_TransmitReceive(hspi, txData, rxData, len, SPI_DEFAULT_TIMEOUT); - } - - if(status != HAL_OK) { - spiTimeoutUserCallback(instance); - } - - return true; -} - -void spiSetSpeed(SPI_TypeDef *instance, SPIClockSpeed_e speed) -{ - SPIDevice device = spiDeviceByInstance(instance); - SPI_HandleTypeDef * hspi = &spiHandle[device]; - - HAL_SPI_DeInit(hspi); - hspi->Init.BaudRatePrescaler = spiHardwareMap[device].divisorMap[speed]; - HAL_SPI_Init(hspi); -} - -SPI_TypeDef * spiInstanceByDevice(SPIDevice device) -{ - return spiHardwareMap[device].dev; -} diff --git a/src/main/drivers/bus_spi_hal_ll.c b/src/main/drivers/bus_spi_hal_ll.c index 9c02ae2cc..55053bc60 100644 --- a/src/main/drivers/bus_spi_hal_ll.c +++ b/src/main/drivers/bus_spi_hal_ll.c @@ -88,6 +88,30 @@ static const uint32_t spiDivisorMapSlow[] = { }; #endif +#if defined(STM32H7) +static spiDevice_t spiHardwareMap[SPIDEV_COUNT] = { +#ifdef USE_SPI_DEVICE_1 + { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .af = GPIO_AF5_SPI1, .divisorMap = spiDivisorMapFast }, +#else + { .dev = NULL }, // No SPI1 +#endif +#ifdef USE_SPI_DEVICE_2 + { .dev = SPI2, .nss = IO_TAG(SPI2_NSS_PIN), .sck = IO_TAG(SPI2_SCK_PIN), .miso = IO_TAG(SPI2_MISO_PIN), .mosi = IO_TAG(SPI2_MOSI_PIN), .rcc = RCC_APB1L(SPI2), .af = GPIO_AF5_SPI2, .divisorMap = spiDivisorMapSlow }, +#else + { .dev = NULL }, // No SPI2 +#endif +#ifdef USE_SPI_DEVICE_3 + { .dev = SPI3, .nss = IO_TAG(SPI3_NSS_PIN), .sck = IO_TAG(SPI3_SCK_PIN), .miso = IO_TAG(SPI3_MISO_PIN), .mosi = IO_TAG(SPI3_MOSI_PIN), .rcc = RCC_APB1L(SPI3), .af = GPIO_AF6_SPI3, .divisorMap = spiDivisorMapSlow }, +#else + { .dev = NULL }, // No SPI3 +#endif +#ifdef USE_SPI_DEVICE_4 + { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .af = GPIO_AF5_SPI4, .divisorMap = spiDivisorMapSlow } +#else + { .dev = NULL } // No SPI4 +#endif +}; +#else static spiDevice_t spiHardwareMap[] = { #ifdef USE_SPI_DEVICE_1 { .dev = SPI1, .nss = IO_TAG(SPI1_NSS_PIN), .sck = IO_TAG(SPI1_SCK_PIN), .miso = IO_TAG(SPI1_MISO_PIN), .mosi = IO_TAG(SPI1_MOSI_PIN), .rcc = RCC_APB2(SPI1), .af = GPIO_AF5_SPI1, .divisorMap = spiDivisorMapFast }, @@ -110,6 +134,7 @@ static spiDevice_t spiHardwareMap[] = { { .dev = NULL } // No SPI4 #endif }; +#endif SPIDevice spiDeviceByInstance(SPI_TypeDef *instance) { @@ -187,12 +212,21 @@ bool spiInitDevice(SPIDevice device, bool leadingEdge) .CRCPoly = 7, .CRCCalculation = SPI_CRCCALCULATION_DISABLE, }; + +#if defined(STM32H7) + // Prevent glitching when SPI is disabled + LL_SPI_EnableGPIOControl(spi->dev); + + LL_SPI_SetFIFOThreshold(spi->dev, LL_SPI_FIFO_TH_01DATA); + LL_SPI_Init(spi->dev, &init); +#else LL_SPI_SetRxFIFOThreshold(spi->dev, SPI_RXFIFO_THRESHOLD_QF); LL_SPI_Init(spi->dev, &init); LL_SPI_Enable(spi->dev); SET_BIT(spi->dev->CR2, SPI_RXFIFO_THRESHOLD); +#endif if (spi->nss) { IOHi(IOGetByTag(spi->nss)); @@ -204,26 +238,11 @@ bool spiInitDevice(SPIDevice device, bool leadingEdge) uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) { - uint16_t spiTimeout = 1000; - - while (!LL_SPI_IsActiveFlag_TXE(instance)) { - if ((spiTimeout--) == 0) { - spiTimeoutUserCallback(instance); - return 0xFF; - } + uint8_t value = 0xFF; + if (!spiTransfer(instance, &value, &txByte, 1)) { + return 0xFF; } - - LL_SPI_TransmitData8(instance, txByte); - - spiTimeout = 1000; - while (!LL_SPI_IsActiveFlag_RXNE(instance)) { - if ((spiTimeout--) == 0) { - spiTimeoutUserCallback(instance); - return 0xFF; - } - } - - return (uint8_t)LL_SPI_ReceiveData8(instance); + return value; } /** @@ -231,11 +250,48 @@ uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) */ bool spiIsBusBusy(SPI_TypeDef *instance) { +#if defined(STM32H7) + // H7 doesnt really have a busy flag. its should be done when the transfer is. + return false; +#else return (LL_SPI_GetTxFIFOLevel(instance) != LL_SPI_TX_FIFO_EMPTY) || LL_SPI_IsActiveFlag_BSY(instance); +#endif } bool spiTransfer(SPI_TypeDef *instance, uint8_t *rxData, const uint8_t *txData, int len) { +#if defined(STM32H7) + LL_SPI_SetTransferSize(instance, len); + LL_SPI_Enable(instance); + LL_SPI_StartMasterTransfer(instance); + while (len) { + int spiTimeout = 1000; + while(!LL_SPI_IsActiveFlag_TXP(instance)) { + if ((spiTimeout--) == 0) { + spiTimeoutUserCallback(instance); + return false; + } + } + uint8_t b = txData ? *(txData++) : 0xFF; + LL_SPI_TransmitData8(instance, b); + + spiTimeout = 1000; + while (!LL_SPI_IsActiveFlag_RXP(instance)) { + if ((spiTimeout--) == 0) { + spiTimeoutUserCallback(instance); + return false; + } + } + b = LL_SPI_ReceiveData8(instance); + if (rxData) { + *(rxData++) = b; + } + --len; + } + while (!LL_SPI_IsActiveFlag_EOT(instance)); + LL_SPI_ClearFlag_TXTF(instance); + LL_SPI_Disable(instance); +#else SET_BIT(instance->CR2, SPI_RXFIFO_THRESHOLD); while (len) { @@ -262,6 +318,7 @@ bool spiTransfer(SPI_TypeDef *instance, uint8_t *rxData, const uint8_t *txData, } --len; } +#endif return true; }