Hello
We’ve been testing the Autonomo with the deep sleep mode (__WFI()
) and we are facing the following issue:
- the SerialUSB connection works fine after boot, in both directions (read/write)
- we are putting the device to sleep (after a timeout, for example)
- we are triggering an interrupt to wake up the device
- after the wake up, the SerialUSB connection freezes on read
Here is the code we are using for testing:
#define SLEEP_PIN A10
volatile unsigned long last_act_time = 0;
void interruptButton() {
last_act_time = millis();
}
void setup() {
pinMode(SLEEP_PIN, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
attachInterrupt(digitalPinToInterrupt(SLEEP_PIN), interruptButton, FALLING);
// Set the XOSC32K to run in standby
SYSCTRL->XOSC32K.bit.RUNSTDBY = 1;
// Configure EIC to use GCLK1 which uses XOSC32K
// This has to be done after the first call to attachInterrupt()
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) |
GCLK_CLKCTRL_GEN_GCLK1 |
GCLK_CLKCTRL_CLKEN;
//Set sleep mode
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
}
void loop() {
if(millis() - last_act_time > 10000) {
digitalWrite(LED_BUILTIN, LOW);
//Enter sleep mode
USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE; // disable USB
__WFI(); // wait for interrupt
USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE; // enable USB
digitalWrite(LED_BUILTIN, HIGH);
}
while(SerialUSB.available()) {
SerialUSB.write(SerialUSB.read());
}
}
Is there anything we are doing wrong?
Thank you
To be more precise, the processor doesn’t actually freeze, but the serial console freezes (or crashes, depending on the application I’m using). When I’m reconnecting, the serial text coming from the device still appears to be flowing normally, but when I try to send a text to the device, it again crashes the console (and, of course, no text arrives to the device).
This happens after a deep sleep cycle. Could it be something related with the SerialUSB being disabled and then re-enabled?
Can you please confirm this is reproducible?
Thank you
The SerialUSB stream uses the USB peripheral of the SAMD21. This is an internal component which ordinarily has it’s clock stopped when entering deep sleep. (It is likely possible that you can keep the USB running during sleep, however, due to the clock speed the current consumption would probably be close to that of device when awake.)
When the SAMD21 enters sleep the clocks to most of the internal peripherals are stopped. In the case of the USB peripheral, this results in the closure of any connection with the host machine. If you want the connection to be closed gracefully, you need to disable the USB before entering sleep mode.
If you have a terminal emulator running, the session will end when the device enters sleep. A new session will not automatically be created when the device wakes up, unless the terminal program you are using has an auto-reconnect feature. You will also get similar behaviour if you reset the device, the terminal session will close.
This is different to the AVR based Arduino boards which have an external UART->USB chip (like an FTDI or similar). That chip remains running even if the main MCU enters sleep or gets reset.
Yes, I understood the different behavior of the sessions. The problem is that after deep sleep, when I restart the terminal and try to start a NEW session, that session works only one-way: from the device to the terminal. I can’t send any data to the device; when I try to send any data (characters) to the device, it freezes the terminal (or it just won’t do anything) and no data arrives to the device.
That is strange, I have not seen that issue before. What terminal program are you using?
Also how long is the device staying awake between sleep cycles?
Also, are you making any calls to enable/disable the USB component before/after enter sleep?
If so I would try it without those and just using the__WFI() call.
I’ve been using different terminals: Br@y terminal, the Arduino serial console and also an in-house built terminal. They all behave similarly.
The test app I’ve been using on the device is the one in my first post. I tried removing the instructions that disable and enable the USB, but to no avail.
The device is staying awake for 10 seconds between sleep cycles. See the logic in the code above.
If someone could test this code and confirm that the serial USB connection works both ways after a sleep cycle, then it must be something with my device or with the computer I’m using for testing.
I’ve just tested it now with a terminal program with auto-reconnect (Visual-Micro’s Terminal window with Atmel Studio). I was able to echo back any text I sent showing that two way communication was working (at least on my machine).
Sorry I couldn’t help more with this. However, I would recommend that you reconsider using the USB in this way. In general the USB plus sleep don’t play well together. Additionally, if you are logging over SerialUSB (debug etc), you will also run into issues whenever the board gets reset.
That’s great. It means it is either the computer having an issue with the COM port, or with the actual device not getting enough power or having some strange fault.
Thank you for your help.
Best regards,
Bogdan Irimia