USB send hangs after changing the MCU core clock

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

USB send hangs after changing the MCU core clock

812 Views
olavbirkeland
Contributor III

We have a custom board  using a Kinetis MK66FX1M0VMD18 connecting to a PC using USB VCOM (COM port on the PC). We use the interface to send commands to the MCU. One command involves internal flash write, and this makes it necessary to lower the MCU clock from 120MHz to below 80MHz. When I change the clock (this does not change the USB clock), the USB function stops sending.  Receive seems to still be working.

I have traced the problem down to the USB_DeviceCdcAcmSend() function where cdcAcmPipe->isBusy is true and thereby leaving the function.

Setting the MCU clock back to its previous state does not help. What does help is to disconnect the USB cable (The device is self powered) and reconnect it. Doing this the "blocked" data present in the USB send buffer gets sent, and everything works until next time the clock is changed.

Summary:

FreeRTOS

SDK_2.1

Kinetis MK66FX1M0VMD18

The USB clock is based on external 50MHz oscillator -> PLL (/5 *24) -> /2 -> USB1PFD clock (120MHz) -> *2 /5 -> 48MHz USB FS clock

Changing the core, system, bus and flash clocks only involves changing OUTDIV1,2,3 and 4 registers.

- Why does the clock change lock USB send, even dough I do not change the clock used by the USB interface ?

- How can I recover from a USB lock situation without having to disconnect the USB cable? (I have a similar problem maybe related to this one, but not involving a clock change)

 Olav

0 Kudos
3 Replies

546 Views
olavbirkeland
Contributor III

I added a screenshot of what happens when the MCU clock is changed before accessing the flash. The two last entries marked with yellow is the "illegal" behavior (does not happen if I do not change the MCU clock). After this the target no longer responds. I am no expert  on the USB inner working, but hopefully this might be a hint about what is the problem.

Capture.PNG

0 Kudos

546 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Olav Birkeland

Could you share how are you changing the core clock?

I made some test in my side and I couldn't reproduce your issue. Even thought every time I send and received data I changed the divisors in OUTDIV1,2,3 and 4 registers, my USB module works without problem.

Best Regards

Jorge Alcala

0 Kudos

546 Views
olavbirkeland
Contributor III

Hi Jorge

I have been on vacation and haven't had the chance to respond until now.

For changing the clock I use the code made by MCUXpresso clock tool. 

This function is called every time the clock is sett back to full speed, and it is the same function as used to set the clock after boot:

/*******************************************************************************
* Code for BOARD_BootClockRUN configuration
******************************************************************************/
void BOARD_BootClockRUN(void)
{

SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);

// Set RUN mode
SMC_SetPowerModeRun(SMC);
while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateRun)
{
}


/* Set the system clock dividers in SIM to safe value. */
CLOCK_SetSimSafeDivs();
/* Initializes OSC0 according to board configuration. */
CLOCK_InitOsc0(&oscConfig_BOARD_BootClockRUN);
CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockRUN.freq);
/* Configure the Internal Reference clock (MCGIRCLK). */
CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockRUN.irclkEnableMode,
mcgConfig_BOARD_BootClockRUN.ircs,
mcgConfig_BOARD_BootClockRUN.fcrdiv);
/* Configure FLL external reference divider (FRDIV). */
CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_BOARD_BootClockRUN.frdiv);
/* Set MCG to PEE mode. */
CLOCK_BootToPeeMode(mcgConfig_BOARD_BootClockRUN.oscsel,
mcgConfig_BOARD_BootClockRUN.pllcs,
&mcgConfig_BOARD_BootClockRUN.pll0Config);
/* Set the clock configuration in SIM module. */
CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN);
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
/* Enable USB FS clock. */
CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0, SIM_USB_CLK_120000000HZ);
/* Set LPUART clock source. */
CLOCK_SetLpuartClock(SIM_LPUART_CLK_SEL_MCGIRCLK_CLK);
}

This function is called before doing flash operations that requires the clock to be 80MHz or lower (the clock is set to 60MHz so the name is misleading) :

void Set_RUN_Mode_80Mhz(void)
{
  /* Set the clock configuration in SIM module. */
  CLOCK_SetSimConfig(&simConfig_Set_RUN_Mode_80Mhz);
  /* Set SystemCoreClock variable. */
  SystemCoreClock = SET_RUN_MODE_80MHZ_CORE_CLOCK;

  // Set RUN mode
  SMC_SetPowerModeRun(SMC);
  while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateRun)
  {
  }
}

/*******************************************************************************
* Variables for Set_RUN_Mode_80Mhz configuration
******************************************************************************/
const mcg_config_t mcgConfig_Set_RUN_Mode_80Mhz =
{
.mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */
.irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */
.ircs = kMCG_IrcFast, /* Fast internal reference clock selected */
.fcrdiv = 0x1U, /* Fast IRC divider: divided by 2 */
.frdiv = 0x4U, /* FLL reference clock divider: divided by 512 */
.drs = kMCG_DrsLow, /* Low frequency range */
.dmx32 = kMCG_Dmx32Fine, /* DCO is fine-tuned for maximum frequency with 32.768 kHz reference */
.oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */
.pll0Config =
{
.enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */
.prdiv = 0x4U, /* PLL Reference divider: divided by 5 */
.vdiv = 0x8U, /* VCO divider: multiplied by 24 */
},
.pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */
};

const sim_clock_config_t simConfig_Set_RUN_Mode_80Mhz =
{
.pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */
.pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */
.pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */
.er32kSrc = SIM_OSC32KSEL_OSC32KCLK_CLK, /* OSC32KSEL select: OSC32KCLK clock */
.clkdiv1 = 0x13370000U, /* SIM_CLKDIV1 - OUTDIV1: /2, OUTDIV2: /4, OUTDIV3: /4, OUTDIV4: /8 */
};
const osc_config_t oscConfig_Set_RUN_Mode_80Mhz =
{
.freq = 50000000U, /* Oscillator frequency: 50000000Hz */
.capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */
.workMode = kOSC_ModeExt, /* Use external clock */
.oscerConfig =
{
.enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */
.erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */
}
};

/*******************************************************************************
* Variables for BOARD_BootClockRUN configuration
******************************************************************************/
const mcg_config_t mcgConfig_BOARD_BootClockRUN =
{
.mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */
.irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */
.ircs = kMCG_IrcFast, /* Fast internal reference clock selected */
.fcrdiv = 0x1U, /* Fast IRC divider: divided by 2 */
.frdiv = 0x4U, /* FLL reference clock divider: divided by 512 */
.drs = kMCG_DrsLow, /* Low frequency range */
.dmx32 = kMCG_Dmx32Fine, /* DCO is fine-tuned for maximum frequency with 32.768 kHz reference */
.oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */
.pll0Config =
{
.enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */
.prdiv = 0x4U, /* PLL Reference divider: divided by 5 */
.vdiv = 0x8U, /* VCO divider: multiplied by 24 */
},
.pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */
};
const sim_clock_config_t simConfig_BOARD_BootClockRUN =
{
.pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */
.pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */
.pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */
.er32kSrc = SIM_OSC32KSEL_OSC32KCLK_CLK, /* OSC32KSEL select: OSC32KCLK clock */
.clkdiv1 = 0x1150000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /2, OUTDIV3: /2, OUTDIV4: /6 */
};
const osc_config_t oscConfig_BOARD_BootClockRUN =
{
.freq = 50000000U, /* Oscillator frequency: 50000000Hz */
.capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */
.workMode = kOSC_ModeExt, /* Use external clock */
.oscerConfig =
{
.enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */
.erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */
}
};

0 Kudos