spi: add nonblocking transfer() with callback
This commit is contained in:
parent
3f32b7e417
commit
ad1c5ab795
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "stm32_dma.h"
|
||||
|
||||
#include "stm32_HAL/stm32XXxx_ll_spi.h"
|
||||
|
||||
#if defined(MOSI) || defined(MISO) || defined(SCK)
|
||||
SPIClass SPI(SPI1, MOSI, MISO, SCK);
|
||||
#else
|
||||
|
@ -11,6 +13,10 @@
|
|||
#endif
|
||||
|
||||
|
||||
int maxUsedCallback = 0; // This is set in SPI begin()
|
||||
SPI_TypeDef *spiCallbackInstances[6];
|
||||
SPIClass *spiClass[6];
|
||||
|
||||
|
||||
void SPIClass::begin() {
|
||||
|
||||
|
@ -30,31 +36,55 @@ void SPIClass::begin() {
|
|||
#ifdef SPI1
|
||||
if (spiHandle.Instance== SPI1) {
|
||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 1);
|
||||
spiCallbackInstances[0] = spiHandle.Instance;
|
||||
spiClass[0] = this;
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI2
|
||||
else if (spiHandle.Instance == SPI2) {
|
||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 2);
|
||||
spiCallbackInstances[1] = spiHandle.Instance;
|
||||
spiClass[1] = this;
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI3
|
||||
else if (spiHandle.Instance == SPI3) {
|
||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 3);
|
||||
spiCallbackInstances[2] = spiHandle.Instance;
|
||||
spiClass[2] = this;
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI4
|
||||
else if (spiHandle.Instance == SPI4) {
|
||||
__HAL_RCC_SPI4_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 4);
|
||||
spiCallbackInstances[3] = spiHandle.Instance;
|
||||
spiClass[3] = this;
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI5
|
||||
else if (spiHandle.Instance == SPI5) {
|
||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 5);
|
||||
spiCallbackInstances[4] = spiHandle.Instance;
|
||||
spiClass[4] = this;
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI6
|
||||
else if (spiHandle.Instance == SPI6) {
|
||||
__HAL_RCC_SPI6_CLK_ENABLE();
|
||||
|
||||
maxUsedCallback = max(maxUsedCallback, 6);
|
||||
spiCallbackInstances[5] = spiHandle.Instance;
|
||||
spiClass[5] = this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -176,60 +206,88 @@ void SPIClass::stm32SetInstance(SPI_TypeDef *instance) {
|
|||
spiHandle.Instance = instance;
|
||||
}
|
||||
|
||||
#if defined(STM32F1) || defined(STM32F4)
|
||||
|
||||
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.
|
||||
if (length == 0) return 0;
|
||||
|
||||
#ifdef STM32F1
|
||||
__HAL_DMA_DISABLE(&hdma_spi_tx);
|
||||
__HAL_DMA_DISABLE(&hdma_spi_rx);
|
||||
#endif
|
||||
|
||||
if (!transmitBuf) {
|
||||
transmitBuf = (uint8_t*)&repeatTransmitData;
|
||||
hdma_spi_tx.Init.MemInc = DMA_MINC_DISABLE;
|
||||
} else {
|
||||
//Need to change the MINC mode since dmaSend with MINC 0 or Null transmitBuf 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);
|
||||
|
||||
HAL_SPI_TransmitReceive_DMA(&spiHandle, transmitBuf, receiveBuf, length);
|
||||
|
||||
while (spiHandle.State != HAL_SPI_STATE_READY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
uint8_t SPIClass::dmaSend(uint8_t *transmitBuf, uint16_t length, bool minc) {
|
||||
bool SPIClass::transfer(uint8_t *txBuffer, uint8_t *rxBuffer, size_t count, spi_callback_type callback) {
|
||||
this->callback = callback;
|
||||
|
||||
#ifdef STM32F1
|
||||
__HAL_DMA_DISABLE(&hdma_spi_tx);
|
||||
__HAL_DMA_DISABLE(&hdma_spi_rx);
|
||||
#endif
|
||||
|
||||
//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;
|
||||
}
|
||||
if (txBuffer != NULL) {
|
||||
hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
} else {
|
||||
txBuffer = (uint8_t*)&repeatTransmitData;
|
||||
hdma_spi_tx.Init.MemInc = DMA_MINC_DISABLE;
|
||||
}
|
||||
|
||||
HAL_DMA_Init(&hdma_spi_tx);
|
||||
if (rxBuffer != NULL) {
|
||||
|
||||
HAL_SPI_Transmit_DMA(&spiHandle, transmitBuf, length);
|
||||
if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (spiHandle.State != HAL_SPI_STATE_READY);
|
||||
if (HAL_DMA_Init(&hdma_spi_rx) != HAL_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
dmaDone = false;
|
||||
if (HAL_SPI_TransmitReceive_DMA(&spiHandle, txBuffer, rxBuffer, count) != HAL_OK) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dmaDone = false;
|
||||
if (HAL_SPI_Transmit_DMA(&spiHandle, txBuffer, count) != HAL_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SPIClass::flush(void) {
|
||||
while (!done()) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
bool SPIClass::done(void) {
|
||||
return dmaDone;
|
||||
}
|
||||
|
||||
uint8_t SPIClass::dmaTransfer(uint8_t *transmitBuf, uint8_t *receiveBuf, uint16_t length) {
|
||||
return transfer(transmitBuf, receiveBuf, length);
|
||||
}
|
||||
|
||||
uint8_t SPIClass::dmaSend(uint8_t *transmitBuf, uint16_t length, bool minc) {
|
||||
if (minc) {
|
||||
return transfer(transmitBuf, NULL, length);
|
||||
} else {
|
||||
repeatTransmitData = transmitBuf[0];
|
||||
return transfer((uint8_t*)NULL, NULL, length);
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32SpiDmaFinished(SPI_HandleTypeDef *hspi) {
|
||||
for(int i=0; i<maxUsedCallback; i++) {
|
||||
if (spiCallbackInstances[i] == hspi->Instance) {
|
||||
spiClass[i]->repeatTransmitData = 0xFFFF;
|
||||
|
||||
if (spiClass[i]->callback != NULL) {
|
||||
spiClass[i]->callback();
|
||||
}
|
||||
spiClass[i]->dmaDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
stm32SpiDmaFinished(hspi);
|
||||
}
|
||||
|
||||
extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
// Called at the end of DMA
|
||||
stm32SpiDmaFinished(hspi);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,17 @@
|
|||
#define SPI_HAS_OLD_DMATRANSFER
|
||||
#endif
|
||||
|
||||
// SPI_HAS_EXTENDED_TRANSFER means SPI has
|
||||
// - transfer(uint8_t data, uint8_t *rxBuffer, size_t count)
|
||||
// - transfer(uint8_t *txBuffer, uint8_t *rxBuffer, size_t count)
|
||||
#define SPI_HAS_EXTENDED_TRANSFER
|
||||
|
||||
// SPI_HAS_EXTENDED_NONBLOCKING_TRANSFER means SPI has
|
||||
// - implies SPI_HAS_EXTENDED_TRANSFER
|
||||
// - transfer(uint8_t data, uint8_t *rxBuffer, size_t count, callback)
|
||||
// - transfer(uint8_t *txBuffer, uint8_t *rxBuffer, size_t count, callback)
|
||||
#define SPI_HAS_EXTENDED_NONBLOCKING_TRANSFER
|
||||
|
||||
// SPI_HAS_TRANSACTION means SPI has
|
||||
// - beginTransaction()
|
||||
// - endTransaction()
|
||||
|
@ -64,7 +75,7 @@ class SPISettings {
|
|||
uint8_t dataMode;
|
||||
};
|
||||
|
||||
|
||||
typedef void (*spi_callback_type)();
|
||||
|
||||
class SPIClass {
|
||||
public:
|
||||
|
@ -97,13 +108,42 @@ 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);
|
||||
|
||||
|
||||
bool transfer(uint8_t data, uint8_t *rxBuffer, size_t count) {
|
||||
repeatTransmitData = data;
|
||||
if (transfer((uint8_t*) NULL, rxBuffer, count, NULL)) {
|
||||
flush();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool transfer(uint8_t *txBuffer, uint8_t *rxBuffer, size_t count) {
|
||||
if (transfer(txBuffer, rxBuffer, count, NULL)) {
|
||||
flush();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool transfer(uint8_t data, uint8_t *rxBuffer, size_t count, spi_callback_type callback) {
|
||||
repeatTransmitData = data;
|
||||
return transfer((uint8_t*) NULL, rxBuffer, count, callback);
|
||||
}
|
||||
bool transfer(uint8_t *txBuffer, uint8_t *rxBuffer, size_t count, spi_callback_type callback);
|
||||
|
||||
void flush(void);
|
||||
bool done(void);
|
||||
|
||||
uint8_t __attribute__ ((deprecated)) dmaTransfer(uint8_t *transmitBuf, uint8_t *receiveBuf, uint16_t length);
|
||||
uint8_t __attribute__ ((deprecated)) dmaSend(uint8_t *transmitBuf, uint16_t length, bool minc = 1);
|
||||
|
||||
|
||||
SPI_HandleTypeDef spiHandle = {};
|
||||
|
||||
uint16_t repeatTransmitData = 0XFFFF;
|
||||
spi_callback_type callback;
|
||||
|
||||
volatile bool dmaDone = false;
|
||||
|
||||
private:
|
||||
uint32_t apb_freq = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
#include "SdSpiDriver.h"
|
||||
#include "SdCard/SdInfo.h"
|
||||
//------------------------------------------------------------------------------
|
||||
static SPIClass& pSpi = SPI;
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -65,8 +66,12 @@ uint8_t SdSpiAltDriver::receive() {
|
|||
*/
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
int rtn = 0;
|
||||
#ifdef SPI_HAS_OLD_DMATRANSFER
|
||||
rtn = pSpi.dmaTransfer(0, buf, n);
|
||||
#ifdef SPI_HAS_EXTENDED_TRANSFER
|
||||
if (pSpi.transfer((uint8_t *)NULL, buf, n)) {
|
||||
return 0;
|
||||
} else {
|
||||
return SD_CARD_ERROR_READ;
|
||||
}
|
||||
#else // USE_STM32F1_DMAC
|
||||
// pSpi.read(buf, n); fails ?? use byte transfer
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
|
@ -90,8 +95,8 @@ void SdSpiAltDriver::send(uint8_t b) {
|
|||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
#ifdef SPI_HAS_OLD_DMATRANSFER
|
||||
pSpi.dmaSend(const_cast<uint8_t*>(buf), n);
|
||||
#ifdef SPI_HAS_EXTENDED_TRANSFER
|
||||
pSpi.transfer((uint8_t*)buf, NULL, n);
|
||||
#else // #if USE_STM32F1_DMAC
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pSpi.transfer(buf[i]);
|
||||
|
|
Loading…
Reference in New Issue