Solution how to fix broken RTC on Nucleo_F103RB / STM32F103 BluePill etc..

Dependencies:   mbed-dev

Fork of Nucleo_RTC_battery_bkup_pwr_off_okay by Kenji Arai

Experimental fork https://os.mbed.com/users/kenjiArai/code/Nucleo_RTC_battery_bkup_pwr_off_okay/ to fix broken RTC on Nucleo_F103RB / STM32F103 BluePill etc..

At this moment (7/11/17) use forked mbed-dev https://os.mbed.com/users/maxxir/code/mbed-dev/.

Or require patch for ./mbed-dev/targets/TARGET_STM/rtc_api.c.

You can manual add to your project fresh mbed-dev and change file mbed-dev\targets\TARGET_STM\rtc_api.c from root project patched rtc_api.c.stm32f10x.txt.

Exploring origin errors, I saw that something wrong with HAL API on STM32F1xx with this functions:

 HAL_RTC_GetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN);

 HAL_RTC_GetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN);


 HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN);

 HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN);

Look here (as I understand it possible broken on STM32CUBE HAL level now):

https://community.st.com/thread/43218-stm32f103-loss-rtc-date-when-reset

So I use direct RTC register manipulation for STM32F1xx:

rtc_read(), rtc_write() (native rtc_init() - works good).

Also added stub for non-working on STM32F1xx rtc_read_subseconds().

Now the stm32F103 can survive power off, and allows you to get and set the time.

Tested OK on boards:

NUCLEO STM32F103RB, DIY STM32F100CB (forked from DISCO_F100RB)

Happy coding!

maxxir

10/11/17

Revision:
8:bf593344668e
Parent:
7:27a1cf7f8921
Child:
9:6a64b0207f72
--- a/main.cpp	Fri May 27 20:19:49 2016 +0000
+++ b/main.cpp	Sat Jul 02 03:08:52 2016 +0000
@@ -6,7 +6,7 @@
  *  http://www.page.sannet.ne.jp/kenjia/index.html
  *  http://mbed.org/users/kenjiArai/
  *      Created: January   17th, 2015
- *      Revised: May       28th, 2016
+ *      Revised: July       2nd, 2016
  *
  * 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
@@ -22,15 +22,20 @@
 #include "SetRTC.h"
 
 //  Definition ------------------------------------------------------------------------------------
-#define SHOW_KEY_PROMPT     30
-
 //#define USE_LCD
 
 #if (defined(TARGET_STM32F401RE) || defined(TARGET_STM32F411RE) \
   || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F334R8) \
-  || defined(TARGET_STM32L476RG) )
+  || defined(TARGET_STM32L476RG) \
+  || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) )
 #else
-#error "Target is only Nucleo F401RE, F411RE, F334R8, L476RG and L152RE"
+#error "Target is only Nucleo F401RE, F411RE, F334R8, F746xx, L476RG and L152RE"
+#endif
+
+#if (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG))
+#define PUSHED_SW   1   // Active high
+#else
+#define PUSHED_SW   0   // Active low
 #endif
 
 //  Object ----------------------------------------------------------------------------------------
@@ -46,7 +51,12 @@
 //  RAM -------------------------------------------------------------------------------------------
 
 //  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 ---------------------------------------------------------------------------
 
 //-------------------------------------------------------------------------------------------------
@@ -54,9 +64,8 @@
 //-------------------------------------------------------------------------------------------------
 int main()
 {
-    char buf[42];               // data buffer for text
+    char buf[64];               // data buffer for text
     time_t seconds;
-    uint8_t counter = SHOW_KEY_PROMPT;
     uint8_t wait_counter = 0;
     uint8_t xtal = 0;
 
@@ -90,7 +99,7 @@
     wait(1.0);
     while(1) {
         seconds = time(NULL);
-        strftime(buf, 40, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
+        strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
         if (xtal){
             pc.printf("[Time] %s", buf);
         } else {
@@ -104,18 +113,15 @@
         strftime(buf, 10, "%H:%M:%S", localtime(&seconds));
         lcd.printf(buf);
 #endif
-        --counter;
-        if (counter){
-            //         012345678901234567890123456789012345678901234567890123456789012
-            pc.printf("Is a time correct? If no, please hit any key for adjustment.\r");
-        }
+        pc.printf(msg0);
+        pc.printf("%s\r", msg1);
         wait_counter = 0;
         while (seconds == time(NULL)){
             if (pc.readable() == 1){
                 buf[0] = pc.getc();  // dummy read
                 time_enter_mode();
             }
-            if (userSW == 0){
+            if (userSW == PUSHED_SW){
 #if defined(USE_LCD)
                 lcd.locate(0, 0);    // 1st line top
                 //          12345678
@@ -124,8 +130,7 @@
                 //          12345678
                 lcd.printf("  Sleep " );
 #endif
-                //             123456789012345678901234567890123456789012345678
-                pc.printf("\r\nEnter Standby Mode, please push RESET to wake-up\r\n");
+                pc.printf(msg2);
                 wait(1.0);
                 myled = 0;
                 goto_standby();
@@ -133,17 +138,18 @@
             wait(0.05);
             if (++wait_counter > (2000 / 50)){
                 if (xtal){
-                    pc.printf("Time was not updated! External Xtal does NOT oscillate.\r\n");
+                    pc.printf(msg3);
                 } else {
-                    pc.printf("Time was not updated! LSI does NOT work.\r\n");
+                    pc.printf(msg4);
                 }
                 break;
             }
         }
-        if (counter){
-            //         12345678901234567890123456789012345678901234567890
-            pc.printf("                                                  \r"); // Not use '\n'
+        uint8_t n = strlen(msg0) + strlen(msg1);
+        for (uint8_t i = 0; i < n; i++){
+            pc.putc(' ');
         }
+        pc.printf("      \r"); // Not use '\n'
         myled = !myled;
     }
 }