SAMD20 Problem waking from system_sleep()

Go To Last Post
26 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, 

 

Working on a new project with a SAMD20G16 and have been stuck with a problem for a couple of days now.

 

I want to be able to put the unit to sleep (STANDBY), then wake it up by either an RTC or EXTINT interrupt.

 

The unit successfully goes to sleep, and I have confirmed that either a RTC (Calendar) interrupt or EXTINT interrupt successfully wakes the unit up.

 

The problem is, after wakeup I try to reinitialise all the peripherals again (TC, ADC) but the program hangs.

 

i.e. 

I put the device to sleep here:

 

 

system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
system_sleep();

 

//Woken Up here...

 

system_init(); <-- I refresh the clocks here (via system_clock_init())

configure_tc(); <-- I try and reconfigure the TC here

 

*****************************************************

 

void configure_tc(void) <-- This is my TC init routine
{
    struct tc_config config_tc;
    tc_get_config_defaults(&config_tc);
    config_tc.counter_size = TC_COUNTER_SIZE_8BIT;
    config_tc.clock_source = GCLK_GENERATOR_1;
    config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV16;
    config_tc.counter_8_bit.period = 205;//100ms heartbeat
    
    tc_init(&tc_instance, CONF_TC_MODULE, &config_tc);
    tc_enable(&tc_instance);
}

 

**********************************************

 

Every time I wakeup the device, it calls the TC init routine and then gets locked in a loop here:

 

 

/* Set ctrlc register*/
    ctrlc_tmp = config->waveform_invert_output;
    for (uint8_t i = 0; i < NUMBER_OF_COMPARE_CAPTURE_CHANNELS; i++) {
        if (config->enable_capture_on_channel[i] == true) {
            ctrlc_tmp |= (TC_CTRLC_CPTEN(1) << i);
        }
    }

    /* Write configuration to register */
    while (tc_is_syncing(module_inst)) { <-- stuck in a permenant loop here
        /* Wait for sync */
    }

 

******************************

 

The peripheral hangs off the SyncBusy bit forever. Its worth noting as well that this also happens with other peripherals such as the USART so I think its a more global issue.

 

I have poured over the internet looking for information and found very little. I am guessing it could be related to the clocks or something, but since I called the system_init() function which in turn called the system_clock_init() function, I presumed all the underlying clocks would be working.

 

The ASF API is very good to work with, unless something goes wrong (in which case its a nightmare).

 

can anyone help me here?

Last Edited: Thu. Oct 15, 2015 - 11:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have seen this, and reported to Atmel - I think it is now documented in the Errata ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, Thanks for the prompt reply.

 

I am looking at the Errata for the SAMD20 revision C (which I know is an old version) but there are so many entries, I am not sure which one(s) relates to my problem. Ill try a few things.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Went through the errata, but didnt find anything that seemed relevent to the TC or ADC getting stuck in a SYNCBUSY after wakeup. Are you sure you had the same problem around the TC after wakeup?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, it was definitely the TC getting stuck waiting for SYNC after sleep.

 

I'll have to see if I can find what the resolution was ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you check the code for system_set_sleepmode

 

In Standby, Idle1 and Idle2 sleep modes the device might not wake up from sleep. An External Reset, Power on Reset or Watch Dog Reset will start the device again. Errata reference: 13140

Fix/Workaround:
the SLEEPPRM bits in the NVMCTRL.CTRLB register must be written to 3 (NVMCTRL - CTRLB.bit.SLEEPPRM = 3) to ensure correct operation of the device. The average power consumption of the device will increase with 20uA compared to numbers in the electrical characteristics chapter.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, 

 

Thanks for the reply.

 

My version of ASF already has that workaround implemented:

 

tatic inline enum status_code system_set_sleepmode(
    const enum system_sleepmode sleep_mode)
{
#if (SAMD20 || SAMD21)
    /* Errata: Make sure that the Flash does not power all the way down
     * when in sleep mode. */
    NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
#endif

    switch (sleep_mode) {
        case SYSTEM_SLEEPMODE_IDLE_0:
        case SYSTEM_SLEEPMODE_IDLE_1:
        case SYSTEM_SLEEPMODE_IDLE_2:
            SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
            PM->SLEEP.reg = sleep_mode;
            break;

        case SYSTEM_SLEEPMODE_STANDBY:
            SCB->SCR |=  SCB_SCR_SLEEPDEEP_Msk;
            break;

        default:
            return STATUS_ERR_INVALID_ARG;
    }

    return STATUS_OK;
}

 

So it must be something else. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Has anyone got any more suggestions? My question in Atmel support has been running for two weeks with no resolution so far...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello, 

I seem to have similar problem. 

once in standby mode the system sleeps but unable to wake up and resume functionality. (i am waking up the system with a TC interrupt that runs in a standby mode)

 

Did you get a solution?

 

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

I'm having the same issue, actually it is quite common that one want to count hour and date in his product, and since I am buying a low power uC with RTC, I expect it to battery run to keep the correct hour/date during black outs.

It's quite obvious that it must go to standby and wakes up, what does standby need if it never recovers from it??!!!

 

I used ASF 3.30 code to wake it up by either RTC to count minutes AND by EXTINT interrupt which senses when the mains is back.

 

I have SAMD20G16A rev C, errata 13140 is already implemented in the ASF code, power consumption 20uA is huge and it will draw the battery too quckly. Despite this it does not wakes up correctly:

- with Atmel ICE connected it wakes up when the main returns but it reset and I loose hour count.

- without Atmel ICE connected it never wakes up.

 

I also found out that stopping the clock to peripherals in APBBMASK and APBCMASK the 20uA goes down to 3uA smiley, but when waking up, TC1 does not recover anymore sad.

 

Does anybody has some information on this matter?

Would a SAMD20 rev E work?

Could the errrata 10416 issue having a role in the above problem?

Thanks

Daniel

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone!

 

Apologies for posting to an old thread, but I was wondering if anyone of you managed to figure out what the root cause of the problem was. I have a similar problem and have posted it here:

https://community.atmel.com/forum/samd21-samd21e16b-sporadically-locks-and-does-not-wake-standby-sleep-mode

 

I've literally tried everything that I could think of and could not get to the bottom if it sad Note that I am using a SAMD21E16B, which is supposedly a Device Variant B, Revision E with errata reference 13140 fixed (?)

 

@awneil, can you perhaps share more details around errata 13140? Maybe it has not been fixed 100% and still lurking under the bridge, waiting for unsuspecting goats like me to base a design on EXTINT, RTC and STANDBY sleep mode and expecting it to never fail.

 

Thanks in advance,

Pieter

http://piconomic.co.za

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

 

Did anyone of you could solve this issue?

I am struggling with currents over 400 µA in Standby mode not knowing where this comes from.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi trangon,

 

Sorry, but I have not solved the issue sad (no one has replied either).

 

Regarding your issue, I can provide some advice. If you are using ASF, look in the file "power.h" for a function called "system_set_sleepmode()". There is a firmware fix for errata 13140 (search inside the datasheet and you will find it):

NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;

 

You can comment this line out if you are using Die Revision E of the silicon, for example SAMD21E16B.

 

Are you using USB? The SAMD21 has an internal 1.5kOhm pull-up resistor on D+ to indicate to the USB host that a full-speed USB device is connected. The SAMD21 Xplained Pro board has ESD protection diodes, which forms a parasitic current path to the USB +5V sense circuit. See attached pic. I had to modify the USB code to disable the stack (and pull-up resistor) before going into STANDBY sleep mode.

 

There are other threads discussing this issue, but I can't put my finger on them immediately.

 

Best of luck!

Pieter

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pieter,

 

Any luck with this? I'm on a SAMD21E16B and am also hung on the TC's STATUS[SYNCBUSY] never clearing. I don't use ASF and have written every line of code from scratch and still can't solve this. At least is seems like it may not be my software. Please let me know what you find, I'll do the same.

 

- Mark

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Mark,

 

@awneil seems to have reported this specific error to Atmel and said that it is now listed as an errata, but he has not elaborated on this. Maybe you can PM him and ask him if he would be so kind to post more details in this thread?

 

Crucial question: does your problem occur EVERY time that the SAMD21 wakes up from STANDBY sleep mode, or just every now and then?

My problem is a little bit different, because in my case (under rare circumstances) the SAMD21 locks up and refuses to wake up from an external interrupt or the RTC alarm. It could be related though, but I still have not figured out what the root cause is sad

 

I can offer some advice though:

1. In earlier versions of the datasheet there was conflicting hardware info. Make sure that you have a 1uF capacitor on VDDCORE and a 1k pull-up resistor on SWCLK.

2. Try clocking the CPU at 24 MHz with 1 flash wait state and not 48 MHz with 2 wait states. I am wondering if the CPU's max frequency limit is not too close for comfort and any jitter on the DFLL causes the SAMD21 to misbehave somehow. Atmel states that the upper limit is 48 MHz, not 48.1 or 48.2, just 48 MHz (that is worrying to me).

3. Try clocking the CPU from the DPLL and not the DFLL

4. Output the GCLK frequencies on GPIO pins so that you have some confidence that the clocks are actually working and working at the correct frequency

5. Check that the whole clock chain to the TC peripheral (AHB, APB, TC peripheral clock, etc.) is still enabled and working. If not, then the TC's STATUS[SYNCBUSY] bit will never clear, because it does not have an active clock.

 

Yes, please, please if you find anything of value, post it to this thread. I will do likewise.

 

Regards,

Pieter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pieter,

 

Thanks for the reply and info. In my case, with the debugger in control the failure happens every time, first time after waking up. Without the debugger physically attached it can take 1-15 minutes. Your problem is different. Can you wake up with the WDT's early warning interrupt? The OSCULP32K never stops and if you keep the WDT on that source, on Gen2, with the WDT's clock enabled it should not fail to wake you up as a last chance. It was the WDT that alerted me to this problem. The code would run fine for 5 or 10 minutes and then I'd enter my early warning ISR, see that not all was well, and reset. Turns out not all was well because I was taking too long sync'ing TC4's COUNT register.

 

I will give your suggestions a try and report back.

 

Thanks!

 

- Mark

Last Edited: Fri. Aug 26, 2016 - 12:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still no joy.

 

I re-checked the specs for the OSC32K and DFLL that I use. The OSC32K specs show it is safe to use as the source for creating the DFLL48M_REF. Furthermore, when run in closed loop mode the DFLL is guaranteed not to exceed 48MHz. So I don't think I can blame being out of spec on this problem. Just to be complete I did drop the DFLL to 24MHz and the same hang still occurs. My power supply is properly decoupled. I do not have the 1k pull-up on the SWCLK line but the debugger is attached when this happens. Not sure what the SAM-ICE does with this pin. I will see if I can add the pull-up and re-test.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Mark,

 

If you would like to take it offline to exchange notes, make plans, etc., feel free to PM me (pieter AT piconomic DOT co DOT za; or use my contact form here).

 

Can you produce the problem quickly on a SAMD21 Xplained Pro board? If so, I can submit it to Atmel for investigation. In my case I was only able to produce it on custom boards and it took 24 - 48 hours to produce (some times a whole week) and I got no joy out of Atmel's tier 1 support in India. If we can submit a working sample on one of their own dev boards, then I think we will get more joy.

 

Regards,

Pieter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pieter,

 

I can lock up the TC4 synchronizer with a very small example on the Xplained Pro board. I've sent this along to my FAE for investigation. I will post any new information when I get it.

 

Regards,

 

- Mark

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Pieter,

 

thanks for your reply and sorry for the late reply I had quite some work load the last weeks and after that I was on vacation.

 

 

I know about the firmware fix. That did not change too much for me. Also, I do not use the USB from inside my test program. I only use the USB to flash the MCU on the Xplained Pro. Not sure whether this already influences the power consumption.

 

Interestingly, we built our own circuitry which has the ATSAMR21B18-MZ210PA module (which includes the SAM R21) mounted. And there I was able to reach currents of around 110 µA. Still not the 2 ot 20 µA, but better as on the Xplained Pro.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pieter,

 

I have fixed many of my problems but I'm not completely sure why it fixes my problems.

 

My bugs:

1. I had improperly set my OSC32K source to run on-demand yet the RTC has no runstdby setting so it did not request the OSC32K to run.

2. I did not understand that WFI into standby will exit on any enabled interrupt even if PRIMASK is set to disable interrupt recognition. My systick interrupt was waking me up unexpectedly causing me to think sleep did not work with the debugger attached

 

Fixes:

1. Set OSC32K to run in standby so the RTC can keep ticking and ultimately wake me back up

2. I now have all drivers that have enabled interrupts, e.g. INTENSET values non-zero, register with my cpu_sleep() function to be called with a disable and later an enable callback just before and after executing WFI

 

Now I get no unexpected wakeups and things seem to be working fine. No more sync hangs either.

 

Hope this helps,

 

- Mark

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Mark,

 

Thanks for the valuable info regarding the CPU waking up from any enabled interrupt, even though interrupts are disabled in PRIMASK. That's news to me!

 

Please be aware that when the debugger is connected to the SAMD21, the CPU will wake up periodically and it won't stay in STANDBY sleep mode as expected. You can verify this by toggling a GPIO pin or LED. I have to disconnect the debugger when I want to perform power consumption measurements.

 

Regarding fix 2, I assume that you keep the RTC and EXTINT interrupts enabled to wake up the CPU, but there were other interrupts enabled that woke up the CPU unexpectedly and you disabled these?

 

Thank you! Your earlier post regarding the WDT has helped me so much. I was trying to identify the root cause of the CPU lock-up and did not search for a robust work-around. I have followed your advice and have enabled the WDT (running from OSCULP32K) to generate an early warning interrupt after 8 seconds. If the CPU does not wake up from STANDBY sleep mode and reset the WDT, then after a further 8 seconds the WDT will reset the CPU. This minimizes the power consumption impact , because the CPU stays in STANDBY sleep mode for most of the time and just wakes up briefly once every 8 seconds to keep the WDT happy and then it goes back to STANDBY sleep again.

 

I have performed the test and 2 out of 4 units locked-up within 24 hours, but the WDT was able to reset the CPU so that it could recover. When my code starts, it checks if a WDT reset occurred, and if so, it does not reset the RTC time, but keeps the existing value.

 

I would recommend that you also implement the same WDT mechanism, because even though it appears that the problem has gone away in your case, I suspect that under the proper "random" timing conditions, the CPU will still lock up and fail to wake up.

 

Regards,

Pieter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So the PRIMASK not affecting wake up makes sense. The Cortex-M0+ book shows how to write a very low latency wakeup handler by disabling interrupts, issuing the WFI, and then writing the wake up handler code right after the WFI instruction - cool!

 

I use OpenOCD v0.10 that I pull and build from their git repo. I do NOT have the problem you describe. If I free-run while sleeping it works just as if the debugger is not attached except that the clocks keep running internally.

 

I have a sleep/wake registration API I wrote to allow all drivers to get called back just before WFI and just after WFI. This allows me to stop/disable all interrupting drivers (including SYSTICK!) before going into standby. I also register the interrupt(s) that are allowed to wake up the CPU. Then I have a quick check after WFI to see why I woke up (interrupts are disabled so no vectoring) and if it's not the source I expect I go back to sleep. If it is the RTC I call all the registered wakeup handlers and re-enable interrupts. Works great!

 

As for the watchdog, I do disable the WDT early-warning interrupt so I don't wake up on it. The key is that if all is sane I feed the dog just before sleeping. The RTC will wake me up in time in this case. If things lockup the watchdog will still reset me because it's running off the OSCULP32K and is not dependent on PRIMASK. I've tested this and it works. So, I can't lock up now. But, if I do for some weird reason I still have my WDT to save me.

 

Regards,

 

- Mark

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mrfirmware wrote:

I use OpenOCD v0.10 that I pull and build from their git repo. I do NOT have the problem you describe.

 

The same for me: I am using OpenOCD from the git repos. Sleep states work as usual in debug mode. Of course, the power consumptions are different than the ones measured without a debugger attached.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

in my case, the MCU (samd21) was able to wake up from sleep, after the RTC interrupt, but didn't via external (GPIO) interrupt. The solution comes from the official documentation:

If filtering or edge detection is enabled, the EIC automatically requests the GCLK_EIC to operate
(GCLK_EIC must be enabled in the GCLK module, see GCLK – Generic Clock Controller for details). If
level detection is enabled, GCLK_EIC is not required, but interrupt and events can still be generated.

  page 367, SAMD21 datasheet

 

So I've switched to level detection, and external interrupt started to work without the clock mentioned in the datasheet. 

 

However an additional problem occurred, the level detection interrupt settings somehow blocked the gpio read functionality. My quick and dirty solution is to enable the ext.int before going to sleep, and disable it after waking up.

 

check out the project on hackaday: https://hackaday.io/project/2003...

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guys, 

Even I'm facing the hangs up issue after wave up from STANDBY mode, but in my case it seems like DMAC is creating a problem.

 

When I debugged the code after wave up the cpu stuck on waiting for DMAC callback.

 

Also my STANDBY current is not that low it is around 1MA.

 

My controller is SAMD21E16BU.

 

Kindly help and let me know if some issue already exist with solution.

 

 

                      

Last Edited: Sat. Jul 7, 2018 - 12:49 PM