Based on an Arduino Due I am trying to implement an application requiring regularly repeated activation of the Wait Mode. Looking into some documentation and examples I came to the code listed below. But even though it seems to be consistent with any documentation I found, it seems to contain a bug.
The unexpected behaviour shows at the second time the code is executed: After running this code the second time the controller does not return to active mode. I could track it down to the following line in pmc_enable_waitmode():
Code: Select all
while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN))
I found some articles in your community touching this topic but none of them could solve the issue.
I am looking forward to your ideas, since I got stuck at this point.
This is the code being executed each time the controller enters WFE:
Code: Select all
uint32_t PllarVal =0; uint32_t MckrVal =0; //save old clock values PllarVal = REG_CKGR_PLLAR; MckrVal = REG_PMC_MCKR; REG_SUPC_MR |= SUPC_MR_KEY(0xA5) | SUPC_MR_BODDIS_DISABLE; //Disable Brownout Detector pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz); pmc_set_fast_startup_input(PMC_FSMR_RTTAL); //Enable Timer Wakeup //pmc_enable_waitmode();/* //restore clock pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1); /* Restart Main Oscillator */ REG_CKGR_MOR = CKGR_MOR_KEY(0x37) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN ; while ( !(REG_PMC_SR & PMC_SR_MOSCXTS) ) ; /* Switch to moscsel */ REG_CKGR_MOR = CKGR_MOR_KEY(0x37) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL ; while ( !(REG_PMC_SR & PMC_SR_MOSCSELS) ) ; pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_1); /* Restart PLL A */ pmc_enable_pllack((PllarVal&CKGR_PLLAR_MULA_Msk)>>CKGR_PLLAR_MULA_Pos, (PllarVal&CKGR_PLLAR_PLLACOUNT_Msk)>>CKGR_PLLAR_PLLACOUNT_Pos, (PllarVal&CKGR_PLLAR_DIVA_Msk)>>CKGR_PLLAR_DIVA_Pos ); //switch to fast clock REG_PMC_MCKR = (MckrVal & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK ; while ( !(REG_PMC_SR & PMC_SR_MCKRDY) ) ; REG_PMC_MCKR = MckrVal ; while ( !(REG_PMC_SR & PMC_SR_MCKRDY) ) ; REG_SUPC_MR = (REG_SUPC_MR |SUPC_MR_KEY(0xA5)) & ~SUPC_MR_BODDIS; //Enable Brownout Detector __WFE(); //clear event register