Atmel USB envía el paquete STALL después de 1 minuto

1

Después de un minuto (inactivo o activo), la pila USB de mi Atmel SAM4E-EK envía un paquete USB STALL que básicamente elimina la conexión USB con el host. ¿Cómo puedo evitar que esto suceda?

El host es un Windows 7 y el estado del paquete USB recibido en el host (PC) es 0xC0000004 desde la dirección del punto final 0x84 (UDI_CDC_DATA_EP_IN_0) y uno con el mismo estado desde 0x83 (UDI_CDC_COMM_EP_0). El dispositivo USB es un dispositivo compuesto USB con CDC y MSC habilitados.

Atmel tiene un proyecto de ejemplo que también es un dispositivo compuesto USB con MSC + CDC y este también se agota después de un par de minutos (3-4 minutos).

    
pregunta Entalpi

2 respuestas

1

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.

    
respondido por el Spektre
1

Eventos como NAK, ACK, STALL ... son emitidos por SIE (Serial Interface Engine) del controlador USB. Por lo tanto, no podrá encontrarlo en el código fuente o en el manual de referencia técnica del dispositivo.

    
respondido por el Prji

Lea otras preguntas en las etiquetas