diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index e162338e99..cab53b92c1 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -115,6 +115,7 @@ void SPIClass::beginTransaction(uint8_t _pin, SPISettings settings) spiSettings[idx].clk = settings.clk; spiSettings[idx].dMode = settings.dMode; spiSettings[idx].bOrder = settings.bOrder; + spiSettings[idx].noReceive = settings.noReceive; if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) { pinMode(_pin, OUTPUT); @@ -262,9 +263,8 @@ byte SPIClass::transfer(uint8_t _pin, uint8_t data, SPITransferMode _mode) if (_pin > NUM_DIGITAL_PINS) { return rx_buffer; } - + uint8_t idx = pinIdx(_pin, GET_IDX); if (_pin != _CSPinConfig) { - uint8_t idx = pinIdx(_pin, GET_IDX); if (idx >= NB_SPI_SETTINGS) { return rx_buffer; } @@ -278,7 +278,7 @@ byte SPIClass::transfer(uint8_t _pin, uint8_t data, SPITransferMode _mode) digitalWrite(_pin, LOW); } - spi_transfer(&_spi, &data, &rx_buffer, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT); + spi_transfer(&_spi, &data, &rx_buffer, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive); if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) { digitalWrite(_pin, HIGH); @@ -330,7 +330,8 @@ uint16_t SPIClass::transfer16(uint8_t _pin, uint16_t data, SPITransferMode _mode digitalWrite(_pin, LOW); } - spi_transfer(&_spi, (uint8_t *)&data, (uint8_t *)&rx_buffer, sizeof(uint16_t), SPI_TRANSFER_TIMEOUT); + spi_transfer(&_spi, (uint8_t *)&data, (uint8_t *)&rx_buffer, sizeof(uint16_t), + SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive); if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) { digitalWrite(_pin, HIGH); @@ -363,9 +364,8 @@ void SPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode if ((_count == 0) || (_buf == NULL) || (_pin > NUM_DIGITAL_PINS)) { return; } - + uint8_t idx = pinIdx(_pin, GET_IDX); if (_pin != _CSPinConfig) { - uint8_t idx = pinIdx(_pin, GET_IDX); if (idx >= NB_SPI_SETTINGS) { return; } @@ -379,7 +379,8 @@ void SPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode digitalWrite(_pin, LOW); } - spi_transfer(&_spi, ((uint8_t *)_buf), ((uint8_t *)_buf), _count, SPI_TRANSFER_TIMEOUT); + spi_transfer(&_spi, ((uint8_t *)_buf), ((uint8_t *)_buf), _count, + SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive); if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) { digitalWrite(_pin, HIGH); @@ -406,9 +407,8 @@ void SPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, S if ((_count == 0) || (_bufout == NULL) || (_bufin == NULL) || (_pin > NUM_DIGITAL_PINS)) { return; } - + uint8_t idx = pinIdx(_pin, GET_IDX); if (_pin != _CSPinConfig) { - uint8_t idx = pinIdx(_pin, GET_IDX); if (idx >= NB_SPI_SETTINGS) { return; } @@ -422,7 +422,8 @@ void SPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, S digitalWrite(_pin, LOW); } - spi_transfer(&_spi, ((uint8_t *)_bufout), ((uint8_t *)_bufin), _count, SPI_TRANSFER_TIMEOUT); + spi_transfer(&_spi, ((uint8_t *)_bufout), ((uint8_t *)_bufin), _count, + SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive); if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) { digitalWrite(_pin, HIGH); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 8ce8e5b24a..7ea60cfdad 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -44,6 +44,9 @@ extern "C" { #define SPI_MODE2 0x02 #define SPI_MODE3 0x03 +#define SPI_TRANSMITRECEIVE 0x0 +#define SPI_TRANSMITONLY 0x1 + // Transfer mode enum SPITransferMode { SPI_CONTINUE, /* Transfer not finished: CS pin kept active */ @@ -57,7 +60,9 @@ enum SPITransferMode { #define NO_CONFIG ((int16_t)(-1)) // Defines a default timeout delay in milliseconds for the SPI transfer -#define SPI_TRANSFER_TIMEOUT 1000 +#ifndef SPI_TRANSFER_TIMEOUT +#define SPI_TRANSFER_TIMEOUT 1000 +#endif /* * Defines the number of settings saved per SPI instance. Must be in range 1 to 254. @@ -69,10 +74,11 @@ enum SPITransferMode { class SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE) { clk = clock; bOrder = bitOrder; + noReceive = noRecv; if (SPI_MODE0 == dataMode) { dMode = SPI_MODE_0; @@ -102,6 +108,7 @@ class SPISettings { //SPI_MODE2 1 0 //SPI_MODE3 1 1 friend class SPIClass; + bool noReceive; }; class SPIClass { diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index b324ebebe1..ee607ee028 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -40,6 +40,7 @@ #include "utility/spi_com.h" #include "PinAF_STM32F1.h" #include "pinconfig.h" +#include "stm32yyxx_ll_spi.h" #ifdef __cplusplus extern "C" { @@ -381,22 +382,7 @@ void spi_deinit(spi_t *obj) */ spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout) { - spi_status_e ret = SPI_OK; - HAL_StatusTypeDef hal_status; - - if ((obj == NULL) || (len == 0)) { - return SPI_ERROR; - } - - hal_status = HAL_SPI_Transmit(&(obj->handle), Data, len, Timeout); - - if (hal_status == HAL_TIMEOUT) { - ret = SPI_TIMEOUT; - } else if (hal_status != HAL_OK) { - ret = SPI_ERROR; - } - - return ret; + return spi_transfer(obj, Data, Data, len, Timeout, 1 /* SPI_TRANSMITONLY */); } /** @@ -407,26 +393,59 @@ spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout) * @param rx_buffer : data to receive * @param len : length in byte of the data to send and receive * @param Timeout: Timeout duration in tick + * @param skipReceive: skip receiving data after transmit or not * @retval status of the send operation (0) in case of error */ -spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, - uint8_t *rx_buffer, uint16_t len, uint32_t Timeout) +spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer, + uint16_t len, uint32_t Timeout, bool skipReceive) { spi_status_e ret = SPI_OK; - HAL_StatusTypeDef hal_status; + uint32_t tickstart, size = len; + SPI_TypeDef *_SPI = obj->handle.Instance; - if ((obj == NULL) || (len == 0)) { - return SPI_ERROR; + if ((obj == NULL) || (len == 0) || (Timeout == 0U)) { + return Timeout > 0U ? SPI_ERROR : SPI_TIMEOUT; } + tickstart = HAL_GetTick(); + +#if defined(STM32H7xx) || defined(STM32MP1xx) + /* Start transfer */ + LL_SPI_SetTransferSize(_SPI, size); + LL_SPI_Enable(_SPI); + LL_SPI_StartMasterTransfer(_SPI); +#endif - hal_status = HAL_SPI_TransmitReceive(&(obj->handle), tx_buffer, rx_buffer, len, Timeout); + while (size--) { +#if defined(STM32H7xx) || defined(STM32MP1xx) + while (!LL_SPI_IsActiveFlag_TXP(_SPI)); +#else + while (!LL_SPI_IsActiveFlag_TXE(_SPI)); +#endif + LL_SPI_TransmitData8(_SPI, *tx_buffer++); - if (hal_status == HAL_TIMEOUT) { - ret = SPI_TIMEOUT; - } else if (hal_status != HAL_OK) { - ret = SPI_ERROR; + if (!skipReceive) { +#if defined(STM32H7xx) || defined(STM32MP1xx) + while (!LL_SPI_IsActiveFlag_RXP(_SPI)); +#else + while (!LL_SPI_IsActiveFlag_RXNE(_SPI)); +#endif + *rx_buffer++ = LL_SPI_ReceiveData8(_SPI); + } + if ((Timeout != HAL_MAX_DELAY) && (HAL_GetTick() - tickstart >= Timeout)) { + ret = SPI_TIMEOUT; + break; + } } +#if defined(STM32H7xx) || defined(STM32MP1xx) + /* Close transfer */ + /* Clear flags */ + LL_SPI_ClearFlag_EOT(_SPI); + LL_SPI_ClearFlag_TXTF(_SPI); + /* Disable SPI peripheral */ + LL_SPI_Disable(_SPI); +#endif + return ret; } diff --git a/libraries/SPI/src/utility/spi_com.h b/libraries/SPI/src/utility/spi_com.h index 0b15e011c0..abf611cba7 100644 --- a/libraries/SPI/src/utility/spi_com.h +++ b/libraries/SPI/src/utility/spi_com.h @@ -99,7 +99,7 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb); void spi_deinit(spi_t *obj); spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout); spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, - uint8_t *rx_buffer, uint16_t len, uint32_t Timeout); + uint8_t *rx_buffer, uint16_t len, uint32_t Timeout, bool skipReceive); uint32_t spi_getClkFreq(spi_t *obj); #ifdef __cplusplus