AnsweredAssumed Answered

USB Stack, bare metal, v4.03, CDC sending FIFO length data to host?

Question asked by giggler g on Feb 27, 2013
Latest reply on Mar 5, 2013 by Monica Arvizu



When sending data to host a full FIFO from event USB_APP_DATA_RECEIVED


DataLength=16;     // RX size from host


if (USB_Class_CDC_Interface_DIC_Send_Data(USB_COMPOSITE_CONTROLLER_ID,(uint8_t*)&Data[0],DataLength)!=USB_OK) {

     for(;;);     // catch in debugger


else {





The IN transaction is not complete without sending a zero length packet (ZLP).  This is as I understand it normal behaviour.


So in my transmit completion event I have:



else if (event_type==USB_APP_SEND_COMPLETE) {

     if (Sent) {

          if (!ZLP) {

               // ZLP on TX fifo, completion of last IN transaction

               if (USB_Class_CDC_Interface_DIC_Send_Data(USB_COMPOSITE_CONTROLLER_ID,NULL,0)!=USB_OK) {

                    for(;;);     // catch in debugger



          }else {

               // ZLP on RX fifo, completion of last OUT transaction, allowing host to begin again sending







Here when we get completion of full FIFO sent, we check if we have to ZLP send.  Do it and only then do we free up the receiver.  Like the demo code, it's half duplex because by not sending ZLP on RX FIFO no more data comes in from host.


Thing is, it's flaky, sometimes works, sometimes does not and hangs.  I have not checking status of sending USB_Class_CDC_Interface_DIC_Recv_Data, should I?


Also it is not clear, do we get USB_APP_SEND_COMPLETE events on ZLP sending on both IN and OUT transactions since both are in a send, albeit of zero data in the data stage of transaction or in the receive the ack - I think?


I am trying to make the USB interface completely interrupt driven, but the biggest issue I have is that the callback to receive data is from the USB ISR as:


static CLASS_APP_CALLBACK_STRUCT callback = {

     .composite_class_callback =CDCApp_Class_Callback,

     .vendor_req_callback =NULL,

     .param_callback = CDCApp_PSTN_Notify_Callback,

     .param_specific_callback =NULL,




if we get a completion event, we send some more data but ... If one of the USB_Send... function calls come back as BUSY, I can't do anything, that results in no completion event because we could not initiate a send and the thing hangs.  I think also that is why you are doing things in half duplex mode, trying to ensure resources are free to use.  That is fine for a demo but not representative of any real world application.


I cannot use MQX because it does not support composite devices, I cannot block because of legacy code in our application connecting to hardware on PCB so calling it from main loop is not possible.


I have to say, I've used Atmel's free stack which is also what you could call bare metal for a number of years and have never had the amount of trouble I'm having with Freescale's implementation.