This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI/USB will drop large multiple of packets in a row. Can't keep up with 1 Mbps on nrf52840 dk?

Hi,

I'm using an nrf52840 dk to query another device over spi and then pipe the response back USB to a host PC. Ideally, we're piping data at 1 Mbps (which should be very much doable for USB) and for a little bit, it will work perfectly. Then randomly we'll miss 4 kB worth of packets. After plotting the data stream it's become apparent that it's quite bad. We consistently lose at least a 3rd of our packets. Furthermore, the lost data is lost in chunks. Here's an example of a 'noisy' sine wave that we sent through the serial link.

I don't believe it's an issue with the spi because I've tied an oscope to the spi pins and observed perfect spi packets being transmitted at a rate of 1 Mbps (but I could only observe maybe 20 packets at a time and didn't decode them so ...). Given that we're missing consecutive packets, and it seems to happen more or less regularly, I think this might have to do with a USB overhead issue.  

Is there something I'm missing about USB? Is there an ideal packet size that I should send over the USB at a given moment? I've played with the following settings but they've seem to make no difference:

  • APP_USBD_CONFIG_SOF_HANDLING_MODE (tried both normal and compress queue)
  • APP_USBD_CONFIG_EVENT_QUEUE_SIZE (Tried setting this to the max, 64, in case I was trying to send packets too frequently and they needed a larger queue)

I'm pretty new with USB communication so any help would be amazing! 

EDIT: I've started saving the data to a buffer on the dev kit and reading it all out at once (ideally this decouples the SPI and USB). While I'm missing significantly fewer packets, I am still missing a few. Now I'm getting 75%-85% of all my packets. So I guess this means there is some function that's interrupting the SPI's interrupt, possibly? I've tried bumping the SPI interrupts priority but it doesn't seem to have changed anything. I'm completely out of ideas so any pointers would be a huge help.

Thanks,

Ryan

  • USB is 12MHz no way USB can be slower than SPI.  The problem is more likely in your SPI code.  Have you validate that you got all the data through SPI before sending to USB ? Are you also sure the SPI sender actually sent all the data correctly.  Validate each step of the way in order to find where the issue is.

  • Yea I agree that there seems to be an issue with the SPI code. I tried writing all the SPI data to a buffer and then reading that out over USB after the fact (in order to decouple the two) and I still had missing packets. I rarely missed a single packet, rather large chunks of adjacent packets were missed so it seems to me that there is some process interrupting the SPI.

    But even that seems odd since the SPI should mostly be handled by hardware.

    Do you have any suggestions for testing the SPI out on its own? Using the NRF Log is a no go because it will sometimes cause issues with the SPI's chip select driver and limit data throughput to <1Mbps.

  • Hi,

     

    Is the SPIM or SPIS running on the nRF?

    If logging is an issue, you could use RTT instead of UART as the logger backend (see sdk_config.h::NRF_LOG_BACKEND_RTT_ENABLED and clearing NRF_LOG_BACKEND_UART_ENABLED) to see if something is caught and printed.

     

    How large are the USB packets and how often do you send? How does your device enumerate, HID, CDC, libusb, winusb?

    Note that HID is limited to 64 byte per 1 ms frame.

     

    Kind regards,

    Håkon

  • The SPIM is running on the nRF.

    I can try with RTT to see if the chip select issue continues (you're right in that I was using UART debugging) - and if not, I can look into debugging with that.

    I send 520 bits every 500 us (so throughput is slightly higher than 1 Mbps). The software will send/receive 520 bits over SPI, then after a flag (spi_xfr_complete flag) is tripped in the main() body. After this flag is tripped, the data is processed (minorly) and then sent via USB to the host pc.

    I've built this off the CDC example so it enumerates as CDC with whatever settings were in the usb_CDC example. Does CDC have a similar limit?

    Thank you for the help!

  • Hi Ryan,

     

    ryerye120 said:
    Does CDC have a similar limit?

    No, that should be able to push more data through the link.

     

    ryerye120 said:
    I send 520 bits every 500 ms

     65 bytes will trigger a 64 byte + 1 byte transaction over USB, as your EP size is 64. Sending that every 500 milliseconds should be plenty time, or do you mean every 500 us?

    Which SDK version are you using? What else than SPIM and USBD is running in your application? Do you have any BLE links active?

     

    Kind regards,

    Håkon 

Related