ATSAM3X8E Issue Returning from Wait Mode

Discussion around product based on ARM Cortex M3 core.

Moderators: nferre, ncollot

ToB
Posts: 3
Joined: Thu Oct 23, 2014 3:13 pm

ATSAM3X8E Issue Returning from Wait Mode

Thu Oct 23, 2014 3:46 pm

Hi!

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))
The controller seems not to enable the MOSCRCEN bit after the second time executing WFE. This makes the controller stay in the while loop and not return from that function.

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
ToB
Posts: 3
Joined: Thu Oct 23, 2014 3:13 pm

Re: ATSAM3X8E Issue Returning from Wait Mode

Thu Oct 30, 2014 2:09 pm

Hey everybody,

EDIT: I just recognised that there there happens some change to the CKGR_MOR register. During the first run it shows the value 1000000000000100000001001. The second run shows 1000000000011111100001001. Even explicitly setting the MOSCXTST field (which contains the changes) does not effect this behavior.

I just recognised that the code I posted contained some Debug-Code and would obviously not run. So here you get the actual version:

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_RTCAL);   //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
jharley
Posts: 238
Joined: Thu Dec 06, 2012 6:40 am

Re: ATSAM3X8E Issue Returning from Wait Mode

Thu Oct 30, 2014 4:43 pm

Not sure you need the last __WFE(); statement.

The ASF function pmc_enable_waitmode(); executes this statement to place the device into wait mode.

Have you looked at the example code that is provided with Atmel Studio?

File->New->Example Project...

Device Family: SAM3, 32-bit
Search box: Low Power

Make a new project with this then look at the examples in the main.c file.
There is an example using Wait mode. The example uses the UART to wake the processor ... just substitute your event in place of the UART.
ToB
Posts: 3
Joined: Thu Oct 23, 2014 3:13 pm

Re: ATSAM3X8E Issue Returning from Wait Mode

Fri Oct 31, 2014 12:04 am

Now that seems to be promising. Unfortunately not all examples of the IDE do seem to be online available thus I didn't find them earlier. I guess the need of the additional WFE is yet another sign of something going wrong in my code.
However, I will come up with the result as soon as I got one.

Return to “SAM3 Cortex-M3 MCU”

Who is online

Users browsing this forum: No registered users and 3 guests