diff --git a/ports/espressif/common-hal/busio/SPI.c b/ports/espressif/common-hal/busio/SPI.c index 0b894fa215b6..da9170a5b099 100644 --- a/ports/espressif/common-hal/busio/SPI.c +++ b/ports/espressif/common-hal/busio/SPI.c @@ -33,6 +33,7 @@ #include "driver/spi_common_internal.h" #define SPI_MAX_DMA_BITS (SPI_MAX_DMA_LEN * 8) +#define MAX_SPI_TRANSACTIONS 10 static bool spi_never_reset[SOC_SPI_PERIPH_NUM]; static spi_device_handle_t spi_handle[SOC_SPI_PERIPH_NUM]; @@ -59,7 +60,7 @@ static void set_spi_config(busio_spi_obj_t *self, .clock_speed_hz = baudrate, .mode = phase | (polarity << 1), .spics_io_num = -1, // No CS pin - .queue_size = 1, + .queue_size = MAX_SPI_TRANSACTIONS, .pre_cb = NULL }; esp_err_t result = spi_bus_add_device(self->host_id, &device_config, &spi_handle[self->host_id]); @@ -213,47 +214,61 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, mp_raise_ValueError(translate("No MISO Pin")); } - spi_transaction_t transaction = { 0 }; + spi_transaction_t transactions[MAX_SPI_TRANSACTIONS]; // Round to nearest whole set of bits int bits_to_send = len * 8 / self->bits * self->bits; if (len <= 4) { + memset(&transactions[0], 0, sizeof(spi_transaction_t)); if (data_out != NULL) { - memcpy(&transaction.tx_data, data_out, len); + memcpy(&transactions[0].tx_data, data_out, len); } - transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - transaction.length = bits_to_send; - spi_device_transmit(spi_handle[self->host_id], &transaction); + transactions[0].flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + transactions[0].length = bits_to_send; + spi_device_transmit(spi_handle[self->host_id], &transactions[0]); if (data_in != NULL) { - memcpy(data_in, &transaction.rx_data, len); + memcpy(data_in, &transactions[0].rx_data, len); } } else { int offset = 0; int bits_remaining = bits_to_send; + int cur_trans = 0; while (bits_remaining && !mp_hal_is_interrupted()) { - memset(&transaction, 0, sizeof(transaction)); - transaction.length = - bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining; + cur_trans = 0; + while (bits_remaining && (cur_trans != MAX_SPI_TRANSACTIONS)) { + memset(&transactions[cur_trans], 0, sizeof(spi_transaction_t)); - if (data_out != NULL) { - transaction.tx_buffer = data_out + offset; - } - if (data_in != NULL) { - transaction.rx_buffer = data_in + offset; - } + transactions[cur_trans].length = + bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining; - spi_device_transmit(spi_handle[self->host_id], &transaction); - bits_remaining -= transaction.length; + if (data_out != NULL) { + transactions[cur_trans].tx_buffer = data_out + offset; + } + if (data_in != NULL) { + transactions[cur_trans].rx_buffer = data_in + offset; + } - // doesn't need ceil(); loop ends when bits_remaining is 0 - offset += transaction.length / 8; + bits_remaining -= transactions[cur_trans].length; + + // doesn't need ceil(); loop ends when bits_remaining is 0 + offset += transactions[cur_trans].length / 8; + cur_trans++; + } - RUN_BACKGROUND_TASKS; + for (int i = 0; i < cur_trans; i++) { + spi_device_queue_trans(spi_handle[self->host_id], &transactions[i], portMAX_DELAY); + } + + spi_transaction_t *rtrans; + for (int x = 0; x < cur_trans; x++) { + RUN_BACKGROUND_TASKS; + spi_device_get_trans_result(spi_handle[self->host_id], &rtrans, portMAX_DELAY); + } } } return true;