summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Poulsen <eric@zyxod.com>2017-11-28 18:48:30 -0800
committerDamien George <damien.p.george@gmail.com>2017-12-18 15:44:35 +1100
commit9123c8d9460017b8c8dc4a38d9a26968eacaa4cb (patch)
treebdbffd94b21c09676be1380b95b23ed5e156cb8e
parent5455bf79c568fa56b2ad05d28d10575d987030b4 (diff)
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.
-rw-r--r--ports/esp32/machine_hw_spi.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c
index 437b620f5..54790bf8d 100644
--- a/ports/esp32/machine_hw_spi.c
+++ b/ports/esp32/machine_hw_spi.c
@@ -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;
+ }
}
}