CDC ACM USBD Binary Mode

Hello All,

Thanks in advance for looking at this.

We have implemented the CDC / ADC / USBD code into our product. It is fast, stable, and seems to be working well...

... until we want to send 8 bit (as opposed to 7 bit ASCII) data. The lower levels are escaping the data consistently.

This is confirmed either in our product hardware, or using the 52833 dev kit or the 52840 dev kit; conclusion is that this is not a hardware problem, this appears to be a firmware problem in the SDK USB protocol stack.

This behavior is consistent between the nRF5_SDK_17.0.2_d674dde SDK and the nRF5_SDK_17.1.0_ddde560 SDK.

Enabling UTF8 (specifically APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED ) in the config file results in no change to the data being transferred; it is still being "escaped".

What are we missing? Is there some other configuration in the config file that we should be using?

Please advise.

Regards,

David

  • Can you please upload some code snippets on how you are doing the 8 bit transfers instead of 7-bit? I can try to replicate it at my end to be able to debug. Which SDK version are you using?

  • Hello Susheel,

    Thank you in advance for your attention.

    Apologies for the delay in responding, have been running various experiments to get additional information on this.
    Same ASCII 'escaping' behavior is observed with either nRF5_SDK_17.0.2 or nRF5_SDK_17.1.0.

    Here is a code fragment which works perfectly:

    // Generic 7 bit ASCII:
    snprintf(usbTxBuf, sizeof(usbTxBuf),
             "HDT, %05d\r\n", ourTxCount);
    // Invoke transport:
    nrfRetVal = app_usbd_cdc_acm_write(&_actAppCdcAcm,   // Instance
                                       usbTxBuf,         // Tx buffer
                                       ourTxCount);      // Number of bytes to Tx

    This generates "escaping":

    // UTF-8 / ISO 8859 / mixed bit 7 set / clear transmission:
    snprintf(usbTxBuf, sizeof(usbTxBuf),
             "HDT, 'À' 'Ä' 'Ö' 'ä' 'ö': %05d\r\n", ourTxCount);
    // Invoke transport:
    nrfRetVal = app_usbd_cdc_acm_write(&_actAppCdcAcm,   // Instance
                                       usbTxBuf,         // Tx buffer
                                       ourTxCount);      // Number of bytes to Tx

    Always nominal return values from app_usbd_cdc_acm_write().

    We have confirmed this with binary dumps on the host... this 'escaping' is happening in the Nordic USB stack.

    After further experimentation, any character with bit 7 set high is escaped with:

          0xC3 (original char & 0xBF), so "Ä", 0xC4, becomes: 0xC3 0x84

    However, sending a pure binary such as:

    // Brute force fill in buffer:
          usbTxBuf[0] = 0x01;
          usbTxBuf[1] = 0x02;
          usbTxBuf[2] = 0x03;
          usbTxBuf[3] = 0x81;
          usbTxBuf[4] = 0x82;
          usbTxBuf[5] = 0x83;
          usbTxBuf[6] = 0x84;
          usbTxBuf[7] = 0x84;
          usbTxBuf[8] = 0x00;
          usbTxBuf[9] = 0x0D;
    // Invoke transport:
    nrfRetVal = app_usbd_cdc_acm_write(&_actAppCdcAcm,   // Instance
                                       usbTxBuf,         // Tx buffer
                                       10);      // Number of bytes to Tx

    results in correct, unescaped transmission from Nordic system and correct reception on the USB host.

    Even mixed transmission such as:

    // Brute force fill in buffer:
          usbTxBuf[0] = 'A';
          usbTxBuf[1] = 'B';
          usbTxBuf[2] = 0x02;
          usbTxBuf[3] = 0x03;
          usbTxBuf[4] = 0x82;
          usbTxBuf[5] = 0x83;
          usbTxBuf[6] = 0xC3;
          usbTxBuf[7] = 0xC3;
          usbTxBuf[8] = 0x00;
          usbTxBuf[9] = 0x0D;
    // Invoke transport:
    nrfRetVal = app_usbd_cdc_acm_write(&_actAppCdcAcm,   // Instance
                                       usbTxBuf,         // Tx buffer
                                       10);      // Number of bytes to Tx

    results in unescaped transmission and correct reception on the USB host.

    It appears that something in the stack is trying to figure out if this is ASCII or not... is this somehow expected behavior?

    If we send pure binary via this API, are there any likelihood that this would be escaped?

    Regards, David

  • Hi,

    Sorry for late reply, I am able to reproduce what you tested. It could be a side affect of the use of macros to copy the buffer data into driver storage but I can see the same thing that you see.

    Have you have a workaround in mind? If not, I can try to contact the usb driver experts to shed some light on how to have a workaround for this.

  • Thank you for your response, and good that you are able to reproduce this.

    Outstanding / unanswered questions from my previous post here:

    It appears that something in the stack is trying to figure out if this is ASCII or not... is this somehow expected behavior?

    If we send pure binary via this API, are there any likelihood that this would be escaped?

    Perhaps you could pose these questions to the USB driver experts and let us know the answers?

  • There is nothiing in the USB drivers that I can see which differentiates the data between ASCII and non-ASCII. Could it be the snprintf that is doing this? Can you please do a quick test to manually write the buffer with characters with bit 7 set to high and not use snprintf?

Related