hideakitai / ESP32DMASPI

SPI library for ESP32 which use DMA buffer to send/receive transactions
MIT License
166 stars 36 forks source link

Data loss SPI communication (Master Slave) (ESP32) #24

Closed Nicrus86 closed 11 months ago

Nicrus86 commented 2 years ago

On ESP32, in Arduino framework with include ESP32DMASPIMaster.h and ESP32DMASPISlave.h (https://github.com/hideakitai/ESP32DMASPI), I tried an simple transmition from Master to Slave using a DMA buffer, but there are data lost in reception, regardless of the size of the data sent and the frequency of sending.

=== CODE MASTER SPI ==========

#include <ESP32DMASPIMaster.h>

ESP32DMASPI::Master master;

static const uint32_t BUFFER_SIZE = 12;
uint8_t* spi_master_tx_buf;
uint8_t* spi_master_rx_buf;
uint8_t num_msg = 0;

void set_buffer() {
    for (uint32_t i = 0; i < BUFFER_SIZE; i++) {
        spi_master_tx_buf[i] = i & 0xFF;
    }
    memset(spi_master_rx_buf, 0, BUFFER_SIZE);
}
void set_buffer_new(uint8_t num_msg) {
    for (uint32_t i = 0; i < BUFFER_SIZE; i++) {
        spi_master_tx_buf[i] = num_msg & 0xFF;
    }
    memset(spi_master_rx_buf, 0, BUFFER_SIZE);
} 

void setup() {

    // to use DMA buffer, use these methods to allocate buffer
    spi_master_tx_buf = master.allocDMABuffer(BUFFER_SIZE);
    spi_master_rx_buf = master.allocDMABuffer(BUFFER_SIZE);

    set_buffer();
    delay(5000);

    master.setDataMode(SPI_MODE0);           // default: SPI_MODE0
    master.setFrequency(4000000);            // default: 8MHz (too fast for bread board...)
    master.setMaxTransferSize(BUFFER_SIZE);  // default: 4092 bytes

    // begin() after setting
    master.begin();  // default: HSPI (CS: 15, CLK: 14, MOSI: 13, MISO: 12)
}

void loop() {
    // start and wait to complete transaction
    set_buffer_new(num_msg);

    master.transfer(spi_master_tx_buf, spi_master_rx_buf, BUFFER_SIZE);

    printf(" ====> Buffer TX: ");
    for (size_t i = 0; i < BUFFER_SIZE; ++i) {
        printf("%d ", spi_master_tx_buf[i]);
    }
    printf("\n");
    // show received data (if needed)
    printf("<== Buffer RX: ");
    for (size_t i = 0; i < BUFFER_SIZE; ++i) {
        printf("%d ", spi_master_rx_buf[i]);
    }
    printf("\n");
    num_msg++;
    delay(2000);
}

=== CODE SLAVE SPI ==========

#include <ESP32DMASPISlave.h>

ESP32DMASPI::Slave slave;

static const uint32_t BUFFER_SIZE = 12;
uint8_t* spi_slave_tx_buf;
uint8_t* spi_slave_rx_buf;

void setup() {

    // to use DMA buffer, use these methods to allocate buffer
    spi_slave_tx_buf = slave.allocDMABuffer(BUFFER_SIZE);
    spi_slave_rx_buf = slave.allocDMABuffer(BUFFER_SIZE);

    // set buffer data...

    // slave device configuration
    slave.setDataMode(SPI_MODE0);
    slave.setMaxTransferSize(BUFFER_SIZE);

    // begin() after setting
    slave.begin();  // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12 -> default
                    // VSPI (CS:  5, CLK: 18, MOSI: 23, MISO: 19)
}

void loop() {
    // if there is no transaction in queue, add transaction
    if (slave.remained() == 0) {
        slave.queue(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);
    }

    // if transaction has completed from master,
    // available() returns size of results of transaction,
    // and buffer is automatically updated

    while (slave.available()) {
      for (size_t i = 0; i < BUFFER_SIZE; ++i) {
        printf("%d ", spi_slave_rx_buf[i]);
        spi_slave_rx_buf[i] = 0;
      }
      printf("\n");
      // do something with received data: spi_slave_rx_buf

      slave.pop();
    }
}

[OUTPUT MASTER]

 ====> Buffer TX: 0 0 0 0 0 0 0 0 0 0 0 0 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 1 1 1 1 1 1 1 1 1 1 1 1 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 2 2 2 2 2 2 2 2 2 2 2 2 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 3 3 3 3 3 3 3 3 3 3 3 3 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 4 4 4 4 4 4 4 4 4 4 4 4 
<== Buffer RX: 125 214 149 0 0 0 0 0 0 0 0 0
 ====> Buffer TX: 5 5 5 5 5 5 5 5 5 5 5 5 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 6 6 6 6 6 6 6 6 6 6 6 6 
<== Buffer RX: 125 74 152 0 0 0 0 0 0 0 0 0
 ====> Buffer TX: 7 7 7 7 7 7 7 7 7 7 7 7 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 8 8 8 8 8 8 8 8 8 8 8 8 
<== Buffer RX: 126 180 0 0 0 0 0 0 0 0 0 0
 ====> Buffer TX: 9 9 9 9 9 9 9 9 9 9 9 9 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71
 ====> Buffer TX: 10 10 10 10 10 10 10 10 10 10 10 10 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71 
 ====> Buffer TX: 11 11 11 11 11 11 11 11 11 11 11 11 
<== Buffer RX: 126 164 0 0 0 0 0 0 0 0 0 0 
 ====> Buffer TX: 12 12 12 12 12 12 12 12 12 12 12 12 
<== Buffer RX: 125 214 165 77 91 190 253 103 40 103 146 71

In Master Code, I send a data with incremental integer on TX buffer dma. When the Master receive on RX buffer dma some '0', the Slave don't receive the current data on RX buffer dma.

[OUTPUT SLAVE]

0 0 0 0 0 0 0 0 0 0 0 0 
1 1 1 1 1 1 1 1 1 1 1 1 
2 2 2 2 2 2 2 2 2 2 2 2 
3 3 3 3 3 3 3 3 3 3 3 3 
0 0 0 0 0 0 0 0 0 0 0 0 
5 5 5 5 5 5 5 5 5 5 5 5 
0 0 0 0 0 0 0 0 0 0 0 0 
7 7 7 7 7 7 7 7 7 7 7 7 
0 0 0 0 0 0 0 0 0 0 0 0 
9 9 9 9 9 9 9 9 9 9 9 9 
10 10 10 10 10 10 10 10 10 10 10 10 
0 0 0 0 0 0 0 0 0 0 0 0 
12 12 12 12 12 12 12 12 12 12 12 12 
0 0 0 0 0 0 0 0 0 0 0 0 

In Slave code, I reset RX buffer dma (with '0') after print current data.

hideakitai commented 11 months ago

Have you tried master/slave examples first? Please try it with a smaller buffer size. If you don't need more than 64 bytes, use the default SPI library and ESP32SPISlave.

hideakitai commented 11 months ago

If you still need help with the problem, please feel free to reopen this issue.