Skip to content

Commit 59efe26

Browse files
committed
feat(spi): add transfer api with tx/rx buffer
Fixes #2205 Signed-off-by: Frederic Pillon <frederic.pillon@st.com>
1 parent 0b9c63d commit 59efe26

File tree

4 files changed

+40
-12
lines changed

4 files changed

+40
-12
lines changed

libraries/SPI/src/SPI.cpp

+26-4
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void SPIClass::setClockDivider(uint8_t divider)
163163
*/
164164
uint8_t SPIClass::transfer(uint8_t data, bool skipReceive)
165165
{
166-
spi_transfer(&_spi, &data, sizeof(uint8_t), skipReceive);
166+
spi_transfer(&_spi, &data, (!skipReceive) ? &data : NULL, sizeof(uint8_t));
167167
return data;
168168
}
169169

@@ -184,7 +184,7 @@ uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive)
184184
tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
185185
data = tmp;
186186
}
187-
spi_transfer(&_spi, (uint8_t *)&data, sizeof(uint16_t), skipReceive);
187+
spi_transfer(&_spi, (uint8_t *)&data, (!skipReceive) ? (uint8_t *)&data : NULL, sizeof(uint16_t));
188188

189189
if (_spiSettings.bitOrder) {
190190
tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
@@ -206,11 +206,33 @@ uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive)
206206
*/
207207
void SPIClass::transfer(void *buf, size_t count, bool skipReceive)
208208
{
209-
if ((count != 0) && (buf != NULL)) {
210-
spi_transfer(&_spi, ((uint8_t *)buf), count, skipReceive);
209+
spi_transfer(&_spi, (uint8_t *)buf, (!skipReceive) ? (uint8_t *)buf : NULL, count);
210+
211+
}
212+
213+
/**
214+
* @brief Transfer several bytes. One constant buffer used to send and
215+
* one to receive data.
216+
* begin() or beginTransaction() must be called at least once before.
217+
* @param tx_buf: array of Tx bytes that is filled by the user before starting
218+
* the SPI transfer. If NULL, default dummy 0xFF bytes will be
219+
* clocked out.
220+
* @param rx_buf: array of Rx bytes that will be filled by the slave during
221+
* the SPI transfer. If NULL, the received data will be discarded.
222+
* @param count: number of bytes to send/receive.
223+
*/
224+
void SPIClass::transfer(const void *tx_buf, void *rx_buf, size_t count)
225+
{
226+
if (tx_buf) {
227+
spi_transfer(&_spi, ((const uint8_t *)tx_buf), ((uint8_t *)rx_buf), count);
228+
} else {
229+
uint8_t dummy_buf[count];
230+
memset(dummy_buf, 0XFF, count);
231+
spi_transfer(&_spi, dummy_buf, ((uint8_t *)rx_buf), count);
211232
}
212233
}
213234

235+
214236
/**
215237
* @brief Not implemented.
216238
*/

libraries/SPI/src/SPI.h

+5
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ class SPIClass {
138138
uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
139139
void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE);
140140

141+
/* Expand SPI API
142+
* https://github.com/arduino/ArduinoCore-API/discussions/189
143+
*/
144+
void transfer(const void *tx_buf, void *rx_buf, size_t count);
145+
141146
/* These methods are deprecated and kept for compatibility.
142147
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
143148
*/

libraries/SPI/src/utility/spi_com.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -500,17 +500,18 @@ void spi_deinit(spi_t *obj)
500500
* @brief This function is implemented by user to send/receive data over
501501
* SPI interface
502502
* @param obj : pointer to spi_t structure
503-
* @param buffer : tx data to send before reception
503+
* @param tx_buffer : tx data to send before reception
504+
* @param rx_buffer : rx data to receive if not numm
504505
* @param len : length in byte of the data to send and receive
505-
* @param skipReceive: skip receiving data after transmit or not
506506
* @retval status of the send operation (0) in case of error
507507
*/
508-
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, bool skipReceive)
508+
spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer,
509+
uint16_t len)
509510
{
510511
spi_status_e ret = SPI_OK;
511512
uint32_t tickstart, size = len;
512513
SPI_TypeDef *_SPI = obj->handle.Instance;
513-
uint8_t *tx_buffer = buffer;
514+
uint8_t *tx_buf = (uint8_t *)tx_buffer;
514515

515516
if (len == 0) {
516517
ret = SPI_ERROR;
@@ -530,15 +531,15 @@ spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, bool skipRe
530531
#else
531532
while (!LL_SPI_IsActiveFlag_TXE(_SPI));
532533
#endif
533-
LL_SPI_TransmitData8(_SPI, *tx_buffer++);
534+
LL_SPI_TransmitData8(_SPI, *tx_buf++);
534535

535-
if (!skipReceive) {
536+
if (rx_buffer) {
536537
#if defined(SPI_SR_RXP)
537538
while (!LL_SPI_IsActiveFlag_RXP(_SPI));
538539
#else
539540
while (!LL_SPI_IsActiveFlag_RXNE(_SPI));
540541
#endif
541-
*buffer++ = LL_SPI_ReceiveData8(_SPI);
542+
*rx_buffer++ = LL_SPI_ReceiveData8(_SPI);
542543
}
543544
if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) &&
544545
(HAL_GetTick() - tickstart >= SPI_TRANSFER_TIMEOUT)) {

libraries/SPI/src/utility/spi_com.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ typedef enum {
110110
/* Exported functions ------------------------------------------------------- */
111111
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb);
112112
void spi_deinit(spi_t *obj);
113-
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, bool skipReceive);
113+
spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len);
114114
uint32_t spi_getClkFreq(spi_t *obj);
115115

116116
#ifdef __cplusplus

0 commit comments

Comments
 (0)