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

Help understanding USB CDC ACM read flow

Hey all, I'm trying very hard to understand how UART over USB works by following through the USB CDC ACM example in SDK 17.0.2 on the nRF52840DK, but I'm still new to this so I'm missing something.  I see that on APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN, we so an initial app_usbd_cdc_acm_read which presumably writes to SIZE.EPOUT register like it shows in the datasheet (Figure 202 on page 540 in v1.2) then sets up the EasyDMA transfer with the buffer your pass to it and kicks off the STARTEPOUT task?  Then, I guess, we get the APP_USBD_CDC_ACM_USER_EVT_RX_DONE event on the ENDEPOUT event register and load up a new EasyDMA buffer and kick off another STARTEPOUT task?

I ask all this because I am not seeing the data I expect to see.  First, I have an array of 16 ArrayLists, each with a 64 byte buffer (same size as USB buffer).  I modified READ_SIZE from 1 to 64. After each app_usbd_cdc_acm_read I put an app_usbd_cdc_acm_write (the only change to cdc_acm_user_ev_handler) to echo back to the terminal.  When I send more than 64 bytes at a time, I see that all of the data appears in the buffer when I look in the debugger, but not in my terminal echo.  Instead I consistently seem to be missing the first 148 bytes in the echo when I send something like 660 bytes at a time.  Since I'm not able to echo those first bytes, I'm also not able to process with them, which is the thing that has me stymied.  Here is the pertinent code:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define ARRAY_LIST_SIZE 16
#define READ_SIZE 64
typedef struct
{
uint8_t buffer[READ_SIZE];
} ArrayList_t;
static ArrayList_t m_rx_buffer[ARRAY_LIST_SIZE];
static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];
static uint16_t m_send_flag = 0;
static uint16_t m_cdc_buffer_idx = 0;
...
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
app_usbd_cdc_acm_user_event_t event)
{
app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
switch (event)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

What I was hoping to do was send a file with a standard header of size ~600 bytes, grab 64 bytes at a time, and look for a few particular fields - one being the first few bytes as a validation and another that could appear at anywhere from 100 to 600 bytes from the start of the file.  That field contains the size of the remainder of the file that I would then write to some flash.  The same protocol also will be used to communicate with the host in 64byte messages.