Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Burstiness of nRF 52840 Dev Kit USB CDC ADM code on Mac OS

We're using a combination of the ESB library/example code and the USB CDC ADM example code to transfer data from one 52840 dev kit to another system via a 2nd 52840 dev kit, via this setup:

  1. The transmitting 52840 send 128 bytes of data every millisecond via nrf_esb_write_payload().
  2. The receiving 52840 receives the 128 byte packet and immediately does an app_usbd_cdc_acm_write() with the data.  
  3. The system reads the data by polling /dev/tty.usbmodemxyz waiting for a complete 128 byte packet.  This is done via either a C++ program or a python3 script.

This all seems to work fine.  By looking at time stamps that are included in the data, we can tell the receive side is getting packets as expected once a millisecond.  But the problem is the reads of the data from the USB are bursty - the first read takes about 4 ms, then we'll get the next 3 or so almost immediately.  Then 4 ms to the next packet, then 3 to 4 more, etc.

I'm seeing this both with an C program (Xcode, Open Framework C++ app) and with python3 script.  I've tried various flags on the device open like O_NDELAY, but nothing I've done really changes the behavior.  Mac OS does not support the N_DIRECT flag.  

Is there a way to eliminate this bursty type of USB read with the CDC ADM example code?  Is there a better Nordic USB device/example code to use?  Any ideas are appreciated, it is important that the data arrive as consistently as is possible (given a non-real time OS like Mac OS).

nRF SDK 15, Mac OS 10.13.4, Xcode 9.3, Python 3.6.2

Thanks

Ed

Parents
  • Hi,

    Could you measure the interval between the APP_USBD_CDC_ACM_USER_EVT_TX_DONE events?

    Do you see the same beahvior if you split your 128 byte packets in two, i.e. use 64 bytes per packet for app_usbd_cdc_acm_write instead?

  • Already measured the interval.  In nrf_esb_event_handler, I recorded the time stamp of the received packet for the NRF_ESB_EVENT_RX_RECEIVED case of p_event->evt_id.  The time stamp is based on the 32 KHz clock.  I recorded the time stamp in the received data so I could look at it after the transfer was complete.  

    The time stamp always show exactly 32 counts between packets, +/- 1 count.  So I would say that the data across the air is coming in at exactly 1 KHz rate (i.e 1 ms between packets).  

    I will try different packet sizes later today.

    Ed

Reply
  • Already measured the interval.  In nrf_esb_event_handler, I recorded the time stamp of the received packet for the NRF_ESB_EVENT_RX_RECEIVED case of p_event->evt_id.  The time stamp is based on the 32 KHz clock.  I recorded the time stamp in the received data so I could look at it after the transfer was complete.  

    The time stamp always show exactly 32 counts between packets, +/- 1 count.  So I would say that the data across the air is coming in at exactly 1 KHz rate (i.e 1 ms between packets).  

    I will try different packet sizes later today.

    Ed

Children
  • A bit more data, but I'm not sure it makes any sense:

    If I split up the app_usbd_cdc_acm_write into 64 byte packets, I now get a burst of 8 USB reads that are about 7.5 ms apart (i.e. eight 64 byte packets in 7.5 ms, first one takes about 7 ms, the remaining 7 happen almost immediately).  I did this both by just splitting up the 128 packet coming across the air into two packets, and by simply xfering a 64 byte across the air (and not manipulating the local buffers at all)..  Both produced the same 7.5 burst cluster.

    Thinking this might be some sort of USB/CDC/ADM cache flush problem on a 512 byte boundary(4 x 128 = 8 x 64 = 512), I tried the opposite, by faking 256 byte writes by writing the 128 byte packet twice to app_usbd_cdc_acm_write.  I was expecting the burst to be around 2 ms, but this produces the same 4 ms burst as with a single 128 byte packet (???).

    Need to ponder this some more, I'll post any other data I come up with.  But this seems to indicate the problem is somehow getting data thru the USB/CDC/ADM to our app, and not related to the ESB transfer of data.

    Ed

Related