Skip to content
Snippets Groups Projects
Commit 9123c8d9 authored by Eric Poulsen's avatar Eric Poulsen Committed by Damien George
Browse files

esp32/machine_hw_spi: Fix large HW SPI transfers by splitting them up.

Breaks up HW SPI transfers into maximum chunks of 32736 bits (4092 bytes),
because this is the maximum that the underlying ESP IDF will accept.
parent 5455bf79
No related branches found
No related tags found
No related merge requests found
......@@ -36,6 +36,9 @@
#include "driver/spi_master.h"
#define MP_HW_SPI_MAX_XFER_BYTES (4092)
#define MP_HW_SPI_MAX_XFER_BITS (MP_HW_SPI_MAX_XFER_BYTES * 8) // Has to be an even multiple of 8
typedef struct _machine_hw_spi_obj_t {
mp_obj_base_t base;
spi_host_device_t host;
......@@ -227,35 +230,52 @@ STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) {
STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
int bits_to_send = len * self->bits;
bool shortMsg = len <= 4;
if (self->state == MACHINE_HW_SPI_STATE_DEINIT) {
mp_raise_msg(&mp_type_OSError, "transfer on deinitialized SPI");
return;
}
struct spi_transaction_t transaction = {
.flags = 0,
.length = bits_to_send,
.tx_buffer = NULL,
.rx_buffer = NULL,
};
struct spi_transaction_t transaction = { 0 };
// Round to nearest whole set of bits
int bits_to_send = len * 8 / self->bits * self->bits;
if (shortMsg) {
if (len <= 4) {
if (src != NULL) {
memcpy(&transaction.tx_data, src, len);
}
transaction.flags |= (SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA);
transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
transaction.length = bits_to_send;
spi_device_transmit(self->spi, &transaction);
if (dest != NULL) {
memcpy(dest, &transaction.rx_data, len);
}
} else {
transaction.tx_buffer = src;
transaction.rx_buffer = dest;
}
int offset = 0;
int bits_remaining = bits_to_send;
while (bits_remaining) {
memset(&transaction, 0, sizeof(transaction));
spi_device_transmit(self->spi, &transaction);
transaction.length =
bits_remaining > MP_HW_SPI_MAX_XFER_BITS ? MP_HW_SPI_MAX_XFER_BITS : bits_remaining;
if (shortMsg && dest != NULL) {
memcpy(dest, &transaction.rx_data, len);
if (src != NULL) {
transaction.tx_buffer = src + offset;
}
if (dest != NULL) {
transaction.rx_buffer = dest + offset;
}
spi_device_transmit(self->spi, &transaction);
bits_remaining -= transaction.length;
// doesn't need ceil(); loop ends when bits_remaining is 0
offset += transaction.length / 8;
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment