K21 1M device USB 4.1.1 Suspend and Resume invoke by host PC problem

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

K21 1M device USB 4.1.1 Suspend and Resume invoke by host PC problem

530 Views
HeMyFAE
NXP Employee
NXP Employee

Customer IDTECh is requesting demo code that can demonstrate the K21 1M device can be suspend and resume by host PC.

While in suspend mode, the  K21 must go into LLS mode. the PC host can then invoke the resume  and wake up the K21 to continue its operation.

It seems that the K21 can go into suspend mode but have intermittent problem with resume process.

Regards,

hy

0 Kudos
1 Reply

320 Views
xinwang-b47377
Contributor III

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;

0 Kudos