Check Deepsleep mode on OS6.6.0

/users/kenjiArai/notebook/standby-mode-current-consumption-on-nucleo-f446re/

IDD Jumper(JP6)
ModeMbed-OSBoardIDD Current(sleep)IDD Current(Normal(*1))
DeepSleep0s5.15.1Nucleo-L152RE4.23uA5mA to 8mA
^0s6.6.0^4.22uA4mA to 7mA
StandBy0s5.15.1^3.90uA4mA to 7mA
^0s6.6.0^3.90uA4mA to 7mA
DeepSleep0s5.15.1Nucleo-L476RG2.13uA7mA to 10mA
^0s6.6.0^2.23uA7mA to 10mA
StandBy0s5.15.1^-uA(*2)-mA(*2)
^0s6.6.0^-uA(*2)-mA(*2)
DeepSleep0s5.15.1Nucleo-F411RE1.91mA(*3)7mA to 10mA
^0s6.6.0^1.65mA(*3)7mA to 10mA
StandBy0s5.15.1^3.35uA7mA to 10mA
^0s6.6.0^3.40uA7mA to 9mA
DeepSleep0s5.15.1Nucleo-F446RE1.67mA(*3)14mA to 17mA
^0s6.6.0^1.76mA(*3)14mA to 16mA
StandBy0s5.15.1^3.42uA14mA to 17mA
^0s6.6.0^3.42uA14mA to 16mA

(*1)-> LED1 Blinky every 1sec and change LED1 current
(*2)-> Could NOT make proper program and could NOT measure
(*3)-> NOT uA but mA
All Nucleo boards are stand alone condition(not additional circuit).
Equipment: DMM6500

/users/kenjiArai/code/Check_DeepSleep_os5/
/users/kenjiArai/code/Check_DeepSleep_os6/
/users/kenjiArai/code/Check_StandBy_os5/
/users/kenjiArai/code/Check_StandBy_os6/

Revision:
1:2831faae6ef1
Parent:
0:f8c5c7d19d9a
--- a/main.cpp	Thu Mar 12 09:19:48 2020 +0000
+++ b/main.cpp	Fri Jan 15 07:31:54 2021 +0000
@@ -2,33 +2,45 @@
  * Mbed Application program
  *  Check Deep Sleep Mode
  *
- * Copyright (c) 2020 Kenji Arai / JH1PJL
+ * Copyright (c) 2020,'21 Kenji Arai / JH1PJL
  *  http://www7b.biglobe.ne.jp/~kenjia/
  *  https://os.mbed.com/users/kenjiArai/
  *      Revised:    March     12th, 2020
- *      Revised:    March     12th, 2020
+ *      Revised:    January   15th, 2021
  */
 
 /*
     Reference information:
+        https://os.mbed.com/docs/mbed-os/v6.6/apis/power-management-sleep.html
         https://forums.mbed.com/t/how-to-deep-sleep/7551
 
-    Tested on
-        Nucleo-L152RE       -> less than 20uA
-        Nucleo-F446RE       -> 1.5mA
+    Tested on with mbed-os5.15.1
+        https://os.mbed.com/users/kenjiArai/code/Check_DeepSleep_os5/
+        Nucleo-L152RE       -> 4.23uA (Normal run = 5mA to 8mA)
+        Nucleo-L476RG       -> 2.13uA (Normal run = 7mA to 10mA)
+        Nucleo-F411RE       -> 1.91mA (not uA)(Normal run = 7mA to 10mA)
+        Nucleo-F446RE       -> 1.67mA (not uA)(Normal run = 14mA to 17mA)
+    Tested on with mbed-os6.6.0
+        Nucleo-L152RE       -> 4.22uA (Normal run = 4mA to 7mA)
+        Nucleo-L476RG       -> 2.23uA (Normal run = 7mA to 10mA)
+        Nucleo-F411RE       -> 1.65mA (not uA)(Normal run = 7mA to 10mA)
+        Nucleo-F446RE       -> 1.76mA (not uA)(Normal run = 14mA to 16mA)
+
+        Current Measurement:
+         Nucleo board has IDD Jumper (JP6).
+         I measured CPU current using Digital Multi-meter DCI mode.
  */
 
 //  Include --------------------------------------------------------------------
 #include "mbed.h"
 
 //  Definition -----------------------------------------------------------------
-//      https://keisan.casio.jp/exec/system/1526003938
-#define DATE_20200222_222222    1582377742      // 2020/2/22 22:22:22              
+#define MODE    1   // MODE=3 does NOT work due to wait_ms() is abolished 
 
 //  Constructor ----------------------------------------------------------------
 DigitalIn   my_sw(USER_BUTTON);
 DigitalOut  myled(LED1,1);
-Serial      pc(USBTX, USBRX);
+static BufferedSerial pc(USBTX, USBRX, 9600);
 AnalogIn    a_in(A0);
 Timer       t;
 
@@ -42,7 +54,7 @@
 void time_enter_mode(void);
 void chk_and_set_time(char *ptr);
 int32_t  xatoi (char **str, int32_t *res);
-void get_line (char *buff, int len);
+void get_line (char *buff, int32_t len);
 void print_revision(void);
 
 //------------------------------------------------------------------------------
@@ -58,38 +70,58 @@
 
     printf("\r\nCheck current consumption at Deep-sleep mode.\r\n");
     print_revision();
+#if   MODE == 1
+    printf("-->MODE=1 --> Use ThisThread::sleep_for() function.\r\n");
+#elif MODE == 2
+    printf("-->MODE=2 --> Use thread_sleep_for() function.\r\n");
+#elif MODE == 3
+    printf("-->MODE=3 --> Use wait_ms() function.\r\n");
+#endif
     seconds = time(NULL);
-    if (seconds < DATE_20200222_222222) {
-        strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
-        pc.printf("[Time] %s\r\n", buf);
-        time_enter_mode();
-    }
     while (my_sw == 0) {;}
-    ThisThread::sleep_for(10);
+    ThisThread::sleep_for(10ms);
     while (true) {
         t.reset();
         t.start();
-        if ((my_sw == 0) || (loop_count > 20)) {
+        if ((my_sw == 0) || (loop_count > 10)) {
             LowPowerConfiguration();
             InterruptIn my_irq(USER_BUTTON);
             while (my_irq.read() == 0) {;}
-            ThisThread::sleep_for(100);
+            ThisThread::sleep_for(100ms);
             my_irq.fall(sw_irq);
             t.stop();
-            ThisThread::sleep_for(10000);
+            //------------ IMPORTANT-------------------
+            // 1) removes the receive interrupt handler
+            pc.enable_input(false);
+            // 2) and releases the deep sleep lock
+            sleep_manager_can_deep_sleep();
+            // 3) then enter Deep Sleep mode
+#if   MODE == 1
+            ThisThread::sleep_for(10s);
+#elif MODE == 2
+            thread_sleep_for(10000);
+#elif MODE == 3
+            wait_ms(10000);
+#endif
             system_reset();
         }
         ain = a_in.read();
         myled = !myled;
         seconds = time(NULL);
         strftime(buf, 50, "%H:%M:%S -> ", localtime(&seconds));
-        pc.printf("%s", buf);
-        pc.printf(
-            "analog = %4.3f, loop_time=%3d, counter=%4d\r\n",
+        printf("%s", buf);
+        printf(
+            "analog = %4.3f, processing time=%3d, counter=%4d\r\n",
             ain, t_pass, loop_count++
         );
-        t_pass = t.read_ms();
-        ThisThread::sleep_for(1000 - t_pass);
+        t_pass = chrono::duration_cast<chrono::milliseconds>(
+                               t.elapsed_time()).count();
+        ThisThread::sleep_for(chrono::milliseconds(1000 - t_pass));
+        if (pc.readable()) {
+            strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
+            printf("[Time] %s\r\n", buf);
+            time_enter_mode();
+        }
     }
 }
 
@@ -105,6 +137,8 @@
     RCC->AHBENR |=
         (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
          RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
+#elif defined(TARGET_NUCLEO_L476RG)
+
 #elif defined(TARGET_NUCLEO_F446RE)
     RCC->AHB1ENR |=
         (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN |
@@ -126,18 +160,22 @@
     RCC->AHBENR &=
         ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |RCC_AHBENR_GPIOCEN |
           RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
+#elif defined(TARGET_NUCLEO_L476RG)
+    RCC->AHB1ENR = 0;
+    RCC->AHB2ENR = 0;
+    RCC->AHB3ENR = 0;
+    RCC->APB1ENR2 = 0;
+    RCC->APB2ENR = 0;
 #elif defined(TARGET_NUCLEO_F446RE)
-    RCC->AHB1ENR &=
-        ~(RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN |
-          RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOHEN);
-    __HAL_RCC_TIM1_CLK_DISABLE();
-    __HAL_RCC_USART1_CLK_DISABLE();
-    __HAL_RCC_USART6_CLK_DISABLE();
-    __HAL_RCC_ADC1_CLK_DISABLE();
-    __HAL_RCC_SPI1_CLK_DISABLE();
-    __HAL_RCC_SYSCFG_CLK_DISABLE();
-    __HAL_RCC_TIM9_CLK_DISABLE();
-    __HAL_RCC_TIM11_CLK_DISABLE();
+    RCC->AHB1ENR = 0;
+    RCC->AHB2ENR = 0;
+    RCC->AHB3ENR = 0;
+    RCC->APB1ENR = 0x8;     // alive TIM5
+    RCC->APB2ENR = 0;
+    RCC->AHB1LPENR = 0;
+    RCC->AHB2LPENR = 0;
+    RCC->APB1LPENR = 0x8;   // alive TIM5
+    RCC->APB2LPENR = 0;
 #endif
 }
 
@@ -146,84 +184,26 @@
     char *ptr;
     char linebuf[64];
 
-    pc.printf("\r\nSet time into RTC\r\n");
-    pc.printf(" e.g. >20 2 22 22 22 22 -> February 22,'20, 22:22:22\r\n");
-    pc.putc('>');
+    if (pc.readable()) {
+        pc.read(linebuf, 1);    // dummy read
+    }
+    puts("\r\nSet time into RTC");
+    puts(" e.g. >21 1 12 13 14 15 -> January 12,'21, 13:14:14");
+    linebuf[0] = '>';
+    pc.write(linebuf, 1);
     ptr = linebuf;
     get_line(ptr, sizeof(linebuf));
-    pc.printf("\r");
+    puts("\r");
     chk_and_set_time(ptr);
 }
 
-void get_line (char *buff, int len)
-{
-    char c;
-    uint32_t idx = 0;
-
-    while(true) {
-        c = pc.getc();
-        if (c == '\r') {
-            buff[idx++] = c;
-            break;
-        }
-        if ((c == '\b') && idx) {
-            idx--;
-            pc.putc(c);
-            pc.putc(' ');
-            pc.putc(c);
-        }
-        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
-            buff[idx++] = c;
-            pc.putc(c);
-        }
-    }
-    buff[idx] = 0;
-    pc.puts("\r\n");
-}
-
-void chk_and_set_time(char *ptr)
+//  Change string -> integer
+int32_t xatoi(char **str, int32_t *res)
 {
-    int32_t p1;
-    struct tm t;
-    time_t seconds;
-
-    if (xatoi(&ptr, &p1)) {
-        t.tm_year       = (uint8_t)p1 + 100;
-        pc.printf("Year:%d ",p1);
-        xatoi( &ptr, &p1 );
-        t.tm_mon        = (uint8_t)p1 - 1;
-        pc.printf("Month:%d ",p1);
-        xatoi( &ptr, &p1 );
-        t.tm_mday       = (uint8_t)p1;
-        pc.printf("Day:%d ",p1);
-        xatoi( &ptr, &p1 );
-        t.tm_hour       = (uint8_t)p1;
-        pc.printf("Hour:%d ",p1);
-        xatoi( &ptr, &p1 );
-        t.tm_min        = (uint8_t)p1;
-        pc.printf("Min:%d ",p1);
-        xatoi( &ptr, &p1 );
-        t.tm_sec        = (uint8_t)p1;
-        pc.printf("Sec: %d \r\n",p1);
-    } else {
-        return;
-    }
-    seconds = mktime(&t);
-    set_time(seconds);
-    pc.printf(
-        "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
-        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
-    );
-}
-
-int32_t xatoi (char **str, int32_t *res)
-{
-    int32_t val;
+    uint32_t val;
     uint8_t c, radix, s = 0;
 
-    while ((c = **str) == ' ') {
-        (*str)++;
-    }
+    while ((c = **str) == ' ') (*str)++;
     if (c == '-') {
         s = 1;
         c = *(++(*str));
@@ -244,7 +224,7 @@
             } else {
                 if ((c >= '0')&&(c <= '9')) {
                     radix = 8;
-                } else {
+                }   else {
                     return 0;
                 }
             }
@@ -257,25 +237,96 @@
     }
     val = 0;
     while (c > ' ') {
-        if (c >= 'a') {
-            c -= 0x20;
-        }
+        if (c >= 'a') c -= 0x20;
         c -= '0';
         if (c >= 17) {
             c -= 7;
-            if (c <= 9) {
-                return 0;
-            }
+            if (c <= 9) return 0;
         }
-        if (c >= radix) {
-            return 0;
-        }
+        if (c >= radix) return 0;
         val = val * radix + c;
         c = *(++(*str));
     }
-    if (s) {
-        val = -val;
-    }
+    if (s) val = -val;
     *res = val;
     return 1;
 }
+
+//  Get key input data
+void get_line(char *buff, int32_t len)
+{
+    char c;
+    char bf[8];
+    int32_t idx = 0;
+
+    for (;;) {
+        pc.read(bf, 1);
+        c = bf[0];
+        //printf("0x%x \r\n", c);
+        if (c == '\r') {
+            buff[idx++] = c;
+            break;
+        }
+        if ((c == '\b') && idx) {
+            idx--;
+            const char bf_bs[] =
+            {0x1b, '[', '1', 'D', ' ', 0x1b, '[', '1', 'D'};
+            pc.write(bf_bs, 9);
+        }
+        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
+            buff[idx++] = c;
+            pc.write(bf, 1);
+        }
+    }
+    buff[idx] = 0;
+    bf[0] = '\n';
+    pc.write(bf, 1);
+}
+
+//  Check key input strings and set time
+void chk_and_set_time(char *ptr)
+{
+    int32_t p1;
+    struct tm t;
+    time_t seconds;
+
+    if (xatoi(&ptr, &p1)) {
+        t.tm_year       = (uint8_t)p1 + 100;
+        printf("Year:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mon        = (uint8_t)p1 - 1;
+        printf("Month:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mday       = (uint8_t)p1;
+        printf("Day:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_hour       = (uint8_t)p1;
+        printf("Hour:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_min        = (uint8_t)p1;
+        printf("Min:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_sec        = (uint8_t)p1;
+        printf("Sec: %d \r\n",p1);
+    } else {
+        return;
+    }
+    seconds = mktime(&t);
+    set_time(seconds);
+    // Show Time with several example
+    // ex.1
+    printf(
+        "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
+        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
+    );
+    char buf[64];
+    // ex.2
+    strftime(buf, 40, "%x %X", localtime(&seconds));
+    printf("Date: %s\r\n", buf);
+    // ex.3
+    strftime(buf, 40, "%I:%M:%S %p (%Y/%m/%d)", localtime(&seconds));
+    printf("Date: %s\r\n", buf);
+    // ex.4
+    strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds));
+    printf("Date: %s\r\n", buf);
+}