Skip to content

Commit

Permalink
esp32/machine_hw_spi: Fix large HW SPI transfers by splitting them up.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MrSurly authored and dpgeorge committed Dec 18, 2017
1 parent 5455bf7 commit 9123c8d
Showing 1 changed file with 37 additions and 17 deletions.
54 changes: 37 additions & 17 deletions ports/esp32/machine_hw_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
}

Expand Down

0 comments on commit 9123c8d

Please sign in to comment.