Browse Source

add h7 support to spi ll driver, drop hal version

master
bkleiner 3 years ago
parent
commit
d7341025b8
  1. 4
      cmake/stm32h7.cmake
  2. 239
      src/main/drivers/bus_spi_hal.c
  3. 95
      src/main/drivers/bus_spi_hal_ll.c

4
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

239
src/main/drivers/bus_spi_hal.c

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <platform.h>
#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;
}

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

Loading…
Cancel
Save