Tengo problemas similares con ATMEL AVR32 USB. Derivé mi clase USB del ejemplo de CDC y AVR-SoftwareFramework-2.3.1
y descubrí que tenían un error (muy probablemente en el HW en algún lugar del chip). En el ejemplo, llaman a flush
por cada NB_MS_BEFORE_FLUSH
-th SoF
(Inicio del marco) que en algunos casos (principalmente cuando no se realiza comunicación durante algún tiempo) congelará Is_device_enumerated()
llamada que se realiza de la misma manera La función de tarea CDC (en la siguiente iteración) hasta el punto en que el chip deja de ejecutar las instrucciones, se interrumpe, etc., hasta que se realiza el reinicio de HW.
Mi código derivado original era así (lo siento, ya no tengo el código de ejemplo de CDC original):
#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;
}
Y después de llegar al fondo de esto y solucionar el problema, el código de trabajo tiene este aspecto:
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;
}
Donde USB es mi clase haciendo un trabajo específico. También esto envía ocasionalmente el puesto, pero no congelará el MCU hasta la muerte. Además, esto resuelve el problema de que después de reiniciar la PC host necesitas reiniciar o volver a conectar el USB.
Sin embargo, sigo sospechando que el ejemplo de USB contenga otro error, posiblemente solo se hayan configurado los tiempos de espera o se haya perdido el reconocimiento en algún lugar, ya que durante períodos más largos de inactividad, la tubería 0 a veces se congela.