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
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: