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;
}