Pregunta

Estoy trabajando con el microcontrolador NXP LPC1788 en este momento, y estoy tratando de configurarlo para comunicarse con una PC de Windows 7 usando USB. Tengo experiencia limitada con USB (comencé a aprender el protocolo a principios de esta semana), pero he trabajado con el LPC1788 durante bastante tiempo y tengo experiencia con otros protocolos de comunicación (Can, I2C, SSP).

Quiero configurar mi microcontrolador para actuar como un dispositivo y para que la PC actúe como el host. Sospecho que necesitaré configurar el microcontrolador para comunicarse con las transferencias de interrupción de velocidad completa. Además, es probable que necesite crear mi propio controlador USB específico del proveedor para la PC más adelante, aún no lo he hecho, y mis descriptores no están configurados correctamente.

Mi problema específico es que cuando ejecuto mi programa e inicialice / habilite el dispositivo USB del microcontrolador, solo recibo dos interrupciones USB. Los valores de estado de interrupción del dispositivo (devIntst) en cada caso son:

0x19 - (FRAME, DEVSTAT, and CCEMPTY interrupts)
0x1  - (FRAME interrupt)

En el caso de recibir la interrupción de Devstat, leí el siguiente valor del motor de interfaz en serie utilizando un comando de estado del dispositivo de obtención:

0x19 - (CON (connected), SUS_CH (suspend state change), and RST (bus reset))

Uso de Usbleryzer, obtengo solo los siguientes cuatro paquetes: http://i.imgur.com/wrk7rbv .png .

Estoy esperando que incluso sin descriptores configurados adecuadamente o un controlador coincidente en el final de la PC, todavía debería recibir más de esto. Esperaba haber recibido una solicitud de descriptor de obtención en el punto final 0.

Mi función principal solo inicializa mi dispositivo USB y los bucles indefinidamente.

El código de inicialización USB se da a continuación:

void USBInit()
{
  // Turn on power and clock
  CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCUSB, ENABLE);

  // PLL0 clock is 96 MHz, usbclk should be 48 MHz.
  LPC_SC->USBCLKSEL = 0x102;

  // Configure USB pins.
  PINSEL_ConfigPin(0, 29, 1); // USB_D+1
  PINSEL_ConfigPin(0, 30, 1); // USB_D-1
  PINSEL_ConfigPin(1, 18, 1); // USB_UP_LED1
  PINSEL_ConfigPin(2,  9, 1); // USB_CONNECT1
  PINSEL_ConfigPin(1, 30, 2); // USB_VBUS 
  //PINSEL_ConfigPin(1, 19, 2); // USB_PPWR1

  PINSEL_SetPinMode(1, 30, PINSEL_BASICMODE_PLAINOUT);

  // Set DEV_CLK_EN and AHB_CLK_EN.
  LPC_USB->USBClkCtrl |= 0x12;

  // Wait until change is reflected in clock status register.
  while((LPC_USB->USBClkSt & 0x12) != 0x12);

  // Select USB port 1.
  LPC_USB->USBClkCtrl |= 0x8;
  while((LPC_USB->USBClkSt & 0x8) == 0);
  LPC_USB->StCtrl &= ~0x3;
  LPC_USB->USBClkCtrl &= ~0x8;

  // Reset the USB.
  USBReset();

  // Configure interrupt mode.
  writeSIECommandData(CMD_SET_MODE, 0);

  // Enable NVIC USB interrupts.
  NVIC_EnableIRQ(USB_IRQn);

  // Set device address to 0x0 and enable device & connection.
  USBSetAddress(0);
  USBSetConnection(TRUE);

  //printf("USB initialised\n");
  //printf("EpIntEn: 0x%x\n", LPC_USB->EpIntEn);

  // No errors here (SIE Error code: 0x0).
  USBPrintErrCode();

  // Packet sequence violation here (SIE Error code: 0x11).
  USBPrintErrCode();
}

La función Restablecer USB:

void USBReset()
{
  LPC_USB->EpInd = 0;
  LPC_USB->MaxPSize = USB_MAX_PACKET_SIZE;
  LPC_USB->EpInd = 1;
  LPC_USB->MaxPSize = USB_MAX_PACKET_SIZE;
  while ((LPC_USB->DevIntSt & EP_RLZED_INT) == 0);

  LPC_USB->EpIntClr  = 0xFFFFFFFF;
  LPC_USB->EpIntEn   = 0xFFFFFFFF;
  LPC_USB->DevIntClr = 0xFFFFFFFF;
  LPC_USB->DevIntEn  = DEV_STAT_INT | EP_SLOW_INT | EP_FAST_INT;
}

La función de dirección SET USB:

void USBSetAddress(uint32_t addr)
{
  writeSIECommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | addr));
  writeSIECommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | addr));
}

La función de conexión establecida USB:

void USBSetConnection(uint32_t connect)
{
  writeSIECommandData(CMD_SET_DEV_STAT, DAT_WR_BYTE(connect ? DEV_CON : 0));
}

La rutina de servicio de interrupción USB:

void USB_IRQHandler(void)
{
  uint32_t data;
  uint32_t interruptData = LPC_USB->DevIntSt;

  printf("InterruptData: 0x%x\n", interruptData);

  // Handle device status interrupt (reset, connection change, suspend/resume).
  if(interruptData & DEV_STAT_INT)
  {
    LPC_USB->DevIntClr = DEV_STAT_INT;
    writeSIECommand(CMD_GET_DEV_STAT);
    data = readSIECommandData(DAT_GET_DEV_STAT);
    printf("Data: 0x%x\n", data);

    // Device reset.
    if(data & DEV_RST)
    {
      USBReset();
      USBResetCore();
      printf("USB Reset\n");
    }

    // Connection change.
    if(data & DEV_CON_CH)
    {
      printf("Connection change\n");
      /* Pass */
    }

    // Suspend/resume.
    if(data & DEV_SUS_CH)
    {
      if(data & DEV_SUS)
      {
        printf("USB Suspend\n");
        USBSuspend();
      }
      else
      {
        printf("USB Resume\n");
        USBResume();
      }
    }

    return;
  }

  // Handle endpoint interrupt.
  if(interruptData & EP_SLOW_INT)
  {
    printf("Endpoint interrupt\n");
  }

  if(interruptData & EP_FAST_INT)
  {
    printf("Endpoint interrupt\n");
  }
}

La salida del terminal:

InterruptData: 0x19
Data: 0x19
USB Reset
USB Resume
InterruptData: 0x1

Editar: Uso del comando de código de error Obtener SIE, encontré que termino un error "Paquete inesperado" al final de la función de inicialización USB. Sin embargo, si leí el registro de pruebas, me devuelvo 0xa50f como se esperaba, lo que significa que mi comunicación con la SIE está funcionando y mis relojes USB / AHB están presumiblemente configurados correctamente y en funcionamiento.

¿Fue útil?

Solución

Me las arreglé para obtener un ejemplo de un proyecto USB que trabaja en el banco de trabajo Embedded IAR.Sobre la base de eso, hice dos cambios que principalmente arreglaron mi programa:

  • Cambié la configuración de mi proyecto de "semihosted" a "swo", que hizo que mi impresión saliera mucho más rápido.

  • He eliminado la siguiente línea.Aparentemente mal configuró la velocidad del reloj USB.

    LPC_SC->USBCLKSEL = 0x102;
    

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top