I got similar problems with ATMEL AVR32 USB. I derived my USB class from the CDC example and AVR-SoftwareFramework-2.3.1
and I found out that they got a bug (most likely on the HW somewhere on the chip). In the example they call flush
for every NB_MS_BEFORE_FLUSH
-th SoF
(Start of Frame) which in some cases (mostly when no communication is done for some time) will freeze Is_device_enumerated()
call which is done in the same CDC task function (in next iteration) to the point the chip stop executing instructions,interrupts etc until HW reset is done.
My original derived code was like this (sorry I do not have the original CDC example code anymore):
#define NB_MS_BEFORE_FLUSH 100
void usb_device::flush() { bool zlp=false; if(!Is_usb_write_enabled(TX_EP)) zlp=true; Usb_ack_in_ready_send(TX_EP); b_tx_new = true; if(zlp==true) { while(!Is_usb_write_enabled(TX_EP)); Usb_ack_in_ready_send(TX_EP); } }
void device_cdc_task(void)
{
if (!Is_device_enumerated()) { _reset_fifos=true; return; }
if (_reset_fifos)
{
_reset_fifos=false;
usb.fifo_send.reset();
usb.fifo_recv.reset();
Usb_reset_endpoint_fifo_access(RX_EP);
Usb_reset_endpoint_fifo_access(TX_EP);
}
if (sof_cnt>=NB_MS_BEFORE_FLUSH) // Flush buffer in Timeout
{
sof_cnt=0;
usb.flush();
}
if (usb.b_send) usb.send(); else usb.recv();
usb.b_send=!usb.b_send;
}
And after getting to the bottom of this and fixing the issue the working code looks like this:
void device_cdc_task(void)
{
if (!Is_device_enumerated()) { _reset_fifos=true; return; }
if (_reset_fifos)
{
_reset_fifos=false;
usb.fifo_send.reset();
usb.fifo_recv.reset();
Usb_reset_endpoint_fifo_access(RX_EP);
Usb_reset_endpoint_fifo_access(TX_EP);
sof_cnt=NB_MS_BEFORE_FLUSH;
}
if (sof_cnt>=NB_MS_BEFORE_FLUSH) // Flush buffer in Timeout
{
Usb_ack_in_ready_send(TX_EP);
b_tx_new=true;
sof_cnt=0;
}
if (usb.b_send) usb.send(); else usb.recv();
usb.b_send=!usb.b_send;
}
Where USB is my class doing specific job. Also this occasionally send stall but will not freeze the MCU to death. Also this solves the issue that after restart of host PC you need to reset or reconnect the USB.
However I am still suspicious that the USB example contains another bug possibly just wrongly set timeouts or missing acknowledge somewhere because during longer periods of inactivity pipe0 sometimes freezes.