SPI HALFDUPLEX looses last bytes
Posted: Thu Dec 05, 2019 2:30 pm
I struggle with a SPI driver: my devices need some setup time between CS and CLK setup. Using command phase (command_bits>0), cs_ena_pretrans is avaliable only in HALFDUPLEX.
HALFDUPLEX seems to loose some last received bytes if transaction before tx anything:
When there is no transmitting part (N=0) received log looks alike:
Received: 11 11 11 11 11 11 11 11
When N = 1: Received: 11 11 11 11 11 11 11 00
When N = 2: Received: 11 11 11 11 11 11 00 00
When N = 3: Received: 11 11 11 11 11 00 00 00
When N = 4: Received: 11 11 11 11 cc 6c fb 3f
I checked using a logical analyzer: Regardless of the value of N, the received block is always correct (0x11 .. only).
Why last N bytes are loosed? Why zeros or this strange block when N=4?
HALFDUPLEX seems to loose some last received bytes if transaction before tx anything:
Code: Select all
// initialize
spi_bus_config_t buscfg = {
.miso_io_num=PIN_NUM_SPI_MISO, .mosi_io_num=PIN_NUM_SPI_MOSI, .sclk_io_num=PIN_NUM_SPI_CLK,
.quadwp_io_num=-1, .quadhd_io_num=-1, .max_transfer_sz=1024
};
spi_device_interface_config_t devcfg = {
.spics_io_num=PIN_NUM_SPI_CS,
.clock_speed_hz=4000000, // 4MHz max
.mode=1, // SPI MODE 1
.command_bits=8, // 8-bit command length
.queue_size=1,
.cs_ena_pretrans = 1,
.flags = SPI_DEVICE_HALFDUPLEX
};
spi_bus_initialize(VSPI_HOST, &buscfg, 1 /*dma_chan - 0 no DMA*/);
ESP_ERROR_CHECK(spi_bus_add_device(VSPI_HOST, &devcfg, &spi));
// transmit
uint8_t N = 1; // ****** set N to 0, 1, 2, ...
if (N > 0) { // skip if N == 0
spi_transaction_t transaction;
memset(&transaction, 0, sizeof(transaction));
transaction.cmd = 0x81;
transaction.length = N*8;
transaction.flags = SPI_TRANS_USE_TXDATA;
transaction.tx_data[0] = 0x00;
transaction.tx_data[1] = 0x00;
transaction.tx_data[2] = 0x00;
transaction.tx_data[3] = 0x00;
assert(spi_device_polling_transmit(spi, &transaction) == ESP_OK);
ESP_LOGI(TAG, "Transmitted: %d bytes [%02x %02x %02x %02x]", N, transaction.tx_data[0], transaction.tx_data[1], transaction.tx_data[2], transaction.tx_data[3]);
}
// receive
char * buffer = heap_caps_malloc(8, MALLOC_CAP_DMA);
spi_transaction_t transaction;
memset(&transaction, 0, sizeof(transaction));
transaction.cmd = 0x01;
transaction.rx_buffer = buffer;
transaction.rxlength = 8 * 8;
transaction.length = transaction.rxlength;
assert(spi_device_polling_transmit(spi, &transaction) == ESP_OK);
ESP_LOGI(TAG, "Received: %02x %02x %02x %02x %02x %02x %02x %02x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
Received: 11 11 11 11 11 11 11 11
When N = 1: Received: 11 11 11 11 11 11 11 00
When N = 2: Received: 11 11 11 11 11 11 00 00
When N = 3: Received: 11 11 11 11 11 00 00 00
When N = 4: Received: 11 11 11 11 cc 6c fb 3f
I checked using a logical analyzer: Regardless of the value of N, the received block is always correct (0x11 .. only).
Why last N bytes are loosed? Why zeros or this strange block when N=4?