From e48e4fde1b8ae7f55f273432d4bb51489a7951f6 Mon Sep 17 00:00:00 2001 From: Dr M Date: Mon, 23 Sep 2024 08:49:42 -0400 Subject: [PATCH 1/2] Patch, SPI.transfer16() Implement SPI.transfer16() as a true 16 bit transfer Signed-off-by: Dr M --- libraries/SPI/src/SPI.cpp | 22 +++++++++- libraries/SPI/src/SPI.h | 1 + libraries/SPI/src/utility/spi_com.c | 64 ++++++++++++++++++++++++++++- libraries/SPI/src/utility/spi_com.h | 1 + 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 2c6e798b33..3b364c0bc7 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -176,7 +176,7 @@ uint8_t SPIClass::transfer(uint8_t data, bool skipReceive) * Optional, default: SPI_TRANSMITRECEIVE. * @return bytes received from the slave in 16 bits format. */ -uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive) +uint16_t SPIClass::transfer16_obsoleted(uint16_t data, bool skipReceive) { uint16_t tmp; @@ -194,6 +194,26 @@ uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive) return data; } +uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive) +{ + uint16_t tmp; + uint16_t out; + + if (_spiSettings.bitOrder) { + tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); + data = tmp; + } + + spi_transfer16(&_spi, (uint16_t *)&data, (!skipReceive) ? (uint16_t *)&out : NULL); + + if (_spiSettings.bitOrder) { + tmp = ((out & 0xff00) >> 8) | ((out & 0xff) << 8); + out = tmp; + } + + return out; +} + /** * @brief Transfer several bytes. Only one buffer used to send and receive data. * begin() or beginTransaction() must be called at least once before. diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 1105991dc7..6aa814b2bb 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -136,6 +136,7 @@ class SPIClass { */ uint8_t transfer(uint8_t data, bool skipReceive = SPI_TRANSMITRECEIVE); uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE); + uint16_t transfer16_obsoleted(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE); void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE); /* Expand SPI API diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 6bfd683a53..0d32a8316a 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -30,8 +30,7 @@ uint32_t spi_getClkFreqInst(SPI_TypeDef *spi_inst) { uint32_t spi_freq = SystemCoreClock; if (spi_inst != NP) { -#if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx) || \ - defined(STM32U0xx) +#if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx) /* SPIx source CLK is PCKL1 */ spi_freq = HAL_RCC_GetPCLK1Freq(); #else @@ -544,6 +543,67 @@ spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buff return ret; } +spi_status_e spi_transfer16(spi_t *obj, const uint16_t *tx_buffer, uint16_t *rx_buffer) +{ + spi_status_e ret = SPI_OK; + uint32_t tickstart; + SPI_TypeDef *_SPI = obj->handle.Instance; + uint16_t *tx_buf = (uint16_t *)tx_buffer; + + tickstart = HAL_GetTick(); + +#if defined(SPI_CR2_TSIZE) + /* Start transfer */ + LL_SPI_SetTransferSize(_SPI, 1); + LL_SPI_Enable(_SPI); + LL_SPI_StartMasterTransfer(_SPI); +#endif + +#if defined(SPI_SR_TXP) + while (!LL_SPI_IsActiveFlag_TXP(_SPI)); +#else + while (!LL_SPI_IsActiveFlag_TXE(_SPI)); +#endif + + LL_SPI_TransmitData16(_SPI, tx_buf ? *tx_buf : 0XFF); + +#if defined(SPI_SR_RXP) + while (!LL_SPI_IsActiveFlag_RXP(_SPI)); +#else + while (!LL_SPI_IsActiveFlag_RXNE(_SPI)); +#endif + + if (rx_buffer) { + *rx_buffer = LL_SPI_ReceiveData16(_SPI); + } else { + LL_SPI_ReceiveData16(_SPI); + } + + if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) && + (HAL_GetTick() - tickstart >= SPI_TRANSFER_TIMEOUT)) { + ret = SPI_TIMEOUT; + } + +#if defined(SPI_IFCR_EOTC) + // Add a delay before disabling SPI otherwise last-bit/last-clock may be truncated + // See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294 + // Computed delay is half SPI clock + delayMicroseconds(obj->disable_delay); + + /* Close transfer */ + /* Clear flags */ + LL_SPI_ClearFlag_EOT(_SPI); + LL_SPI_ClearFlag_TXTF(_SPI); + /* Disable SPI peripheral */ + LL_SPI_Disable(_SPI); +#else + /* Wait for end of transfer */ + while (LL_SPI_IsActiveFlag_BSY(_SPI)); +#endif + + return ret; +} + #ifdef __cplusplus } #endif diff --git a/libraries/SPI/src/utility/spi_com.h b/libraries/SPI/src/utility/spi_com.h index 4d145ff7fd..4132c7f5f1 100644 --- a/libraries/SPI/src/utility/spi_com.h +++ b/libraries/SPI/src/utility/spi_com.h @@ -85,6 +85,7 @@ typedef enum { void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb); void spi_deinit(spi_t *obj); spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len); +spi_status_e spi_transfer16(spi_t *obj, const uint16_t *tx_buffer, uint16_t *rx_buffer); uint32_t spi_getClkFreq(spi_t *obj); #ifdef __cplusplus From 6b9619fc6bf02a245e306cbfd46739caf027ff5d Mon Sep 17 00:00:00 2001 From: Dr M Date: Tue, 24 Sep 2024 08:55:38 -0400 Subject: [PATCH 2/2] Update spi_com.c Correction, defined(STM32U0xx) Signed-off-by: Dr M --- libraries/SPI/src/utility/spi_com.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 0d32a8316a..615020b67d 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -30,7 +30,8 @@ uint32_t spi_getClkFreqInst(SPI_TypeDef *spi_inst) { uint32_t spi_freq = SystemCoreClock; if (spi_inst != NP) { -#if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx) +#if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx) || \ + defined(STM32U0xx) /* SPIx source CLK is PCKL1 */ spi_freq = HAL_RCC_GetPCLK1Freq(); #else