ESB High frequency transmission

Hi:

I have the following hardware structure:

FPGA < -- SPI -- > NRF5340 (TX)  -- !    (ESB)   ! -- NRF5340 (RX) < -- USB -- > PC

Due to the nature of my application, I need to send a lot of data through the ESB with high frequency. (250 bytes of data are transferred every 2ms.)

As a result, I've achieved what I needed. But the transfer was erratic, even when I put the two DK boards close together:

-->  I control IO level flipping at SPI receive, ESB send, and ESB receive, respectively.

--> The results show that the ESB receives no more than 30s. And I need to reset PTX to have a high probability to work again.

Here is my project with the code configuration:

PTX and PRX:

CONFIG_ESB_NEVER_DISABLE_TX=y
CONFIG_ESB_TX_FIFO_SIZE=64
CONFIG_ESB_RX_FIFO_SIZE=64

ret..delay = 150, ret...count = 1, tx_mode = manual_start, fast_ramp_up = true, auto_ack = true, crc = off

PTX:

spis_handler:

write_payload, toggle pin 1, set spis buffer

main:

start_tx, toggle pin 2

PRX:

esb_handler:

read_payload, toggle pin 3

The core code is as above, omitting some other code, but I don't think it will affect the solution of the problem, of course, if you need to provide other content or source code is ok.

For the transfer of data, I allow a small amount of data packet loss.

Thanks !

Parents
  • Hi 

    Sending 250 bytes every 2ms should be achievable if you use 2Mbps bitrate, but it won't leave you a lot of overhead for retransmissions etc. 

    It seems you are trying to send a lot of packets back to back, and then you are manually sending an ACK after a certain number of packets? 

    Have you tried to simply send 250 byte payloads every 2ms with retransmit disabled to see if the performance is better? Then you should have time for an ACK after each packet, but you won't have time for any retransmits. 

    --> The results show that the ESB receives no more than 30s. And I need to reset PTX to have a high probability to work again.

    You mean reception stops completely after 30 seconds?

    Best regards
    Torbjørn

  • Hi 

    Have you tried to implement a simple test where you just send dummy data from a timer, to double check if the problem is related to the handover of data between the SPI interface and the ESB library? 

    1) Looking through your code I found a potential issue in the SPI_Thread(..) thread function:

    if (likely(!k_fifo_is_empty(&SPI_DATA_FIFO)))
    {
        rx_data = k_fifo_get(&SPI_DATA_FIFO, K_FOREVER);
        if (rx_data)
        {
            memcpy(tx_payload.data, rx_data->data, rx_data->data_size);
            tx_payload.length = rx_data->data_size;
    
            esb_write_payload(&tx_payload);
            
            gpio_pin_toggle_dt(&(test_gpios[1]));
        }
    }

    If I read this code correctly it will call k_fifo_is_empty(..) repeatedly as long as the FIFO is empty, without yielding the thread, which will block other threads in the system. You should be able to simply remove this if check, and just call k_fifo_get(&SPI_DATA_FIFO, K_FOREVER). In that case the thread will yield as long as there is no data in the FIFO, and only be resumed once the data is there. 

    2) Did you consider running the SPI coms from the appcore, so you didn't need to bit bang the SPI master? 

    3) Why is CRC disabled? 

    4) What kind of hardware are you using? Is this standard devkits or custom hardware?

    Best regards
    Torbjørn

Reply
  • Hi 

    Have you tried to implement a simple test where you just send dummy data from a timer, to double check if the problem is related to the handover of data between the SPI interface and the ESB library? 

    1) Looking through your code I found a potential issue in the SPI_Thread(..) thread function:

    if (likely(!k_fifo_is_empty(&SPI_DATA_FIFO)))
    {
        rx_data = k_fifo_get(&SPI_DATA_FIFO, K_FOREVER);
        if (rx_data)
        {
            memcpy(tx_payload.data, rx_data->data, rx_data->data_size);
            tx_payload.length = rx_data->data_size;
    
            esb_write_payload(&tx_payload);
            
            gpio_pin_toggle_dt(&(test_gpios[1]));
        }
    }

    If I read this code correctly it will call k_fifo_is_empty(..) repeatedly as long as the FIFO is empty, without yielding the thread, which will block other threads in the system. You should be able to simply remove this if check, and just call k_fifo_get(&SPI_DATA_FIFO, K_FOREVER). In that case the thread will yield as long as there is no data in the FIFO, and only be resumed once the data is there. 

    2) Did you consider running the SPI coms from the appcore, so you didn't need to bit bang the SPI master? 

    3) Why is CRC disabled? 

    4) What kind of hardware are you using? Is this standard devkits or custom hardware?

    Best regards
    Torbjørn

Children
No Data
Related