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:
0:0751c92c0f71
Child:
1:7a48c475bbd2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Feb 07 03:18:40 2015 +0000
@@ -0,0 +1,117 @@
+/*
+ * mbed Application program
+ *      RTC (inside STM32x CPU) test program
+ *
+ * Copyright (c) 2015 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created: January   17th, 2015
+ *      Revised: Feburary   7th, 2015
+ *
+ * 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.
+ */
+
+//  Include ---------------------------------------------------------------------------------------
+#include "mbed.h"
+#include "TextLCD.h"
+#include "SetRTC.h"
+
+//  Definition ------------------------------------------------------------------------------------
+#define SHOW_KEY_PROMPT     30
+
+#define USE_LCD
+
+//  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
+
+//  RAM -------------------------------------------------------------------------------------------
+
+//  ROM / Constant data ---------------------------------------------------------------------------
+
+//  Function prototypes ---------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------------------
+//  Control Program
+//-------------------------------------------------------------------------------------------------
+int main()
+{
+    char buf[42];               // data buffer for text
+    time_t seconds;
+    uint8_t counter = SHOW_KEY_PROMPT;
+
+#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");
+    // waiting for Initial screen
+    myled = 1;
+    wait(1.0);
+    myled = !myled;
+    wait(1.0);
+    myled = !myled;
+    if (SetRTC() == OK) {
+        pc.printf("External Xtal for RTC\r\n");
+    } else {
+        pc.printf("Internal Xtal for RTC\r\n");
+    }
+    show_RTC_reg(); // only for debug purpose
+    while(1) {
+        myled = !myled;
+        seconds = time(NULL);
+        strftime(buf, 40, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
+        pc.printf("[Time] %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
+        if (counter){
+            --counter;
+            //      012345678901234567890123456789012345678901234567890123456789012
+            pc.printf("Is time correct? If okay, nothing. If not, please hit any key.\r");
+            wait(1.0);
+            if (pc.readable() == 1){
+                buf[0] = pc.getc();  // dummy read
+                time_enter_mode();
+                counter = SHOW_KEY_PROMPT;
+            }
+            pc.printf("                                                                 \r");
+        } else {
+            wait(1.0);
+        }
+        if (userSW == 0){
+#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("\r\nEnter Deep Sleep Mode, please push RESET to wake-up\r\n");
+            wait(1.0);
+            myled = 0;       
+            deepsleep();
+        }
+    }
+}