feat: H7 SPI support (#5425)

This commit is contained in:
Raphael Coeffic
2024-08-13 15:03:47 +02:00
committed by GitHub
parent 2df817fbf0
commit 3bdec2f347
2 changed files with 104 additions and 12 deletions
@@ -60,7 +60,11 @@ void stm32_spi_enable_clock(SPI_TypeDef *SPIx)
#endif
#if defined(SPI6)
else if (SPIx == SPI6) {
#if defined(LL_APB2_GRP1_PERIPH_SPI6)
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI6);
#elif defined(LL_APB4_GRP1_PERIPH_SPI6)
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SPI6);
#endif
}
#endif
}
@@ -147,18 +151,47 @@ static void _config_dma_streams(const stm32_spi_t* spi)
LL_DMA_InitTypeDef dmaInit;
LL_DMA_StructInit(&dmaInit);
#if defined(STM32F2) || defined(STM32F4)
dmaInit.Channel = spi->DMA_Channel;
dmaInit.PeriphOrM2MSrcAddress = (uint32_t)&spi->SPIx->DR;
dmaInit.PeriphOrM2MSrcAddress = LL_SPI_DMA_GetRegAddr(spi->SPIx);
#endif
#if defined(STM32F2) || defined(STM32F4) || defined(STM32H7)
dmaInit.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dmaInit.Priority = LL_DMA_PRIORITY_VERYHIGH;
dmaInit.FIFOMode = spi->DMA_FIFOMode;
dmaInit.FIFOThreshold = spi->DMA_FIFOThreshold;
dmaInit.MemoryOrM2MDstDataSize = spi->DMA_MemoryOrM2MDstDataSize;
dmaInit.MemBurst = spi->DMA_MemBurst;
#elif defined(STM32H7RS)
dmaInit.Priority = LL_DMA_LOW_PRIORITY_HIGH_WEIGHT;
#endif
#if defined(STM32H7)
dmaInit.PeriphRequest = spi->rxDMA_PeriphRequest;
dmaInit.PeriphOrM2MSrcAddress = LL_SPI_DMA_GetRxRegAddr(spi->SPIx);
#elif defined(STM32H7RS)
dmaInit.Request = spi->rxDMA_PeriphRequest;
dmaInit.SrcAddress = LL_SPI_DMA_GetRxRegAddr(spi->SPIx);
dmaInit.SrcIncMode = LL_DMA_SRC_FIXED;
dmaInit.DestIncMode = LL_DMA_DEST_INCREMENT;
dmaInit.DestDataWidth = LL_DMA_DEST_DATAWIDTH_HALFWORD; // TODO
#endif
dmaInit.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
LL_DMA_Init(spi->DMA, spi->rxDMA_Stream, &dmaInit);
#if defined(STM32H7)
dmaInit.PeriphRequest = spi->txDMA_PeriphRequest;
dmaInit.PeriphOrM2MSrcAddress = LL_SPI_DMA_GetTxRegAddr(spi->SPIx);
#elif defined(STM32H7RS)
dmaInit.Request = spi->rxDMA_PeriphRequest;
dmaInit.DestAddress = LL_SPI_DMA_GetTxRegAddr(spi->SPIx);
dmaInit.SrcIncMode = LL_DMA_SRC_INCREMENT;
dmaInit.DestIncMode = LL_DMA_DEST_FIXED;
dmaInit.SrcDataWidth = LL_DMA_SRC_DATAWIDTH_HALFWORD; // TODO
#endif
dmaInit.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
LL_DMA_Init(spi->DMA, spi->txDMA_Stream, &dmaInit);
}
@@ -212,10 +245,18 @@ void stm32_spi_set_max_baudrate(const stm32_spi_t* spi, uint32_t baudrate)
uint8_t stm32_spi_transfer_byte(const stm32_spi_t* spi, uint8_t out)
{
auto* SPIx = spi->SPIx;
#if defined(STM32H7) || defined(STM32H7RS)
while (!LL_SPI_IsActiveFlag_TXP(SPIx));
#else
while (!LL_SPI_IsActiveFlag_TXE(SPIx));
#endif
LL_SPI_TransmitData8(SPIx, out);
#if defined(STM32H7) || defined(STM32H7RS)
while (!LL_SPI_IsActiveFlag_RXP(SPIx));
#else
while (!LL_SPI_IsActiveFlag_RXNE(SPIx));
#endif
return LL_SPI_ReceiveData8(SPIx);
}
@@ -242,10 +283,18 @@ uint16_t stm32_spi_transfer_bytes(const stm32_spi_t* spi, const uint8_t* out,
uint16_t stm32_spi_transfer_word(const stm32_spi_t* spi, uint16_t out)
{
auto* SPIx = spi->SPIx;
#if defined(STM32H7) || defined(STM32H7RS)
while (!LL_SPI_IsActiveFlag_TXP(SPIx));
#else
while (!LL_SPI_IsActiveFlag_TXE(SPIx));
#endif
LL_SPI_TransmitData16(SPIx, out);
while (!LL_SPI_IsActiveFlag_RXNE(SPIx));
#if defined(STM32H7) || defined(STM32H7RS)
while (!LL_SPI_IsActiveFlag_TXP(SPIx));
#else
while (!LL_SPI_IsActiveFlag_TXE(SPIx));
#endif
return LL_SPI_ReceiveData16(SPIx);
}
@@ -253,13 +302,26 @@ uint16_t stm32_spi_transfer_word(const stm32_spi_t* spi, uint16_t out)
static uint16_t _scratch_byte __DMA;
static uint8_t _scratch_buffer[512] __DMA;
#if defined(STM32H7) || defined(STM32H7RS) || defined(STM32F4)
extern uint32_t _sram;
extern uint32_t _eram;
#define _IS_DMA_BUFFER(addr) \
((intptr_t)(addr) >= (intptr_t)&_sram && (intptr_t)(addr) <= (intptr_t)&_eram)
#else
#define _IS_DMA_BUFFER(addr) (true)
#endif
#define _IS_ALIGNED(addr) (((intptr_t)(addr) & 3U) == 0U)
static void _dma_enable_stream(DMA_TypeDef* DMAx, uint32_t stream,
const void* data, uint32_t length)
{
stm32_dma_check_tc_flag(DMAx, stream);
#if !defined(STM32H7RS)
LL_DMA_SetMemoryAddress(DMAx, stream, (uintptr_t)data);
LL_DMA_SetDataLength(DMAx, stream, length);
LL_DMA_EnableStream(DMAx, stream);
#endif
}
#endif
@@ -271,7 +333,8 @@ uint16_t stm32_spi_dma_receive_bytes(const stm32_spi_t* spi,
return stm32_spi_transfer_bytes(spi, nullptr, data, length);
}
if (((uintptr_t)data < SRAM_BASE) || ((uintptr_t)data & 3)) {
bool use_scratch_buffer = !_IS_DMA_BUFFER(data) || !_IS_ALIGNED(data);
if (use_scratch_buffer) {
_dma_enable_stream(spi->DMA, spi->rxDMA_Stream, _scratch_buffer, length);
} else {
_dma_enable_stream(spi->DMA, spi->rxDMA_Stream, data, length);
@@ -279,23 +342,32 @@ uint16_t stm32_spi_dma_receive_bytes(const stm32_spi_t* spi,
LL_SPI_EnableDMAReq_RX(spi->SPIx);
_scratch_byte = 0xFFFF;
#if !defined(STM32H7RS)
LL_DMA_SetMemoryIncMode(spi->DMA, spi->txDMA_Stream, LL_DMA_MEMORY_NOINCREMENT);
#endif
_dma_enable_stream(spi->DMA, spi->txDMA_Stream, &_scratch_byte, length);
LL_SPI_EnableDMAReq_TX(spi->SPIx);
// Wait for end of DMA transfer
while(!stm32_dma_check_tc_flag(spi->DMA, spi->rxDMA_Stream));
// Disable SPI TX/RX DMA requests
CLEAR_BIT(spi->SPIx->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
#if !defined(STM32H7) && !defined(STM32H7RS)
// Wait for TXE=1
while(!LL_SPI_IsActiveFlag_TXE(spi->SPIx));
while (!LL_SPI_IsActiveFlag_TXE(spi->SPIx));
// Wait for BSY=0
while(LL_SPI_IsActiveFlag_BSY(spi->SPIx));
#else
// Wait for EOT=1
while (!LL_SPI_IsActiveFlag_EOT(spi->SPIx));
LL_SPI_ClearFlag_EOT(spi->SPIx);
#endif
if (((uintptr_t)data < SRAM_BASE) || ((uintptr_t)data & 3)) {
// Disable SPI TX/RX DMA requests
LL_SPI_DisableDMAReq_TX(spi->SPIx);
LL_SPI_DisableDMAReq_RX(spi->SPIx);
if (use_scratch_buffer) {
memcpy(data, _scratch_buffer, length);
}
@@ -313,21 +385,23 @@ uint16_t stm32_spi_dma_transmit_bytes(const stm32_spi_t* spi,
return stm32_spi_transfer_bytes(spi, data, nullptr, length);
}
if (((uintptr_t)data < SRAM_BASE) || ((uintptr_t)data & 3)) {
bool use_scratch_buffer = !_IS_DMA_BUFFER(data) || !_IS_ALIGNED(data);
if (use_scratch_buffer) {
memcpy(_scratch_buffer, data, length);
data = _scratch_buffer;
}
#if !defined(STM32H7RS)
LL_DMA_SetMemoryIncMode(spi->DMA, spi->txDMA_Stream, LL_DMA_MEMORY_INCREMENT);
#endif
_dma_enable_stream(spi->DMA, spi->txDMA_Stream, data, length);
LL_SPI_EnableDMAReq_TX(spi->SPIx);
// Wait for end of DMA transfer
while (!stm32_dma_check_tc_flag(spi->DMA, spi->txDMA_Stream));
// Disable SPI TX DMA requests
CLEAR_BIT(spi->SPIx->CR2, SPI_CR2_TXDMAEN);
#if !defined(STM32H7) && !defined(STM32H7RS)
// Wait for TXE=1
while (!LL_SPI_IsActiveFlag_TXE(spi->SPIx));
@@ -338,6 +412,19 @@ uint16_t stm32_spi_dma_transmit_bytes(const stm32_spi_t* spi,
if (LL_SPI_IsActiveFlag_RXNE(spi->SPIx)) {
(void)LL_SPI_ReceiveData8(spi->SPIx);
}
#else
// Wait for EOT=1
while (!LL_SPI_IsActiveFlag_EOT(spi->SPIx));
LL_SPI_ClearFlag_EOT(spi->SPIx);
// Clear RX FIFO
while (LL_SPI_IsActiveFlag_RXP(spi->SPIx)) {
(void)LL_SPI_ReceiveData8(spi->SPIx);
}
#endif
// Disable SPI TX DMA requests
LL_SPI_DisableDMAReq_TX(spi->SPIx);
return length;
#else
@@ -33,7 +33,12 @@ struct stm32_spi_t {
uint32_t CS_Pin; // CS
DMA_TypeDef* DMA;
#if defined(STM32H7) || defined(STM32H7RS)
uint32_t txDMA_PeriphRequest;
uint32_t rxDMA_PeriphRequest;
#else
uint32_t DMA_Channel;
#endif
uint32_t txDMA_Stream;
uint32_t rxDMA_Stream;
uint32_t DMA_FIFOMode;