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
1 changed files with 36 additions and 21 deletions

View File

@ -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;
if (data_out != NULL) {
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);
bits_remaining -= transaction.length;
for (int i = 0; i < cur_trans; i++) {
spi_device_queue_trans(spi_handle[self->host_id], &transactions[i], portMAX_DELAY);
}
// doesn't need ceil(); loop ends when bits_remaining is 0
offset += transaction.length / 8;
RUN_BACKGROUND_TASKS;
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;