Arduino due not going into wait mode

Hi,

I am programming my first project with Arduino DUE.

I am trying to make the MCU enter wait mode using the function pmc_enable_waitmode() from ATMEL library, however the MCU does not enter this mode, and keeps executing instructions

Does anyone have any good tutorial or can guide me on solving this issue?

Thanks!

The DUE offers several low power modes: Sleep, Wait and Backup modes, down to 2.5 μA (for the uc itself, not LEDs) in Backup mode with RTC, RTT, and GPBR.

With Sleep and Wait modes, your code returns in loop() after wake-up, whereas in backup mode, there is a reset and your code returns in setup() after waking up. In these different modes, different parts of the uc are kept alive while the uc is sleeping.

Also, note that there are 2 Wait modes: Wait for Interrupt and Wait for Event.

There is an Atmel Application Note to handle Low Power Modes in SAM3 family uc:

Which low power mode are you trying to enter ?

I am trying to enter Wait mode and I have followed the Atmel Application Note procedure.

I never switched to XTAL oscillator in my program, so I assume my processor is already using Fast RC Oscillator, which is default behaviour.

I am calling the function pmc_enable_waitmode() which does:

  1. Set the LPM bit in the PMC Fast Startup Mode Register (PMC_FSMR)
  2. Execute the Wait-For-Event (WFE) instruction of the processor

Expected behaviour is that the mcu enters Wait mode and main clock is stopped until system is woken up, however, after running this line, the folowing code keeps being executed.

/**
 * \brief Enable Wait Mode.
 * Enter condition: WFE + (SLEEPDEEP bit = 0) + (LPM bit = 1)
 */
void pmc_enable_waitmode(void)
{
	uint32_t i;

	PMC->PMC_FSMR |= PMC_FSMR_LPM; // Enter Wait mode
	SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep
	__WFE();

	/* Waiting for MOSCRCEN bit cleared is strongly recommended
	 * to ensure that the core will not execute undesired instructions
	 */
	for (i = 0; i < 500; i++) {
		__NOP();
	}
	while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
}

This example sketch below is for entering in Wait Mode with Event. Note that you could reduce consumption further by swaping to the 4 MHz RC clock before entering Wait Mode, I kept the 12 MHz RC clock:

/**********************************************
                  Wait mode with Event
**********************************************/

const uint32_t AL = 4;  // Alarm = AL * T

void setup() {

  Serial.begin(250000);
  printf("\n Last software update  : %s   %s\n", __DATE__, __TIME__);

  RTT->RTT_MR = RTT_MR_RTTRST
                | RTT_MR_RTPRES (0x8000);  // T = 1 second

  RTT->RTT_AR = RTT_AR_ALMV(AL);         // Send an event every AL * T seconds

  Serial.println("\n\rHELLO ALL !!");

  PMC->PMC_FSMR = PMC_FSMR_LPM
                  | PMC_FSMR_RTTAL;
}

void loop() {

  Serial.println("Entering Wait mode ");
  delay(3);

  clock_system(1);

  EFC0->EEFC_FMR = EEFC_FMR_FWS(0); //1 wait state flash access
  EFC1->EEFC_FMR = EEFC_FMR_FWS(0);

  __SEV(); // Set Event Register (force a 1 on the Event register regardless of its initial value)
  __WFE(); // Clear Event Register

  __WFE(); // Enter Low Power Mode

  while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
  clock_system(13);

  Serial.println("Exit from Wait mode");

  RTT->RTT_SR;
  RTT->RTT_MR |= RTT_MR_RTTRST;

}

void clock_system (uint32_t clock_num) {

  EFC0->EEFC_FMR = EEFC_FMR_FWS(3); //3+1 wait states flash access
  EFC1->EEFC_FMR = EEFC_FMR_FWS(3);


  PMC->CKGR_PLLAR =  CKGR_PLLAR_ONE
                     | CKGR_PLLAR_MULA(clock_num)
                     | CKGR_PLLAR_PLLACOUNT(0x3fUL)
                     | CKGR_PLLAR_DIVA(0x1UL);
  while (!(PMC->PMC_SR & PMC_SR_LOCKA));

  PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2
                  | PMC_MCKR_CSS_PLLA_CLK;
  while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

}

Hello,

Thanks very much for your reply.

I tried adding these two lines before my call to pmc_enable_waitmode()

__SEV(); // Set Event Register (force a 1 on the Event register regardless of its initial value)
__WFE(); // Clear Event Register

In case EVENT REGISTER was set to 0, however, it doesn't make any difference, the mcu does not go into wait mode, instead, it continues executing code as in active mode

I don't know what else I can do, I have read the ATMEL datasheet and tried to find examples of code online but I wasn't able to find anything helpful.

My code in reply #3 works, use it, or find out what's the difference between this code and pmc_enable_waitmode().

Obviousely something is missing in pmc_enable_waitmode().

Fix the "bug" in the pmc file ( ...packages/arduino/hadware/sam/1.6.6/system/libsam/source/pmc). Copy pmc file into a blank sketch (no setup(), no loop()), add your modifications, save the pmc file.

Hi,

Sorry I forgot to reply to his thread.

Your code works and the function pmc_enable_waitmode() works as well.
I tried them both using a simple sketch and the mcu went into wait mode.

However, I couldn't get it to work on the bigger project I am working on. Probably some other pieces of code are messing it up. I'll post it here if I find a solution

Regards