Merge pull request #7686 from gamblor21/esp_family_spi_speed_increase

ESP32 Family: Add multiple transctions to SPI for improved efficency
This commit is contained in:
Scott Shawcroft 2023-03-09 10:01:02 -08:00 committed by GitHub
commit fcc4299b92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -33,6 +33,7 @@
#include "driver/spi_common_internal.h" #include "driver/spi_common_internal.h"
#define SPI_MAX_DMA_BITS (SPI_MAX_DMA_LEN * 8) #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 bool spi_never_reset[SOC_SPI_PERIPH_NUM];
static spi_device_handle_t spi_handle[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, .clock_speed_hz = baudrate,
.mode = phase | (polarity << 1), .mode = phase | (polarity << 1),
.spics_io_num = -1, // No CS pin .spics_io_num = -1, // No CS pin
.queue_size = 1, .queue_size = MAX_SPI_TRANSACTIONS,
.pre_cb = NULL .pre_cb = NULL
}; };
esp_err_t result = spi_bus_add_device(self->host_id, &device_config, &spi_handle[self->host_id]); 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")); 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 // Round to nearest whole set of bits
int bits_to_send = len * 8 / self->bits * self->bits; int bits_to_send = len * 8 / self->bits * self->bits;
if (len <= 4) { if (len <= 4) {
memset(&transactions[0], 0, sizeof(spi_transaction_t));
if (data_out != NULL) { 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; transactions[0].flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
transaction.length = bits_to_send; transactions[0].length = bits_to_send;
spi_device_transmit(spi_handle[self->host_id], &transaction); spi_device_transmit(spi_handle[self->host_id], &transactions[0]);
if (data_in != NULL) { if (data_in != NULL) {
memcpy(data_in, &transaction.rx_data, len); memcpy(data_in, &transactions[0].rx_data, len);
} }
} else { } else {
int offset = 0; int offset = 0;
int bits_remaining = bits_to_send; int bits_remaining = bits_to_send;
int cur_trans = 0;
while (bits_remaining && !mp_hal_is_interrupted()) { while (bits_remaining && !mp_hal_is_interrupted()) {
memset(&transaction, 0, sizeof(transaction));
transaction.length = cur_trans = 0;
bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining; while (bits_remaining && (cur_trans != MAX_SPI_TRANSACTIONS)) {
memset(&transactions[cur_trans], 0, sizeof(spi_transaction_t));
if (data_out != NULL) { transactions[cur_trans].length =
transaction.tx_buffer = data_out + offset; bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining;
}
if (data_in != NULL) { if (data_out != NULL) {
transaction.rx_buffer = data_in + offset; transactions[cur_trans].tx_buffer = data_out + offset;
}
if (data_in != NULL) {
transactions[cur_trans].rx_buffer = data_in + offset;
}
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++;
} }
spi_device_transmit(spi_handle[self->host_id], &transaction); for (int i = 0; i < cur_trans; i++) {
bits_remaining -= transaction.length; spi_device_queue_trans(spi_handle[self->host_id], &transactions[i], portMAX_DELAY);
}
// doesn't need ceil(); loop ends when bits_remaining is 0 spi_transaction_t *rtrans;
offset += transaction.length / 8; for (int x = 0; x < cur_trans; x++) {
RUN_BACKGROUND_TASKS;
RUN_BACKGROUND_TASKS; spi_device_get_trans_result(spi_handle[self->host_id], &rtrans, portMAX_DELAY);
}
} }
} }
return true; return true;