SAMD51 Sleep Mode - USB problems

Hello everyone!

I'm using a SAMD51 board and currently trying to make it sleep to save some power. I'm using Adafruit_SleepyDog library to make it sleep and wakeup, with a basic code. The Built in LED is blinking like it should, meaning that the board is sleeping and waking it up. However, I can't access the USB after it wakes up.

// just to make sure that this isn't the problem
#define __SAMD51__
#define ARDUINO_ARCH_SAMD

#include <Adafruit_SleepyDog.h>


int times = 0;
int sleepMS = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake

  Serial.begin(115200);
  while(!Serial); // wait for Arduino Serial Monitor (native USB boards)
  Serial.println("Adafruit Watchdog Library Sleep Demo!");
  Serial.println();

}

void loop() {
  Serial.println("Going to sleep in one second...");
  delay(3000);

//    Serial.println("USBDevice.detach");
//    USBDevice.detach();
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  sleepMS = Watchdog.sleep(4000);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
    // Try to reattach USB connection on "native USB" boards (connection is
    // lost on sleep). Host will also need to reattach to the Serial monitor.
    // Seems not entirely reliable, hence the LED indicator fallback.
//    USBDevice.init();
//    USBDevice.attach();

  Serial.print("I'm awake now! I slept for ");
  Serial.print(sleepMS, DEC);
  Serial.println(" milliseconds.");
  Serial.println();
  times += 0;
}

I added some comments in the SleepyDog function to know where the USB problem happens. The USB connection happens after the __WFI(), that is when the board goes to sleep, and I do agree that this should happen. The problem is that the USB doesn't come back after it.

sleep: int WatchdogSAMD::sleep(int maxPeriodMS)
    enable: int WatchdogSAMD::enable(int maxPeriodMS, bool isForSleep)
        _initialize_wdt: Before USB->DEVICE.CTRLA.bit.ENABLE = 0;
        _initialize_wdt: After USB->DEVICE.CTRLA.bit.ENABLE = 1;
    enable: #if defined(__SAMD51__)
    enable: After maxPeriodMS and cycles
    enable: #if defined(__SAMD51__)
    enable: if (isForSleep)
sleep: #if defined(__SAMD51__)
sleep: before __DSB() and __WFI()

The next step was to add USBDevice.detach() before the board goes to sleep and USBDevice.init(); USBDevice.attach(); after it awakes. The only difference is that after the board awakes, the stop running and never sleeps again.

    Serial.println("USBDevice.detach");
    USBDevice.detach();
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  sleepMS = Watchdog.sleep(4000);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
    // Try to reattach USB connection on "native USB" boards (connection is
    // lost on sleep). Host will also need to reattach to the Serial monitor.
    // Seems not entirely reliable, hence the LED indicator fallback.
   USBDevice.init();
   USBDevice.attach();

To make sure that the problem isn't with the USBDevice, I removed the Watchdog and used a simple delay and it worked, the USB "goes out", wait for the delay and them "comes back" and print in the Serial Monitor.

  Serial.println("Going to sleep in three second...");
  delay(2500);
  
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  USBDevice.detach();
  delay(2500);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
  USBDevice.init();
  USBDevice.attach();
  delay(5000);

  Serial.print("I'm awake now! I slept for ");
  Serial.print(sleepMS, DEC);
  Serial.println(" milliseconds.");
  Serial.println();
  times += 0;

Are you sure your PC is connected to the SAMD21 board's Serial port, and not SerialUSB or Serial1?

What is shown connected in IDE as the com port? Normally should say 'Native' or 'Programming' port.

I use this SAMD51 port to upload code, read and write on the Serial Monitor and works just fine.

Also, as I told before, the USB.detach() -> USB.init() -> USB.attach(), works fine when is a delay before the init(). I can clearly see the Serial Monitor turn gray, when disabled and then white again.