¿Con qué frecuencia debe ejecutarse la tarea USB HID USBDeviceTask() de Microchip?

Estoy integrando el módulo USB de ejemplo en mi aplicación existente y solo puedo hacer que funcione cuando deshabilito las interrupciones.

Estoy trabajando en el ejemplo de mla instalado en la ruta:

C:/microchip/mla/v2013_12_20/apps/usb/device/bootloaders/firmware/pic18fxxjxx

Detalles

  • Estoy implementando cada una de las funciones de devolución de llamada USB exactamente como se hizo en el ejemplo.
  • El reloj USB es de 48MHz
  • El reloj de la CPU (f_osc) es de 16MHz
  • pic18f25k50
  • una interrupción de alta prioridad para Timer1 marca cada 250us, todo lo demás sucede cada 1s
    • nunca te vayas a dormir, pero esto todavía parece reiniciarse

¿La pila USB del microchip no es segura para subprocesos?

¿No estoy ejecutando la tarea USB lo suficientemente rápido?

while (1)
{
  // Clear the watchdog timer
  ClrWdt();

  // Run the USB task faster than xxxHz?
  USBDeviceTasks();

  // Do stuff
}

// high-priority foreground loop takes ~5us
void high_priority interrupt HighPriorityTasks(void)
{
  // Do stuff quickly, clear sources of interrupts
}

// low-priority foreground loop takes ~5us
void low_priority interrupt LowPriorityTasks(void)
{
  // Do stuff quickly, clear sources of interrupts
}

Cuando falla, veo que el administrador de dispositivos continúa actualizándose acompañado de una de estas ventanas emergentes cada 5 segundos en Windows 7:ingrese la descripción de la imagen aquí

Respuestas (3)

Intente usar USB en modo de interrupción. Los dispositivos USB deben responder a las solicitudes del host dentro de un período de tiempo determinado. No ha detallado cuánto tarda en ejecutarse la rutina de tareas del temporizador, pero a partir de este error parece que está tardando demasiado y no hay forma de que el USB responda de manera oportuna.

Sin detalles específicos de su aplicación, sugeriría ejecutar USBDeviceTasks() como la única tarea de interrupción de alta prioridad y configurar el temporizador y sus tareas con menor prioridad.

De esta manera, cuando el host solicite una respuesta del PIC cuando esté ejecutando las tareas del temporizador, hará una pausa en la ejecución de esa rutina, responderá al host y luego volverá a esa rutina.

en esta versión de la pila USB, no veo ninguna macro USB_INTERRUPT. aunque ciertamente parece tener algo que ver con el tiempo
Mi error: abrí la biblioteca equivocada. Sin embargo, puede mover USBDeviceTasks() de main a HighPriorityTasks una vez que las interrupciones estén configuradas correctamente.
sí, no estaba seguro de si sería seguro ejecutar USBDeviceTasks() en una interrupción.

La clase USB HID puede sondear tan rápido como cada 1 ms. Entonces, idealmente, desea llamar a USBDeviceTask() con más frecuencia que cada 1 ms.

Por otro lado, he intentado llamar a USBDeviceTask() cada 10 ms, ¡y parece funcionar bien!

Tengo mis propias funciones de apagado/encendido al entrar y salir del modo de suspensión y no me di cuenta de que la función predeterminada de devolución de llamada de suspensión USB puso el dispositivo en modo de suspensión:

void USBCBSuspend(void)
{
  Sleep();         // Go to sleep, wake up when a USB activity event occurs
  //If using the WDT, should go back to sleep if awoke by WDT instead of USBIF
  while((0 == USBIF_FLAG) && (0 == RCONbits.TO))      //If using the WDT, should go back to sleep if awoke by WDT instead of USBIF
  {
    Sleep();     //Entry into sleep clears WDT count, much like executing ClrWdt() instruction
  }

  //After the USB suspend event ends, you should re-configure your I/O pins
  //for normal operation mode (which is allowed to consume more current).
  //However, it is recommended to put this code in the USBCBWakeFromSuspend()
  //function instead of here (so that this function will work with either
  //sleeping or clock switching to a lower frequency).
}

Esto es ciertamente algo que no tenía la intención de hacer, así que comente esto por ahora.

Aunque un poco aparte, un bucle do-while realmente proporciona una implementación más legible aquí mejor de todos modos:

// USB_onSuspend(void)
// Called when the USB host sends USB suspend signaling
void USBCBSuspend(void) {
  do {
    Sleep();
  } while ((USBIF_FLAG == 0) && (RCONbits.TO == 0));
}