Created
March 9, 2022 01:59
-
-
Save DavidJRobertson/3d077b55dce744c4c87ae6c49d0fc2cb to your computer and use it in GitHub Desktop.
Example of workaround for 9-bit SPI data corruption on ESP32-S3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "driver/spi_master.h" | |
#include "driver/gpio.h" | |
#include "sdkconfig.h" | |
#include "esp_log.h" | |
#ifdef CONFIG_IDF_TARGET_ESP32 | |
# define SPI_HOST HSPI_HOST | |
# define PIN_NUM_MISO 18 | |
# define PIN_NUM_MOSI 23 | |
# define PIN_NUM_CLK 19 | |
# define PIN_NUM_CS 13 | |
#elif CONFIG_IDF_TARGET_ESP32S3 | |
# define SPI_HOST SPI2_HOST | |
# define PIN_NUM_MISO 13 | |
# define PIN_NUM_MOSI 11 | |
# define PIN_NUM_CLK 12 | |
# define PIN_NUM_CS 10 | |
#endif | |
static const char TAG[] = "main"; | |
// Just send the data normally. | |
// This fails on ESP32-S3 if sizeBits is 8n+1 (last bit will be sent as 0 always) | |
void send_without_workaround(spi_device_handle_t device, uint8_t *buf, size_t sizeBits) { | |
spi_transaction_t transaction = { | |
.flags = 0, | |
.cmd = 0, | |
.addr = 0, | |
.length = sizeBits, | |
.rxlength = 0, | |
.tx_buffer = buf, | |
}; | |
ESP_ERROR_CHECK(spi_device_transmit(device, &transaction)); | |
} | |
void send_with_workaround(spi_device_handle_t device, uint8_t *buf, size_t sizeBits) { | |
if (sizeBits == 1) { | |
// Can't handle this case. You could bit-bang if really necessary. | |
assert(false); | |
} else if ((sizeBits % 8) != 1) { | |
// Normal case where workaround is not necessary. | |
send_without_workaround(device, buf, sizeBits); | |
} else { | |
// Need to work around bug on ESP32S3 by splitting transfer | |
ESP_ERROR_CHECK(spi_device_acquire_bus(device, portMAX_DELAY)); | |
// Send all but last 2 bits | |
spi_transaction_t transaction1 = { | |
.flags = SPI_TRANS_CS_KEEP_ACTIVE, | |
.cmd = 0, | |
.addr = 0, | |
.length = sizeBits - 2, | |
.rxlength = 0, | |
.tx_buffer = buf, | |
}; | |
ESP_ERROR_CHECK(spi_device_transmit(device, &transaction1)); | |
// Send last 2 bits | |
uint8_t lastBits = (buf[(sizeBits/8)-1] << 7) | (buf[sizeBits/8] >> 1); | |
spi_transaction_t transaction2 = { | |
.flags = 0, | |
.cmd = 0, | |
.addr = 0, | |
.length = 2, | |
.rxlength = 0, | |
.tx_buffer = &lastBits, | |
}; | |
ESP_ERROR_CHECK(spi_device_transmit(device, &transaction2)); | |
spi_device_release_bus(device); | |
} | |
} | |
void test_send(spi_device_handle_t device, uint8_t *buf, size_t sizeBits) { | |
send_without_workaround(device, buf, sizeBits); | |
send_with_workaround(device, buf, sizeBits); | |
vTaskDelay(1); | |
} | |
void app_main(void) | |
{ | |
esp_err_t ret; | |
// Initialise bus | |
ESP_LOGI(TAG, "Initializing bus SPI%d...", SPI_HOST+1); | |
spi_bus_config_t buscfg={ | |
.miso_io_num = PIN_NUM_MISO, | |
.mosi_io_num = PIN_NUM_MOSI, | |
.sclk_io_num = PIN_NUM_CLK, | |
.quadwp_io_num = -1, | |
.quadhd_io_num = -1, | |
.max_transfer_sz = 32, | |
}; | |
ret = spi_bus_initialize(SPI_HOST, &buscfg, SPI_DMA_CH_AUTO); | |
ESP_ERROR_CHECK(ret); | |
// Initialise device | |
ESP_LOGI(TAG, "Initializing device"); | |
spi_device_handle_t spiDevice; | |
spi_device_interface_config_t deviceConfig = { | |
.command_bits = 0, | |
.address_bits = 0, | |
.dummy_bits = 0, | |
.mode = 0, | |
.duty_cycle_pos = 0, | |
.cs_ena_pretrans = 0, | |
.cs_ena_posttrans = 0, | |
.clock_speed_hz = 100000, | |
.input_delay_ns = 0, | |
.spics_io_num = PIN_NUM_CS, | |
.flags = 0, | |
.queue_size = 200, | |
}; | |
ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST, &deviceConfig, &spiDevice)); | |
// Send test data | |
uint8_t testData[3] = {0xff, 0xff, 0xff}; | |
test_send(spiDevice, testData, 9); | |
test_send(spiDevice, testData, 17); | |
while (1) { | |
// Add your main loop handling code here. | |
vTaskDelay(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment