Kenji Arai / Mbed OS Nucleo_RTC_battery_bkup_pwr_off_okay
Revision:
9:6a64b0207f72
Parent:
8:bf593344668e
Child:
10:806cfec92eb6
--- a/main.cpp	Sat Jul 02 03:08:52 2016 +0000
+++ b/main.cpp	Mon Jan 16 09:38:03 2017 +0000
@@ -2,96 +2,88 @@
  * mbed Application program
  *      RTC (inside STM32x CPU) test program
  *
- * Copyright (c) 2015,'16 Kenji Arai / JH1PJL
+ * Copyright (c) 2015,'16,'17 Kenji Arai / JH1PJL
  *  http://www.page.sannet.ne.jp/kenjia/index.html
  *  http://mbed.org/users/kenjiArai/
  *      Created: January   17th, 2015
- *      Revised: July       2nd, 2016
+ *      Revised: January   16th, 2017
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*  mbed library now suports RTC continuous operation at Reset & Power ON/OFF
+    --------------------------------------------------------------------------
+    In the past, rtc_api.c (inside mbed) alway made a reset RTC registers
+    when user push a reset buttom or terninate a power.
+    Even if user configures a back-up circuit for RTC, mbed board could not
+    keep proper time.
+    I have checked mbed rev.133 and mbed-dev rev.155.
  */
 
-//  Include ---------------------------------------------------------------------------------------
-#include "mbed.h"
-#include "TextLCD.h"
- // MUST -> need to modify rtc_api.c, please refer SetRTC.h file [CAUTION] and modify_info_xxx.h
-#include "SetRTC.h"
-
-//  Definition ------------------------------------------------------------------------------------
-//#define USE_LCD
+/*
+    ----- Tested board -----
+                  / Reset: / Stanby: / power off and restart:
+    Nucleo-F401RE /  ok    /  ok     / ok (need following Back-up Circuit)
+    Nucleo-F411RE /  ok    /  ok     / ok (need following Back-up Circuit)
+    Nucleo-F446RE /  ok    /  ok     / ok (need following Back-up Circuit)
+    Nucleo-F334R8 /  ok    /  ok     / ok (need following Back-up Circuit)
+    Nucleo-L476RG /  ok    /  ok     / ok (need following Back-up Circuit)
+    Nucleo-L152RE /  ok    /  ok     / no check (Need additional hardware)
+    Nucleo-L073RZ /  ok    /  ok     / no check (Need additional hardware)
+    Nucleo-L053R8 /  ok    /  ok     / no check (Need additional hardware)
 
-#if (defined(TARGET_STM32F401RE) || defined(TARGET_STM32F411RE) \
-  || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F334R8) \
-  || defined(TARGET_STM32L476RG) \
-  || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) )
-#else
-#error "Target is only Nucleo F401RE, F411RE, F334R8, F746xx, L476RG and L152RE"
-#endif
+    < Back-up circuit >
+    CN7 VIN <- SBD <- 330 Ohm <- CR2032 + - -> CN7 GND
+    Remove SB45 Zero Ohm resistor
+ */
 
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+
+//  Definition -----------------------------------------------------------------
 #if (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG))
 #define PUSHED_SW   1   // Active high
 #else
 #define PUSHED_SW   0   // Active low
 #endif
 
-//  Object ----------------------------------------------------------------------------------------
+//  Object ---------------------------------------------------------------------
 DigitalIn userSW(USER_BUTTON);
 DigitalOut myled(LED1);         // Indicate the sampling period
 Serial pc(USBTX, USBRX);
-#if defined(USE_LCD)
-I2C i2c(D14,D15);               // SDA, SCL
-TextLCD_I2C_N lcd(&i2c, 0x7c, TextLCD::LCD8x2);  // LCD(Akizuki AQM0802A)
-#endif
-DigitalOut pwr_onoff(PA_9);
 
-//  RAM -------------------------------------------------------------------------------------------
+//  RAM ------------------------------------------------------------------------
 
-//  ROM / Constant data ---------------------------------------------------------------------------
+//  ROM / Constant data --------------------------------------------------------
 char *const msg0 = "Is a time correct? If no, please hit any key. ";
 char *const msg1 = "<Push USER SW then enter sleep mode> ";
 char *const msg2 = "\r\nEnter Standby Mode, please push RESET to wake-up\r\n";
-char *const msg3 = "Time was not updated! External Xtal does NOT oscillate.\r\n";
-char *const msg4 = "Time was not updated! LSI does NOT work.\r\n";
-                
-//  Function prototypes ---------------------------------------------------------------------------
 
-//-------------------------------------------------------------------------------------------------
+//  Function prototypes --------------------------------------------------------
+static void time_enter_mode(void);
+static void chk_and_set_time(char *ptr);
+static void goto_standby(void);
+static int xatoi (char **str, unsigned long *res);
+static void get_line (char *buff, int len);
+
+//------------------------------------------------------------------------------
 //  Control Program
-//-------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 int main()
 {
     char buf[64];               // data buffer for text
     time_t seconds;
     uint8_t wait_counter = 0;
-    uint8_t xtal = 0;
 
-    pwr_onoff = 1;
     wait(2.0);
-#if defined(USE_LCD)
-    // lcd
-    lcd.locate(0, 0);    // 1st line top
-    //          12345678
-    lcd.printf("  RTC   ");
-    lcd.locate(0, 1);    // 2nd line top
-    //        12345678
-    lcd.puts(" JH1PJL ");
-    lcd.setContrast(0x14);
-#endif
     pc.printf("\r\n\r\nTest Nucleo RTC Function\r\n");
     myled = !myled;
-    if (SetRTC(0) == 1) {
-        pc.printf("External");
-        xtal = 1;
-    } else {
-        pc.printf("Internal");
-        xtal = 0;
-    }
-    pc.printf(" Xtal for RTC\r\n");
-    show_RTC_reg(); // only for debug purpose
     // waiting for Initial screen
     myled = 1;
     wait(1.0);
@@ -100,19 +92,7 @@
     while(1) {
         seconds = time(NULL);
         strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
-        if (xtal){
-            pc.printf("[Time] %s", buf);
-        } else {
-            pc.printf("[Time by Internal Clock] %s", buf);
-        }
-#if defined(USE_LCD)
-        lcd.locate(0, 0);    // 1st line top
-        strftime(buf, 40, "%b%d'%y", localtime(&seconds));
-        lcd.printf(buf);
-        lcd.locate(0, 1);    // 2nd line top
-        strftime(buf, 10, "%H:%M:%S", localtime(&seconds));
-        lcd.printf(buf);
-#endif
+        pc.printf("[Time] %s", buf);
         pc.printf(msg0);
         pc.printf("%s\r", msg1);
         wait_counter = 0;
@@ -122,14 +102,6 @@
                 time_enter_mode();
             }
             if (userSW == PUSHED_SW){
-#if defined(USE_LCD)
-                lcd.locate(0, 0);    // 1st line top
-                //          12345678
-                lcd.printf(" Enter  ");
-                lcd.locate(0, 1);    // 2nd line top
-                //          12345678
-                lcd.printf("  Sleep " );
-#endif
                 pc.printf(msg2);
                 wait(1.0);
                 myled = 0;
@@ -137,11 +109,6 @@
             }
             wait(0.05);
             if (++wait_counter > (2000 / 50)){
-                if (xtal){
-                    pc.printf(msg3);
-                } else {
-                    pc.printf(msg4);
-                }
                 break;
             }
         }
@@ -153,3 +120,157 @@
         myled = !myled;
     }
 }
+
+void time_enter_mode(void)
+{
+    char *ptr;
+    char linebuf[64];
+
+    pc.printf("\r\nSet time into RTC\r\n");
+    pc.printf(" e.g. >17 1 16 20 55 23 -> January 16th,'17, 20:55:23\r\n");
+    pc.printf(" If time is fine, just hit enter\r\n");
+    pc.putc('>');
+    ptr = linebuf;
+    get_line(ptr, sizeof(linebuf));
+    pc.printf("\r");
+    chk_and_set_time(ptr);
+}
+
+void goto_standby(void)
+{
+    deepsleep();   // Not Standby Mode but Deep Sleep Mode
+}
+
+//  Change string -> integer
+int xatoi (char **str, unsigned long *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    while ((c = **str) == ' ') (*str)++;
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                }   else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') c -= 0x20;
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) return 0;
+        }
+        if (c >= radix) return 0;
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) val = -val;
+    *res = val;
+    return 1;
+}
+
+//  Get key input data
+void get_line (char *buff, int len)
+{
+    char c;
+    int idx = 0;
+
+    for (;;) {
+        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.putc('\n');
+}
+
+void chk_and_set_time(char *ptr)
+{
+    unsigned long 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);
+    // Show Time with several example
+    // ex.1
+    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
+    );
+#if 0
+    time_t seconds;
+    char buf[40];
+
+    seconds = mktime(&t);
+    // ex.2
+    strftime(buf, 40, "%x %X", localtime(&seconds));
+    pc.printf("Date: %s\r\n", buf);
+    // ex.3
+    strftime(buf, 40, "%I:%M:%S %p (%Y/%m/%d)", localtime(&seconds));
+    pc.printf("Date: %s\r\n", buf);
+    // ex.4
+    strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds));
+    pc.printf("Date: %s\r\n", buf);
+#endif
+}