Hi Mai, I had verify the suspend/resume functions on the twrk21f120m with hid_keyboard device example. The functions suspend and resume both ok. But hid_keyboard device can not be work normally after resume. With the help of the Nguyen Hai Duc (B39389) and debugging, We found that code of MCG mode for k21 now the PLLSTEN =0, so when the device entered to stop mode, the MCG will be in PBE mode. So after resuming the device, We have to write the code to swtich from PBE mode to PEE mode.
Now we have two solutions,
1) You can write code to swtich from PBE mode to PEE mode after resume, Just like remove "set_MCG_PEE_Mode();" function and replace by "pll_init()" in "TestApp_Task" function.
void TestApp_Task(void)
{
enter_stop();
/* The processor will wait for an AWIC interrupt, and then continue on.
* Any lines following this assume we are waking up.
*/
#if defined(MCU_MK20D5)
PMC_REGSC &= ~(0x10); // e4481 workaround
#endif
//set_MCG_PEE_Mode(); /* Resume proper clock */
pll_init();
#endif // STOP_IN_SUSPEND
USB_Class_Initiate_Resume(CONTROLLER_ID); /* Resume USB Bus */
}
2) we can enable PLLSTEN bit in "pll_init()" function and remove the "set_MCG_PEE_Mode();" function in "TestApp_Task" function.
The code now looks like:
#ifdef MCU_MK21D5
/* System clock initialization */
if ( *((uint8_t*) 0x03FFU) != 0xFFU) {
MCG_C3 = *((uint8_t*) 0x03FFU);
MCG_C4 = (MCG_C4 & 0xE0U) | ((*((uint8_t*) 0x03FEU)) & 0x1FU);
}
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=0,OUTDIV4=2,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
SIM_CLKDIV1 = (uint32_t)0x01270000UL; /* Update system prescalers */
/* OSC_CR: ERCLKEN=0,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC_CR = (uint8_t)0x00U;
/* MCG_C7: OSCSEL=0 */
MCG_C7 &= (uint8_t)~(uint8_t)0x01U;
/* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=1 */
MCG_C2 = (uint8_t)0x25U;
/* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (uint8_t)0x98U;
/* MCG_C4: DMX32=0,DRST_DRS=0 */
MCG_C4 &= (uint8_t)~(uint8_t)0xE0U;
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=3 */
//MCG_C5 = (uint8_t)0x03U;
MCG_C5 = (uint8_t)0x01U;
/* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
//MCG_C6 = (uint8_t)0x00U;
MCG_C6 = (uint8_t)0x06U;
while((MCG_S & MCG_S_OSCINIT0_MASK) == 0x00U) { /* Check that the oscillator is running */
}
while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */
}
while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */
}
/* Switch to PBE Mode */
/* OSC_CR: ERCLKEN=0,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC_CR = (uint8_t)0x00U;
/* MCG_C7: OSCSEL=0 */
MCG_C7 &= (uint8_t)~(uint8_t)0x01U;
/* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (uint8_t)0x98U;
/* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=1 */
MCG_C2 = (uint8_t)0x25U;
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=3 */
//MCG_C5 = (uint8_t)0x03U;
MCG_C5 = (uint8_t)0x01U;
/* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=0 */
//MCG_C6 = (uint8_t)0x40U;
MCG_C6 = (uint8_t)0x46U;
while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */
}
while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */
}
/* Switch to PEE Mode */
/* OSC_CR: ERCLKEN=0,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC_CR = (uint8_t)0x00U;
/* MCG_C7: OSCSEL=0 */
MCG_C7 &= (uint8_t)~(uint8_t)0x01U;
/* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (uint8_t)0x18U;
/* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=1 */
MCG_C2 = (uint8_t)0x25U;
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=3 */
//MCG_C5 = (uint8_t)0x03U;
MCG_C5 = (uint8_t)0x21U;
/* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=0 */
//MCG_C6 = (uint8_t)0x40U;
MCG_C6 = (uint8_t)0x46U;
while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */
}
while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */
}
/* MCG_C6: CME0=1 */
MCG_C6 |= (uint8_t)0x20U; /* Enable the clock monitor */
return 0;