LPC54608 using USBPLL for USB0 ?

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

LPC54608 using USBPLL for USB0 ?

1,935 Views
carstengroen
Senior Contributor II

Hello

until now, I have used the FRO96 for USB0 clocking. I would like to be able to switch it to the USBPLL instead.

I'm having difficulties in doing this and I'm not able to find any samples in the SDK that uses the USBPLL (all examples uses FRO96)

I have the code below, any pointers to where the problem is ?

#ifdef USBPLL
    // Does not work
     const usb_pll_setup_t usb_pllSetup = {
        .msel = 15U,
        .nsel = 1U,
        .psel = 0U,
        .direct = false,
        .bypass = false,
        .fbsel = true,
        .inputRate = 12000000U,
    };
    CLOCK_SetUsbPLLFreq(&usb_pllSetup);

    POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); // Turn on USB Phy
    CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
    
    CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK); // Attach USB PLL clock to USB
     
    // enable usb0 host clock
    CLOCK_EnableClock(kCLOCK_Usbhsl0);
    *((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
    // disable usb0 host clock
    CLOCK_DisableClock(kCLOCK_Usbhsl0);
    // enable USB IP clock
    CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbSrcUsbPll, CLOCK_GetFreq(kCLOCK_UsbPll));

#else
     // Works
     // We use the FRO for the USB clock, turn it on and set it to 96 MHz
    POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); // Ensure FRO is on
    CLOCK_SetupFROClocking(96000000U); // Set up high frequency FRO output to selected frequency
    
     POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); // Turn on USB Phy
    CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
    
     CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); // Attach FRO clock to USB
    // enable usb0 host clock
    CLOCK_EnableClock(kCLOCK_Usbhsl0);
    *((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
    // disable usb0 host clock
    CLOCK_DisableClock(kCLOCK_Usbhsl0);
    // enable USB IP clock
    CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf));

#endif
Labels (2)
8 Replies

1,391 Views
Dezheng_Tang
NXP Employee
NXP Employee

Inside devices\LPC54608\drivers\fsl_clock.c file, there are two modules:

CLOCK_EnableUsbfs0DeviceClock() and CLOCK_EnableUsbhs0DeviceClock(),

When you call CLOCK_EnableUsbfs0DeviceClock(), the first parameter, clock_usb_src_t, use "kCLOCK_UsbPll",

the second parameter doesn't matter because this routine assumes PLL input is 12MHz OSC only.

Since external OSC is the only option as USBPLL input, be careful that you need to power up XTAL related in PDRUNCFG, take a close look in CLOCK_SetUsbPLLFreq() and also make sure your external OSC is connected and working.

/*! @brief USB clock source definition. */
typedef enum _clock_usb_src
{
    kCLOCK_UsbSrcFro = (uint32_t)kCLOCK_FroHf,            /*!< Use FRO 96 or 48 MHz. */
    kCLOCK_UsbSrcSystemPll = (uint32_t)kCLOCK_PllOut,     /*!< Use System PLL output. */
    kCLOCK_UsbSrcMainClock = (uint32_t)kCLOCK_CoreSysClk, /*!< Use Main clock.    */
    kCLOCK_UsbSrcUsbPll = (uint32_t)kCLOCK_UsbPll,        /*!< Use USB PLL clock.    */

    kCLOCK_UsbSrcNone = SYSCON_USB0CLKSEL_SEL(7)          /*!< Use None, this may be selected in order to reduce power when no output is needed.. */
} clock_usb_src_t;

0 Kudos
Reply

1,391 Views
carstengroen
Senior Contributor II

Thanks Tang,

So the last line in the #ifdef USBPLL can be changed to this:

    // enable USB IP clock
    CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbSrcUsbPll, 0);‍‍‍‍

I'm pretty sure that the external clock/OSC is working (I hope) as I already use it for the main PLL (running at 180 MHz), the code I use for this is:

void BOARD_BootClockPLL180M(void) {
    POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); // Ensure FRO is on
    CLOCK_AttachClk(
        kFRO12M_to_MAIN_CLK); // Switch to FRO 12MHz first to ensure we can change voltage without accidentally
                              // being below the voltage for current speed 
    POWER_SetVoltageForFreq(
        12000000U); // Set voltage for the one of the fastest clock outputs: System clock output
    CLOCK_SetFLASHAccessCyclesForFreq(12000000U); // Set FLASH wait states for core

    // Set up SYS PLL
    const pll_setup_t pllSetup = {
        .pllctrl = SYSCON_SYSPLLCTRL_SELI(32U) | SYSCON_SYSPLLCTRL_SELP(16U) | SYSCON_SYSPLLCTRL_SELR(0U),
        .pllmdec = (SYSCON_SYSPLLMDEC_MDEC(8191U)),
        .pllndec = (SYSCON_SYSPLLNDEC_NDEC(770U)),
        .pllpdec = (SYSCON_SYSPLLPDEC_PDEC(98U)),
        .pllRate = 180000000U,
        .flags = PLL_SETUPFLAG_WAITLOCK | PLL_SETUPFLAG_POWERUP};
    CLOCK_AttachClk(kEXT_CLK_to_SYS_PLL); // Set sys pll clock source from external crystal
          
    CLOCK_SetPLLFreq(&pllSetup);
    POWER_SetVoltageForFreq(
        180000000U); // Set voltage for the one of the fastest clock outputs: System clock output
    CLOCK_SetFLASHAccessCyclesForFreq(180000000U); // Set FLASH wait states for core 
          
    CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); // Reset divider counter and set divider to value 1
    CLOCK_SetClkDiv(kCLOCK_DivEmcClk, 0U, true);  // Reset EMCCLKDIV divider counter and halt it
    CLOCK_SetClkDiv(kCLOCK_DivEmcClk, 2U, false); // Set EMCCLKDIV divider to value 2
          
    CLOCK_AttachClk(kSYS_PLL_to_MAIN_CLK); // Switch System clock to SYS PLL 180MHz
     // Switch MAINCLKSELA to FRO12M even it is not used for MAINCLKSELB
     SYSCON->MAINCLKSELA = ((SYSCON->MAINCLKSELA & ~SYSCON_MAINCLKSELA_SEL_MASK) | SYSCON_MAINCLKSELA_SEL(0U)); 
          
    SystemCoreClock = BOARD_BootClockPLL180M_CORE_CLOCK;
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So something else must be wrong ?

Is there no example of the usage of the USB PLL available ??

0 Kudos
Reply

1,391 Views
Dezheng_Tang
NXP Employee
NXP Employee

Yes, maybe something else is wrong. The SDK has USB examples for both HS and FS. USB PLL must be

used for USB HS, so these modules should have been tested.

Can you double check the fill-up of pll_setup before CLOCK_SetUsbPLLFreq() is called and the return value

of this function? There is also a modules, CLOCK_GetUsbPLLOutFromSetup(), you can check if you have

the correct setup value before PLL configuration.

0 Kudos
Reply

1,391 Views
carstengroen
Senior Contributor II

Thanks Tang,

I figure I must do something wrong. I followed the CLOCK-SetUsbPLLFreq() function, the pll_setup looks like this:

pastedImage_1.png

I can follow the function until it waits for a lock, which never happens!

The USBPLL registers (from SYSCON) looks like this:

pastedImage_2.png

When looking at the SYSPLL (which runs at 180 MHz from external xtal), the registers looks like this:

pastedImage_3.png

Is there something more I can check to narrow what I have done wrong ?

0 Kudos
Reply

1,391 Views
Dezheng_Tang
NXP Employee
NXP Employee

If th lock never happen after USB PLL configured, while SYSPLL at 180MHz works using xtal, then, your M, P, N, values or mode may be wrong. Have you tried the value and mode from SDK?

0 Kudos
Reply

1,391 Views
carstengroen
Senior Contributor II

Tang,

I got the values etc from the MCUXpresso config tool, this was the code snippet I took from the "clock_config.c" window:

pastedImage_1.png

In my own code, I setup the USBPLL after I have configured and switched to the SYSPLL running at 180 MHz.

0 Kudos
Reply

1,391 Views
Dezheng_Tang
NXP Employee
NXP Employee

/* Setup USB PLL (PL160 such that USB_clock to 48MHz going to USB HS PHY. */
/* USB PLL is configured to integer mode:
    FCLKOUT = (M * FCLKIN)/N
    FCCO = 2 * P * FCLKOUT
    FCLKIN = 12MHz, M = 16 (bit 7~0) (msel=3), N = 2 (bit 11~10) (nsel=1), and P = 1 (bit 9~8) (psel=0)
    fbsel bit 14 is set. FCLKOUT is 96MHz, FCCO = 192MHz. */

    LPC_SYSCON->USBPLLCTRL = (0x1 << 14) | (0xF << 0) | (0x1 << 10) | (0x0 << 8);
    while (!(LPC_SYSCON->USBPLLSTAT & 0x01)) {};  /* Wait Until PLL Locked    */

Once it locks, USB0CLKDIV needs to be set to 1, divided by 2, to get 48MHz.

You can also use the M, P, N value from SDK, once set USB PLL, then instead of setting

USB1CLKSEL and USB1CLKDIV registers, you can route USB PLL to USB0 by setting USB0CLKSEL and USB1CLKDIV registers respectively.

If you think MCUXpresso clock configuration tool has issues, you can report from their website directly.

0 Kudos
Reply

1,391 Views
carstengroen
Senior Contributor II

Tang,

this also does not work for me. For now I will give up and continue using the FRO96 for USB and hope that a suitable sample using the USBPLL will be included in the SDK at some point (which I think it should have had in the first place..)

Also the documentation of the USBPLL in the UM is not exactly overwhelming :smileywink:

0 Kudos
Reply