From 95f37d7c7796316049b6a02942703c62b5f1eaeb Mon Sep 17 00:00:00 2001 From: victorpv Date: Sat, 29 Apr 2017 22:08:02 -0500 Subject: [PATCH] 1st version SPI DMA for F4. Blocking. --- STM32/libraries/SPI/src/SPI.cpp | 159 ++++++++++++++++++++++++++++++-- STM32/libraries/SPI/src/SPI.h | 59 ++++++++++++ 2 files changed, 211 insertions(+), 7 deletions(-) diff --git a/STM32/libraries/SPI/src/SPI.cpp b/STM32/libraries/SPI/src/SPI.cpp index 52defa2..6bb5422 100644 --- a/STM32/libraries/SPI/src/SPI.cpp +++ b/STM32/libraries/SPI/src/SPI.cpp @@ -9,35 +9,143 @@ #endif + void SPIClass::begin() { + DMA_Stream_TypeDef *_StreamTX; + DMA_Stream_TypeDef *_StreamRX; + uint32_t _ChannelTX; + uint32_t _ChannelRX; + apb_freq = stm32GetClockFrequency((void*)spiHandle.Instance); spiHandle.Init.Mode = SPI_MODE_MASTER; spiHandle.Init.Direction = SPI_DIRECTION_2LINES; spiHandle.Init.DataSize = SPI_DATASIZE_8BIT; spiHandle.Init.NSS = SPI_NSS_SOFT; + spiHandle.hdmatx = &hdma_spi_tx; + spiHandle.hdmarx = &hdma_spi_rx; + + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + #ifdef SPI1 - if (spiHandle.Instance == SPI1) __HAL_RCC_SPI1_CLK_ENABLE(); + if (spiHandle.Instance== SPI1) { + __HAL_RCC_SPI1_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI1_StreamTX); + _StreamRX = SPIx_DMA(SPI1_StreamRX); + _ChannelTX = SPI1_ChannelTX; + _ChannelRX = SPI1_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI1); + } #endif #ifdef SPI2 - if (spiHandle.Instance == SPI2) __HAL_RCC_SPI2_CLK_ENABLE(); + else if (spiHandle.Instance == SPI2) { + __HAL_RCC_SPI2_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI2_StreamTX); + _StreamRX = SPIx_DMA(SPI2_StreamRX); + _ChannelTX = SPI2_ChannelTX; + _ChannelRX = SPI2_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI2); + } #endif #ifdef SPI3 - if (spiHandle.Instance == SPI3) __HAL_RCC_SPI3_CLK_ENABLE(); + else if (spiHandle.Instance == SPI3) { + __HAL_RCC_SPI3_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI3_StreamTX); + _StreamRX = SPIx_DMA(SPI3_StreamRX); + _ChannelTX = SPI3_ChannelTX; + _ChannelRX = SPI3_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI3); + } #endif #ifdef SPI4 - if (spiHandle.Instance == SPI4) __HAL_RCC_SPI4_CLK_ENABLE(); + else if (spiHandle.Instance == SPI4) { + __HAL_RCC_SPI4_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI4_StreamTX); + _StreamRX = SPIx_DMA(SPI4_StreamRX); + _ChannelTX = SPI4_ChannelTX; + _ChannelRX = SPI4_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI4); + } #endif #ifdef SPI5 - if (spiHandle.Instance == SPI5) __HAL_RCC_SPI5_CLK_ENABLE(); + else if (spiHandle.Instance == SPI5) { + __HAL_RCC_SPI5_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI5_StreamTX); + _StreamRX = SPIx_DMA(SPI5_StreamRX); + _ChannelTX = SPI5_ChannelTX; + _ChannelRX = SPI5_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI5); + } #endif #ifdef SPI6 - if (spiHandle.Instance == SPI6) __HAL_RCC_SPI6_CLK_ENABLE(); + else if (spiHandle.Instance == SPI6) { + __HAL_RCC_SPI6_CLK_ENABLE(); + _StreamTX = SPIx_DMA(SPI6_StreamTX); + _StreamRX = SPIx_DMA(SPI6_StreamRX); + _ChannelTX = SPI6_ChannelTX; + _ChannelRX = SPI6_ChannelRX; + /* + * Not used yet, still just polling + */ + //_SPISetDmaIRQ(SPI6); + } #endif + + hdma_spi_tx.Instance = _StreamTX; + hdma_spi_tx.Parent = &spiHandle; + hdma_spi_tx.Init.Channel = _ChannelTX; + hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi_tx.Init.Mode = DMA_NORMAL; + hdma_spi_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; + hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_spi_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_spi_tx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_spi_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; + + + hdma_spi_rx.Instance = _StreamRX; + hdma_spi_rx.Parent = &spiHandle; + hdma_spi_rx.Init.Channel = _ChannelRX; + hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi_rx.Init.Mode = DMA_NORMAL; + hdma_spi_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH; + hdma_spi_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_spi_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_spi_rx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_spi_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; + + stm32AfSPIInit(spiHandle.Instance, mosiPort, mosiPin, misoPort, misoPin, sckPort, sckPin); -}; + +} void SPIClass::beginTransaction(SPISettings settings) { if (this->settings.clock == settings.clock @@ -122,3 +230,40 @@ void SPIClass::stm32SetSCK(uint8_t sck) { void SPIClass::stm32SetInstance(SPI_TypeDef *instance) { spiHandle.Instance = instance; } +uint8_t SPIClass::dmaTransfer(uint8_t *transmitBuf, uint8_t *receiveBuf, uint16_t length) { + //HAL_SPI_TransmitReceive(&spiHandle, transmitBuf, receiveBuf, length, 1000); + // DMA handles configured in Begin. Need to change the MINC mode since dmaSend may have been called last + hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE; + + HAL_DMA_Init(&hdma_spi_tx); + HAL_DMA_Init(&hdma_spi_rx); + + /* + * We dont use interrupts here. + */ + + HAL_SPI_TransmitReceive_DMA(&spiHandle, transmitBuf, receiveBuf, length); + HAL_DMA_PollForTransfer(&hdma_spi_tx, HAL_DMA_FULL_TRANSFER, 10000); + HAL_DMA_PollForTransfer(&hdma_spi_rx, HAL_DMA_FULL_TRANSFER, 10000); + HAL_DMA_IRQHandler(&hdma_spi_tx); + HAL_DMA_IRQHandler(&hdma_spi_rx); + spiHandle.State = HAL_SPI_STATE_READY; + return 0; +} +uint8_t SPIClass::dmaSend(uint8_t *transmitBuf, uint16_t length, bool minc) { + //HAL_SPI_TransmitReceive(&spiHandle, transmitBuf, buf, length, 1000); + //Need to set TX DMA handle. + if (minc == 1){ + hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE; + } else { + hdma_spi_tx.Init.MemInc = DMA_MINC_DISABLE; + } + + HAL_DMA_Init(&hdma_spi_tx); + + HAL_SPI_Transmit_DMA(&spiHandle, transmitBuf, length); + HAL_DMA_PollForTransfer(&hdma_spi_tx, HAL_DMA_FULL_TRANSFER, 10000); + HAL_DMA_IRQHandler(&hdma_spi_tx); + spiHandle.State = HAL_SPI_STATE_READY; + return 0; +} diff --git a/STM32/libraries/SPI/src/SPI.h b/STM32/libraries/SPI/src/SPI.h index 15eb610..685d2a2 100644 --- a/STM32/libraries/SPI/src/SPI.h +++ b/STM32/libraries/SPI/src/SPI.h @@ -38,6 +38,60 @@ #define SPI_MODE2 0x02 #define SPI_MODE3 0x03 +#ifdef STM32F0 +#endif +#ifdef STM32F1 + #define SPI1_StreamTX DMA1_Channel3 + #define SPI1_StreamRX DMA1_Channel2 + #define SPI1_ChannelTX + #define SPI1_ChannelRX + #define SPI2_StreamTX DMA1_Channel5 + #define SPI2_StreamRX DMA1_Channel4 + #define SPI2_ChannelTX + #define SPI2_ChannelRX + #define SPI3_StreamTX DMA2_Channel2 + #define SPI3_StreamRX DMA2_Channel1 + #define SPI3_ChannelTX + #define SPI3_ChannelRX +#endif +#ifdef STM32F2 +#endif +#ifdef STM32F3 +#endif +#ifdef STM32F4 + #define SPI1_StreamTX 2_Stream3 + #define SPI1_StreamRX 2_Stream0 + #define SPI1_ChannelTX DMA_CHANNEL_3 + #define SPI1_ChannelRX DMA_CHANNEL_3 + #define SPI2_StreamTX 1_Stream4 + #define SPI2_StreamRX 1_Stream3 + #define SPI2_ChannelTX DMA_CHANNEL_0 + #define SPI2_ChannelRX DMA_CHANNEL_0 + #define SPI3_StreamTX 1_Stream5 + #define SPI3_StreamRX 1_Stream0 + #define SPI3_ChannelTX DMA_CHANNEL_0 + #define SPI3_ChannelRX DMA_CHANNEL_0 + + #define _SPIx_DMA(a) DMA##a + #define SPIx_DMA(a) _SPIx_DMA(a) + #define _SPIx_DMA_IRQn(a) DMA##a##_IRQn + #define SPIx_DMA_IRQn(a) _SPIx_DMA_IRQn(a) + + #define _SPISetDmaIRQ(a) HAL_NVIC_SetPriority(SPIx_DMA_IRQn(a##_StreamTX), 0, 0); \ + HAL_NVIC_SetPriority(SPIx_DMA_IRQn(a##_StreamRX), 0, 0); \ + HAL_NVIC_EnableIRQ(SPIx_DMA_IRQn(a##_StreamTX)); \ + HAL_NVIC_EnableIRQ(SPIx_DMA_IRQn(a##_StreamRX)); +#endif +#ifdef STM32F7 +#endif +#ifdef STM32L0 +#endif +#ifdef STM32L1 +#endif +#ifdef STM32L4 +#endif + + class SPISettings { public: SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode): clock(clock), bitOrder(bitOrder), dataMode(dataMode) {}; @@ -82,6 +136,9 @@ class SPIClass { uint8_t transfer(uint8_t data); uint16_t transfer16(uint16_t data); void transfer(uint8_t *buf, size_t count); + uint8_t dmaTransfer(uint8_t *transmitBuf, uint8_t *receiveBuf, uint16_t length); + uint8_t dmaSend(uint8_t *transmitBuf, uint16_t length, bool minc = 1); + private: uint32_t apb_freq = 0; @@ -89,6 +146,8 @@ class SPIClass { SPISettings settings = {}; SPI_HandleTypeDef spiHandle = {}; + DMA_HandleTypeDef hdma_spi_rx = {}; + DMA_HandleTypeDef hdma_spi_tx = {}; GPIO_TypeDef *mosiPort = NULL; uint32_t mosiPin = 0;