summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+ }
}
}