Skip to content

Commit

Permalink
feat(spi): add transfer api with tx/rx buffer
Browse files Browse the repository at this point in the history
Fixes #2205

Signed-off-by: Frederic Pillon <[email protected]>
  • Loading branch information
fpistm committed Nov 24, 2023
1 parent 0b9c63d commit 59efe26
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
30 changes: 26 additions & 4 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ void SPIClass::setClockDivider(uint8_t divider)
*/
uint8_t SPIClass::transfer(uint8_t data, bool skipReceive)
{
spi_transfer(&_spi, &data, sizeof(uint8_t), skipReceive);
spi_transfer(&_spi, &data, (!skipReceive) ? &data : NULL, sizeof(uint8_t));
return data;
}

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

if (_spiSettings.bitOrder) {
tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
Expand All @@ -206,11 +206,33 @@ uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive)
*/
void SPIClass::transfer(void *buf, size_t count, bool skipReceive)
{
if ((count != 0) && (buf != NULL)) {
spi_transfer(&_spi, ((uint8_t *)buf), count, skipReceive);
spi_transfer(&_spi, (uint8_t *)buf, (!skipReceive) ? (uint8_t *)buf : NULL, count);

}

/**
* @brief Transfer several bytes. One constant buffer used to send and
* one to receive data.
* begin() or beginTransaction() must be called at least once before.
* @param tx_buf: array of Tx bytes that is filled by the user before starting
* the SPI transfer. If NULL, default dummy 0xFF bytes will be
* clocked out.
* @param rx_buf: array of Rx bytes that will be filled by the slave during
* the SPI transfer. If NULL, the received data will be discarded.
* @param count: number of bytes to send/receive.
*/
void SPIClass::transfer(const void *tx_buf, void *rx_buf, size_t count)
{
if (tx_buf) {
spi_transfer(&_spi, ((const uint8_t *)tx_buf), ((uint8_t *)rx_buf), count);
} else {
uint8_t dummy_buf[count];
memset(dummy_buf, 0XFF, count);
spi_transfer(&_spi, dummy_buf, ((uint8_t *)rx_buf), count);
}
}


/**
* @brief Not implemented.
*/
Expand Down
5 changes: 5 additions & 0 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ class SPIClass {
uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE);

/* Expand SPI API
* https://github.com/arduino/ArduinoCore-API/discussions/189
*/
void transfer(const void *tx_buf, void *rx_buf, size_t count);

/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/
Expand Down
15 changes: 8 additions & 7 deletions libraries/SPI/src/utility/spi_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,17 +500,18 @@ void spi_deinit(spi_t *obj)
* @brief This function is implemented by user to send/receive data over
* SPI interface
* @param obj : pointer to spi_t structure
* @param buffer : tx data to send before reception
* @param tx_buffer : tx data to send before reception
* @param rx_buffer : rx data to receive if not numm
* @param len : length in byte of the data to send and receive
* @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 *buffer, uint16_t len, bool skipReceive)
spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer,
uint16_t len)
{
spi_status_e ret = SPI_OK;
uint32_t tickstart, size = len;
SPI_TypeDef *_SPI = obj->handle.Instance;
uint8_t *tx_buffer = buffer;
uint8_t *tx_buf = (uint8_t *)tx_buffer;

if (len == 0) {
ret = SPI_ERROR;
Expand All @@ -530,15 +531,15 @@ spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, bool skipRe
#else
while (!LL_SPI_IsActiveFlag_TXE(_SPI));
#endif
LL_SPI_TransmitData8(_SPI, *tx_buffer++);
LL_SPI_TransmitData8(_SPI, *tx_buf++);

if (!skipReceive) {
if (rx_buffer) {
#if defined(SPI_SR_RXP)
while (!LL_SPI_IsActiveFlag_RXP(_SPI));
#else
while (!LL_SPI_IsActiveFlag_RXNE(_SPI));
#endif
*buffer++ = LL_SPI_ReceiveData8(_SPI);
*rx_buffer++ = LL_SPI_ReceiveData8(_SPI);
}
if ((SPI_TRANSFER_TIMEOUT != HAL_MAX_DELAY) &&
(HAL_GetTick() - tickstart >= SPI_TRANSFER_TIMEOUT)) {
Expand Down
2 changes: 1 addition & 1 deletion libraries/SPI/src/utility/spi_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ typedef enum {
/* Exported functions ------------------------------------------------------- */
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, uint8_t *buffer, uint16_t len, bool skipReceive);
spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len);
uint32_t spi_getClkFreq(spi_t *obj);

#ifdef __cplusplus
Expand Down

0 comments on commit 59efe26

Please sign in to comment.