This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2511/CC1111 USB issues

Other Parts Discussed in Thread: CC2511

Hello,

I'm developing a widget that uses the CC2511 and is based very heavily on the rs232_to_usb example.   My application software uses the USB framework pretty much as-is, but I've stripped out most of the radio configuration and communications code for that example as it was very hard for me to follow and overkill for the application.  

I have a few questions that I'm hoping someone from TI can step in and answer.

 

I've run into some failure modes with the USB device that I'm not sure how to detect and remedy, my attempts thus far have not really panned out.

I believe some of the problems could be with the interaction with  the windows usb-serial driver (searching the internet yields a number of very negative references to usbser.sys).

 

Main Problem:

After some fault condition, perhaps the windows driver not emptying the buffer quickly enough (IN packets through usbser.sys), the device communication goes "mute".   Data makes it to the CC2511/CC1111, but there is no data seen by the PC even though I know the device is trying to respond.   As with the RS232 example, i wait for (USBCSIL & USBCSIL_INPKT_RDY) to return false before trying to send.     I'm debugging this particular problem and I notice that in the failed state, the actual write  usbfwWriteFifo(&USBF4,c)  call takes much less time, and thus far I have not been able to recover from this condition.

I can also force this condition to happen by having the device continuously send data to the host while the host is reading the data out through a terminal program and then the port is closed.  

So here are the questions:

1) Anyone else seen this?

 

2) I experimented with trying to flush the fifo but that did not work at the time.  Is there any way to reset the endpoint fifo, or the controller, or to signal to windows to flush its buffer?

 

3) I realize that the application probably needs to revert to an inactive state when it has not been communicated with in a while -- what is the best way to do this?  Right now the device will not be recognized by windows on a soft reboot or when connected to a powered USB hub.   On some machines I've seen the device prevent the machine from booting.  

 

Thanks for any help you can provide!

Lance

 

  • I have recently worked with another developer on a very similar, if not the same, issue on the CC1111.  I will share some of my notes with you and hope that this will drive towards resolution of the issue you are facing.
    I do want to confirm a couple of things with you regarding the code base you are referencing.  My comments are based on the RFUSB library (SWRC088) for the CC2511/CC1111.

    Please let me know if this is also what you are using.  Also, please indicate which example in the .\embedded_sw directory you are referencing, if any.

     

    As background information, the RFUSB library configures the USB Endpoint FIFOs (both IN and OUT) by parsing the USB descriptors, which are used by the host to interrogate the device and understand what it requires, and sets up the Endpoint FIFOs based on this information.  For example, if Endpoint 4 is used, the CC1111 supports a FIFO size of 256 bytes, BUT if the Endpoint 4 descriptor indicates to the host that it is a 64-byte BULK enpoint, the RFUSB library layer will configure the actual hardware logic for a FIFO size of 64-bytes.  This is independent of single-buffering or double-buffering of the FIFO from the device perspective.

    With that background, the RFUSB library itself does not handle segmentation of packets sent by the device to the PC (the USB IN direction) to write data into the IN FIFO.  Your application layer, which the Embedded Software examples emulate, will need to handle the RFUSB EVENT for IN Endpoints and continue writing N bytes into the IN FIFO, where N is <= the size of the endpoint.  A USB transaction will stop when the transfer size is zero or < the maximum size of the endpoint.

    When the USB peripheral empties the IN endpoint FIFO, it will generate an interrupt.  This interrupt is handled by the RFUSB layer in usbIrqHandler() (found int .\source\usb_interrupt.c).  To use the example of Endpoint 4, this interrupt handler will effectively set the USBIRQ_EVENT_EP4IN event flag in the usbirqData.eventMask.

    However, in .\embedded_sw\App_Ex\rs232_to_usb\rs232_to_usb_dongle\source\main.c, I don't see the main() function checking for this event.  Rather it is simply looking at the USBCSIL_INPKT_RDY flag as you mentioned in your post and acting on it.  It would seem to me, the IN Endpoint handling should be similar to how the OUT Endpoint handling is done.

     

     

  • Brandon,

    Thank yo so much for sharing these notes so far.

     

    Yes  I am using the .\embedded_sw\App_Ex\rs232_to_usb\rs232_to_usb_dongle\source\main.c  as the basis for the application.  I stripped much of the radio handling out and replaced with my own and as for USB the only thing I've modified is the vendor ID  and strings in the descriptor.


    I need to reread your note more carefully but I have a few quick comments.


    When I read over the device descriptor stuff along with the documentaiton I too found some discrepancies and was a little confused about that -- especially when it came to double buffering.

    Maybe you are onto something there.

    More background:

    -> because of uncertainty in the size of the buffer, I make sure I write no more than 32 bytes at  a time into the fifo before triggering the send; that seemed ultra conservative and typically works OK until I get into this mode.

     

    Lance

  • lance_RFdude.com said:

    Yes  I am using the .\embedded_sw\App_Ex\rs232_to_usb\rs232_to_usb_dongle\source\main.c  as the basis for the application.  I stripped much of the radio handling out and replaced with my own and as for USB the only thing I've modified is the vendor ID  and strings in the descriptor.

    Thank you for the confirmation.  This will ensure I am looking at the same sources.

     

    lance_RFdude.com said:

    When I read over the device descriptor stuff along with the documentaiton I too found some discrepancies and was a little confused about that -- especially when it came to double buffering.

    Maybe you are onto something there.

    I didn't mean to indicate that double buffering is an issue.  What I do want to stress however, is that the RFUSB Library will initialize the USBMAXI to the size indicated in the descriptor.  Therefore, when you do write to the FIFO, you need to write in <= USBMAXI chunks.

     

    lance_RFdude.com said:

    -> because of uncertainty in the size of the buffer, I make sure I write no more than 32 bytes at  a time into the fifo before triggering the send; that seemed ultra conservative and typically works OK until I get into this mode.

    I believe this will always be the case. 

     

    My prior investigations did not include the rs232_to_usb example specifically, so I need to review the code there to see if it is implementing similar functionality to what I had advised the other developer.

  • Brandon,


    Thanks again.  I didn't think that you implied the double buffering was a problem, but in my couple of passes through the documentation and comparing the descriptor info, it was unclear to me whether a factor of two needed to be there or not -- so I was being ultra conservative and trying to send small chunks of data each pass through my loop.

     

    The loop should execute ~5 times for each 32 bytes of data that need to make it to the host, so it should be rare unless my writes timeout many times in a row for me to actually need to send more than that at once.

     

    Lance

  • Does this issue happen all of the time, meaning none of the packets of data come through?
    Or every now and again?

    I reread you original post, but perhaps I missed it.

    Are you doing any handling of the USBIRQ_EVENT_EP4IN event?

    Also, it seems the rs232_to_usb_dongle\source\main.c uses the USB_MAX_PACKET_SIZE variable to determine the size of the buffer to write into the IN Endpoint FIFO.  Is this value the same as the descriptor you are using?

  • BrandonAzbell said:

    Does this issue happen all of the time, meaning none of the packets of data come through?
    Or every now and again?

    It is quite rare unless I force the condition by closing the port on the host PC.  It has not been clear to me how the device can even know the status of the host and how it can detect changes after it is initially configured .  

    I left a number of these of these running overnight and some of them timed out, but many of them locked up in this mode.  If they time out (fail to get access to write the FIFO in my sequence detailed below), I can typically start communications again. If not, the unit needs to be pulled an reinserted.

    I reread you original post, but perhaps I missed it.

    Are you doing any handling of the USBIRQ_EVENT_EP4IN event?

    No I am not -- was this done in the example?  -- do you mean just clear this "event"?

    Also, it seems the rs232_to_usb_dongle\source\main.c uses the USB_MAX_PACKET_SIZE variable to determine the size of the buffer to write into the IN Endpoint FIFO.  Is this value the same as the descriptor you are using?

    I am writing the fifo directly using the following pseudo sequence

    1) on EP4, wait for USBCSIL_INPKT_RDY to clear (I have a timeout loop that goes for a few ms before giving up this pass)

    2) loop through and typically send only a few bytes, but if I've previously timed out it may be more... but neve rmore than a hard coded value of 32 bytes in my code.  write using;  usbfwWriteFifo(&USBF4,1,&cTemp);   


    3) after I've written into the fifo using the above  I do this:  USBCSIL |= USBCSIL_INPKT_RDY;   

     

    Again, most of these low level USB things were copied from the application example assuming that it was complete.  I may still have made mistakes, but it is fairly minimal.

     

    Thanks again

     

  • Just to clarify a few things...

     

    1) I'm doing all of the USB processing that I can in the main loop, not using DMA or interrupts that I've setup (whatever the usb framework does is left intact as far as I know).

     

    2) generally this application works well, but I find that over time this fault condition will be encountered -- it is detecting it and recovering from it that is giving me the most trouble.

     

    thanks again for the help

    Lance

  • So I'm not sure I've gotten to the root of the problem or gotten many of my questions answered, but I do think I found a pretty significant flaw in the rs232 example.

     

    the code goes through the trouble of disabling interrupts before changing the USBINDEX (endpoint index) register, but typically reenables them before actually polling the USB register.  So in theory another interrupt that dealt with the USB framework could change the index and the polling could apply to another endpoint.

     

    Once I undid this mess things seem to be doing much better.   I would still like to hear more of an official critique of the rs-232 dongle code, because it seems that a number of people are basing their work on it.

     

    Thanks  (and I'll be out of town tomorrow and not back to the forum for a while if the discussion kicks up).

     

    Lance 

  • lance_RFdude.com said:

    So I'm not sure I've gotten to the root of the problem or gotten many of my questions answered, but I do think I found a pretty significant flaw in the rs232 example.

    the code goes through the trouble of disabling interrupts before changing the USBINDEX (endpoint index) register, but typically reenables them before actually polling the USB register.  So in theory another interrupt that dealt with the USB framework could change the index and the polling could apply to another endpoint.

    I would agree that re-enabling interrupts prior to accessing the USB endpoint registers indexed by USBINDEX would open things up for problems.

     

    lance_RFdude.com said:

    Once I undid this mess things seem to be doing much better.   I would still like to hear more of an official critique of the rs-232 dongle code, because it seems that a number of people are basing their work on it.

    This is good news.  Has your further testing resulted positively?

  • yes, everything is much better now.

     

    I still would like to know more about how the device can detect and recover from communications issues with the host.

     

    Lance

  • When the communication issues were observed, did you see any interrupt flags being set that may clue into an error condition, or disconnection from the host?

  • once the issues manifested, everything was unstable as I recall. 

    Clearly if my theory held, the chip was reading status from the wrong endpoint registers due to interrupts firing in-between when USBINDEX was set and the particular USB registers were read.

    It has been solid since I ensured interrupts were disabled through the polling period.


    When will the revised eamples be out?  I saw mention of this on one of the other forums that is newer -- I imagine this will cause many others issues.

    Lance

     

     

  • I'm so glad this was here - or I would have spent weeks trying to figure this out instead of just a week.  I found two problems in my code

    1) What caught me is that using bulk endpoints, the packet length is limited to 64 bytes, per the USB spec.  However, the chip datasheet states the following in section 12.16.6.5:

    A bulk transfer longer than the maximum
    packet size is performed by splitting the
    transfer into a number of data packets of
    maximum size followed by a smaller data
    packet containing the remaining bytes. If the
    transfer length is a multiple of the maximum
    packet size, a zero length data packet is sent
    last. This means that a packet with a size less
    than the maximum packet size denotes the
    end of the transfer.

    I incorrectly assumed that this was handled in hardware – In my defense, the wording is a bit ambiguous.

    and 2) I also ended up having problems with the interrupt structure, as already described in this post.  Once I fixed the interrupts data started flowing freely.

    It would be nice to have some clarification in the datasheet that #1 needs to be handled by software.  It would have saved me at least one weeks worth of time... probably more, and my final product would have been better.