USB1 PLL stucks

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB1 PLL stucks

690 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by andres.cass on Wed Nov 18 07:47:15 MST 2015
Hi.
I am starting with the USB stack in the LPC4337, but I have a problem.
I am trying to make a simple virtual COM (CDC) device with an eco functionality. I take the example base of the LPCOpen usbd_rom_cdc_uart but using the uC USB1 port.

But when I run the application it gets stuck in while (!(Chip_Clock_GetPLLStatus(CGU_USB_PLL) & CGU_PLL_LOCKED)) {}while cicle inside the static void Chip_USB_PllSetup(void) function. It's like it can´t set the PLL for the USB.

Here is my code:

int main(void) {

#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
    // Set up and initialize all required blocks and
    // functions related to the board hardware
    Board_Init();
    // Set the LED to the state of "On"
    Board_LED_Set(0, true);
#endif
#endif
    uint32_t sarasa = 0;
    while(sarasa < 10000)
    sarasa++;

    SystemCoreClockUpdate();

    USBD_API_INIT_PARAM_T usb_param;
USB_CORE_DESCS_T desc;
ErrorCode_t ret = LPC_OK;
USB_CORE_CTRL_T *pCtrl;

Chip_SCU_PinMuxSet(0x9, 5, (SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2));/* P9_5 USB1_VBUS_EN, USB1 VBus function */
Chip_SCU_PinMuxSet(0x2, 5, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2));/* P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION */
Chip_SCU_PinMuxSet(0x6, 3, (SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1));/* P6_3 USB0_PWR_EN, USB0 VBus function */

Chip_USB1_Init(); //USB_init_pin_clk();

/* Init USB API structure */
g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->usbdApiBase;

/* initialize call back structures */
memset((void *) &usb_param, 0, sizeof(USBD_API_INIT_PARAM_T));
usb_param.usb_reg_base = LPC_USB_BASE;
usb_param.max_num_ep = 4;
usb_param.mem_base = USB_STACK_MEM_BASE;
usb_param.mem_size = USB_STACK_MEM_SIZE;

/* Set the USB descriptors */
desc.device_desc = (uint8_t *) USB_DeviceDescriptor;
desc.string_desc = (uint8_t *) USB_StringDescriptor;

#ifdef USE_USB0
desc.high_speed_desc = USB_HsConfigDescriptor;
desc.full_speed_desc = USB_FsConfigDescriptor;
desc.device_qualifier = (uint8_t *) USB_DeviceQualifier;
#else
/* Note, to pass USBCV test full-speed only devices should have both
 * descriptor arrays point to same location and device_qualifier set
 * to 0.
 */
desc.high_speed_desc = USB_FsConfigDescriptor;
desc.full_speed_desc = USB_FsConfigDescriptor;
desc.device_qualifier = 0;
#endif

ret = USBD_API->hw->Init(&g_hUsb, &desc, &usb_param);
if (ret == LPC_OK) {

/*WORKAROUND for artf45032 ROM driver BUG:
Due to a race condition there is the chance that a second NAK event will
occur before the default endpoint0 handler has completed its preparation
of the DMA engine for the first NAK event. This can cause certain fields
in the DMA descriptors to be in an invalid state when the USB controller
reads them, thereby causing a hang.
 */
pCtrl = (USB_CORE_CTRL_T *) g_hUsb;/* convert the handle to control structure */
g_Ep0BaseHdlr = pCtrl->ep_event_hdlr[0];/* retrieve the default EP0_OUT handler */
pCtrl->ep_event_hdlr[0] = EP0_patch;/* set our patch routine as EP0_OUT handler */

/* Init UCOM - USB to UART bridge interface */
ret = UCOM_init(g_hUsb, &desc, &usb_param);
if (ret == LPC_OK) {
/* Make sure USB and UART IRQ priorities are same for this example */
NVIC_SetPriority(LPC_USB_IRQ, 1);
/*  enable USB interrupts */
NVIC_EnableIRQ(LPC_USB_IRQ);
/* now connect */
USBD_API->hw->Connect(g_hUsb, 1);
}
}


    // TODO: insert code here
    /* Setup GPIOs for USB demos */
    Chip_SCU_PinMuxSet(0x9, 5, (SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2));/* P9_5 USB1_VBUS_EN, USB1 VBus function */
    Chip_SCU_PinMuxSet(0x2, 5, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2));/* P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION */
    Chip_SCU_PinMuxSet(0x6, 3, (SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1));/* P6_3 USB0_PWR_EN, USB0 VBus function */

    Chip_SCU_PinMuxSet(0xE, 7, (SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN));
    Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 7, 7);

    // Force the counter to be placed into memory
    volatile static uint32_t i = 0 ;
    // Enter an infinite loop, just incrementing a counter
    while(1) {
        i++ ;
        if(i == 500000)
        {
        Chip_GPIO_SetPinToggle(LPC_GPIO_PORT, 7, 7);
        i = 0;
        }
    }
    return 0 ;
}


Chip_USB1_Init function (in lpc_chip_43xx\src\chip_18xx_43xx.c):

void Chip_USB1_Init(void)
{
/* Setup and enable the PLL */
Chip_USB_PllSetup();

/* USB1 needs a 60MHz clock. To get it, a divider of 4 and then 2 are
   chained to make a divide by 8 function. Connect the output of
   divider D to the USB1 base clock. */
Chip_Clock_SetDivider(CLK_IDIV_A, CLKIN_USBPLL, 4);
Chip_Clock_SetDivider(CLK_IDIV_D, CLKIN_IDIVA, 2);
Chip_Clock_SetBaseClock(CLK_BASE_USB1, CLKIN_IDIVD, true, true);

/* enable USB main clock */
Chip_Clock_EnableBaseClock(CLK_BASE_USB1);
Chip_Clock_EnableOpts(CLK_MX_USB1, true, true, 1);
/* enable USB1_DP and USB1_DN on chip FS phy.*/
LPC_SCU->SFSUSB = 0x12;
}


The application get stuck inside Chip_USB_PllSetup()  (in lpc_chip_43xx\src\chip_18xx_43xx.c):

static void Chip_USB_PllSetup(void)
{
/* No need to setup anything if PLL is already setup for the frequency */
if (Chip_Clock_GetClockInputHz(CLKIN_USBPLL) == usbPLLSetup.freq)
return ;

/* Setup default USB PLL state for a 480MHz output and attach */
Chip_Clock_SetupPLL(CLKIN_CRYSTAL, CGU_USB_PLL, &usbPLLSetup);

/* enable USB PLL */
Chip_Clock_EnablePLL(CGU_USB_PLL);

/* Wait for PLL lock */
while (!(Chip_Clock_GetPLLStatus(CGU_USB_PLL) & CGU_PLL_LOCKED)) {} // <-------------------- HERE
}


Never get oout of the while cicle, like it never get the PLL working (in lpc_chip_43xx\src\clock_18xx_43xx.c):

uint32_t Chip_Clock_GetPLLStatus(CHIP_CGU_USB_AUDIO_PLL_T pllnum)
{
return LPC_CGU->PLL[pllnum].PLL_STAT;
}


Is this a configuration problem? I am missing somthing? I take it directly from the LPCOpen example.

Thank you
Labels (1)
2 Replies

569 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by andres.cass on Fri Nov 27 07:28:56 MST 2015
Thank you for the reply.
I have looked again my code and I find the problem, thjat of course was a mistake of mine. In the PLL Setup function (Chip_Clock_SetupPLL(CLKIN_CRYSTAL, CGU_USB_PLL, &usbPLLSetup)) I was passing the CLKIN_CRYSTAL as source and the crystal on my board has a freq of 32 KHz, but the usbPLLSetup struct has parameters to configure the PLL to 480 MHz with 12MHz input, that was why the PLL never works as required.

I change the PLL source to the IRC (that runs at 12MHz) and it works excellent.
Thank you so much for your time.

Regards

569 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Tue Nov 24 09:35:14 MST 2015
If I remember correctly there was a problem with the PLL setup in one of the previous versions of LPCOpen, but I think it has been fixed.
Do you use a 2.x version of LPCOpen?

The Problem with the PLL could be that it switches too fast from a low to a high frequency. This causes instability and therefore it never locks.
Switching in steps or insertion of wait loops here and there can solve this.

Please test it with the current LPCOpen version for the LPC4300, I keep watching for your feedback.

Regards,
NXP Support Team
0 Kudos