diff --git a/components/driver/include/driver/spi_slave.h b/components/driver/include/driver/spi_slave.h index 047ab41392..ed12cb62df 100644 --- a/components/driver/include/driver/spi_slave.h +++ b/components/driver/include/driver/spi_slave.h @@ -53,6 +53,7 @@ typedef struct { */ struct spi_slave_transaction_t { size_t length; ///< Total data length, in bits + size_t trans_len; ///< Transaction data length, in bits const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase void *rx_buffer; ///< Pointer to receive buffer, or NULL for no MISO phase void *user; ///< User-defined variable. Can be used to store eg transaction ID. diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index 7600b4e45c..305bea6ab0 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -289,12 +289,20 @@ static void IRAM_ATTR spi_intr(void *arg) if (!host->hw->slave.trans_done) return; if (host->cur_trans) { + //when data of cur_trans->length are all sent, the slv_rdata_bit + //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise + //the length sent. + host->cur_trans->trans_len = host->hw->slv_rd_bit.slv_rdata_bit; + if ( host->cur_trans->trans_len == host->cur_trans->length - 1 ) { + host->cur_trans->trans_len++; + } + if (host->dma_chan == 0 && host->cur_trans->rx_buffer) { //Copy result out uint32_t *data = host->cur_trans->rx_buffer; - for (int x = 0; x < host->cur_trans->length; x += 32) { + for (int x = 0; x < host->cur_trans->trans_len; x += 32) { uint32_t word; - int len = host->cur_trans->length - x; + int len = host->cur_trans->trans_len - x; if (len > 32) len = 32; word = host->hw->data_buf[(x / 32)]; memcpy(&data[x / 32], &word, (len + 7) / 8); diff --git a/docs/api-reference/peripherals/spi_slave.rst b/docs/api-reference/peripherals/spi_slave.rst index 76f44c4942..727338ffa1 100644 --- a/docs/api-reference/peripherals/spi_slave.rst +++ b/docs/api-reference/peripherals/spi_slave.rst @@ -74,10 +74,12 @@ may decide to use DMA for transfers, so these buffers should be allocated in DMA The amount of data written to the buffers is limited by the ``length`` member of the transaction structure: the driver will never read/write more data than indicated there. The ``length`` cannot define the actual -length of the SPI transaction; this is determined by the master as it drives the clock and CS lines. In -case the length of the transmission is larger than the buffer length, only the start of the transmission -will be sent and received. In case the transmission length is shorter than the buffer length, only data up -to the length of the buffer will be exchanged. +length of the SPI transaction; this is determined by the master as it drives the clock and CS lines. The actual length +transferred can be read from the ``trans_len`` member of the ``spi_slave_transaction_t`` structure after transaction. +In case the length of the transmission is larger than the buffer length, only the start of the transmission +will be sent and received, and the ``trans_len`` is set to ``length`` instead of the actual length. It's recommended to +set ``length`` longer than the maximum length expected if the ``trans_len`` is required. In case the transmission +length is shorter than the buffer length, only data up to the length of the buffer will be exchanged. Warning: Due to a design peculiarity in the ESP32, if the amount of bytes sent by the master or the length of the transmission queues in the slave driver, in bytes, is not both larger than eight and dividable by