summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ports/esp32/machine_hw_spi.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c
index 2792216cc0..5b59f2431c 100644
--- a/ports/esp32/machine_hw_spi.c
+++ b/ports/esp32/machine_hw_spi.c
@@ -217,7 +217,7 @@ STATIC void machine_hw_spi_init_internal(
.clock_speed_hz = self->baudrate,
.mode = self->phase | (self->polarity << 1),
.spics_io_num = -1, // No CS pin
- .queue_size = 1,
+ .queue_size = 2,
.flags = self->firstbit == MICROPY_PY_MACHINE_SPI_LSB ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0,
.pre_cb = NULL
};
@@ -273,6 +273,17 @@ STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) {
}
}
+STATIC mp_uint_t gcd(mp_uint_t x, mp_uint_t y) {
+ while (x != y) {
+ if (x > y) {
+ x -= y;
+ } else {
+ y -= x;
+ }
+ }
+ return x;
+}
+
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);
@@ -281,13 +292,16 @@ STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const ui
return;
}
- struct spi_transaction_t transaction = { 0 };
-
// Round to nearest whole set of bits
int bits_to_send = len * 8 / self->bits * self->bits;
+ if (!bits_to_send) {
+ mp_raise_ValueError(MP_ERROR_TEXT("buffer too short"));
+ }
if (len <= 4) {
+ spi_transaction_t transaction = { 0 };
+
if (src != NULL) {
memcpy(&transaction.tx_data, src, len);
}
@@ -302,26 +316,42 @@ STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const ui
} else {
int offset = 0;
int bits_remaining = bits_to_send;
+ int optimum_word_size = 8 * self->bits / gcd(8, self->bits);
+ int max_transaction_bits = MP_HW_SPI_MAX_XFER_BITS / optimum_word_size * optimum_word_size;
+ spi_transaction_t *transaction, *result, transactions[2];
+ int i = 0;
+
+ spi_device_acquire_bus(self->spi, portMAX_DELAY);
while (bits_remaining) {
- memset(&transaction, 0, sizeof(transaction));
+ transaction = transactions + i++ % 2;
+ memset(transaction, 0, sizeof(spi_transaction_t));
- transaction.length =
- bits_remaining > MP_HW_SPI_MAX_XFER_BITS ? MP_HW_SPI_MAX_XFER_BITS : bits_remaining;
+ transaction->length =
+ bits_remaining > max_transaction_bits ? max_transaction_bits : bits_remaining;
if (src != NULL) {
- transaction.tx_buffer = src + offset;
+ transaction->tx_buffer = src + offset;
}
if (dest != NULL) {
- transaction.rx_buffer = dest + offset;
+ transaction->rx_buffer = dest + offset;
}
- spi_device_transmit(self->spi, &transaction);
- bits_remaining -= transaction.length;
+ spi_device_queue_trans(self->spi, transaction, portMAX_DELAY);
+ bits_remaining -= transaction->length;
+
+ if (offset > 0) {
+ // wait for previously queued transaction
+ spi_device_get_trans_result(self->spi, &result, portMAX_DELAY);
+ }
// doesn't need ceil(); loop ends when bits_remaining is 0
- offset += transaction.length / 8;
+ offset += transaction->length / 8;
}
+
+ // wait for last transaction
+ spi_device_get_trans_result(self->spi, &result, portMAX_DELAY);
+ spi_device_release_bus(self->spi);
}
}