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

Committer:
kenjiArai
Date:
Fri Jan 29 07:51:04 2016 +0000
Revision:
6:5ada291037aa
Parent:
5:bc464a588c2e
Child:
7:27a1cf7f8921
Use mbed-dev lib. (old rev. -> use mbed-src)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:0751c92c0f71 1 /*
kenjiArai 0:0751c92c0f71 2 * mbed Application program
kenjiArai 0:0751c92c0f71 3 * RTC (inside STM32x CPU) test program
kenjiArai 0:0751c92c0f71 4 *
kenjiArai 0:0751c92c0f71 5 * Copyright (c) 2015 Kenji Arai / JH1PJL
kenjiArai 0:0751c92c0f71 6 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:0751c92c0f71 7 * http://mbed.org/users/kenjiArai/
kenjiArai 0:0751c92c0f71 8 * Created: January 17th, 2015
kenjiArai 5:bc464a588c2e 9 * Revised: May 24th, 2015
kenjiArai 0:0751c92c0f71 10 *
kenjiArai 0:0751c92c0f71 11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
kenjiArai 0:0751c92c0f71 12 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
kenjiArai 0:0751c92c0f71 13 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
kenjiArai 0:0751c92c0f71 14 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kenjiArai 0:0751c92c0f71 15 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kenjiArai 0:0751c92c0f71 16 */
kenjiArai 0:0751c92c0f71 17
kenjiArai 0:0751c92c0f71 18 // Include ---------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 19 #include "mbed.h"
kenjiArai 0:0751c92c0f71 20 #include "TextLCD.h"
kenjiArai 2:77ec44bf1fa5 21 // MUST -> need to modify rtc_api.c, please refer SetRTC.h file [CAUTION] and modify_info_xxx.h
kenjiArai 0:0751c92c0f71 22 #include "SetRTC.h"
kenjiArai 0:0751c92c0f71 23
kenjiArai 0:0751c92c0f71 24 // Definition ------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 25 #define SHOW_KEY_PROMPT 30
kenjiArai 0:0751c92c0f71 26
kenjiArai 6:5ada291037aa 27 //#define USE_LCD
kenjiArai 0:0751c92c0f71 28
kenjiArai 5:bc464a588c2e 29 #if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) \
kenjiArai 5:bc464a588c2e 30 || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F334R8)
kenjiArai 1:7a48c475bbd2 31 #else
kenjiArai 5:bc464a588c2e 32 #error "Target is only Nucleo F401RE, F411RE, F334R8 and L152RE"
kenjiArai 1:7a48c475bbd2 33 #endif
kenjiArai 1:7a48c475bbd2 34
kenjiArai 0:0751c92c0f71 35 // Object ----------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 36 DigitalIn userSW(USER_BUTTON);
kenjiArai 0:0751c92c0f71 37 DigitalOut myled(LED1); // Indicate the sampling period
kenjiArai 0:0751c92c0f71 38 Serial pc(USBTX, USBRX);
kenjiArai 6:5ada291037aa 39 //#if defined(USE_LCD)
kenjiArai 0:0751c92c0f71 40 I2C i2c(D14,D15); // SDA, SCL
kenjiArai 0:0751c92c0f71 41 TextLCD_I2C_N lcd(&i2c, 0x7c, TextLCD::LCD8x2); // LCD(Akizuki AQM0802A)
kenjiArai 6:5ada291037aa 42 //#endif
kenjiArai 6:5ada291037aa 43 DigitalOut pwr_onoff(PA_9);
kenjiArai 0:0751c92c0f71 44
kenjiArai 0:0751c92c0f71 45 // RAM -------------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 46
kenjiArai 0:0751c92c0f71 47 // ROM / Constant data ---------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 48
kenjiArai 0:0751c92c0f71 49 // Function prototypes ---------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 50
kenjiArai 0:0751c92c0f71 51 //-------------------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 52 // Control Program
kenjiArai 0:0751c92c0f71 53 //-------------------------------------------------------------------------------------------------
kenjiArai 0:0751c92c0f71 54 int main()
kenjiArai 0:0751c92c0f71 55 {
kenjiArai 0:0751c92c0f71 56 char buf[42]; // data buffer for text
kenjiArai 0:0751c92c0f71 57 time_t seconds;
kenjiArai 0:0751c92c0f71 58 uint8_t counter = SHOW_KEY_PROMPT;
kenjiArai 4:a9cebfe4715f 59 uint8_t wait_counter = 0;
kenjiArai 4:a9cebfe4715f 60 uint8_t xtal = 0;
kenjiArai 0:0751c92c0f71 61
kenjiArai 6:5ada291037aa 62 pwr_onoff = 1;
kenjiArai 6:5ada291037aa 63 wait(2.0);
kenjiArai 0:0751c92c0f71 64 #if defined(USE_LCD)
kenjiArai 0:0751c92c0f71 65 // lcd
kenjiArai 0:0751c92c0f71 66 lcd.locate(0, 0); // 1st line top
kenjiArai 0:0751c92c0f71 67 // 12345678
kenjiArai 0:0751c92c0f71 68 lcd.printf(" RTC ");
kenjiArai 0:0751c92c0f71 69 lcd.locate(0, 1); // 2nd line top
kenjiArai 0:0751c92c0f71 70 // 12345678
kenjiArai 0:0751c92c0f71 71 lcd.puts(" JH1PJL ");
kenjiArai 0:0751c92c0f71 72 lcd.setContrast(0x14);
kenjiArai 0:0751c92c0f71 73 #endif
kenjiArai 0:0751c92c0f71 74 pc.printf("\r\n\r\nTest Nucleo RTC Function\r\n");
kenjiArai 2:77ec44bf1fa5 75 myled = !myled;
kenjiArai 5:bc464a588c2e 76 if (SetRTC(0) == 1) {
kenjiArai 2:77ec44bf1fa5 77 pc.printf("External");
kenjiArai 4:a9cebfe4715f 78 xtal = 1;
kenjiArai 2:77ec44bf1fa5 79 } else {
kenjiArai 2:77ec44bf1fa5 80 pc.printf("Internal");
kenjiArai 4:a9cebfe4715f 81 xtal = 0;
kenjiArai 2:77ec44bf1fa5 82 }
kenjiArai 2:77ec44bf1fa5 83 pc.printf(" Xtal for RTC\r\n");
kenjiArai 2:77ec44bf1fa5 84 show_RTC_reg(); // only for debug purpose
kenjiArai 0:0751c92c0f71 85 // waiting for Initial screen
kenjiArai 0:0751c92c0f71 86 myled = 1;
kenjiArai 0:0751c92c0f71 87 wait(1.0);
kenjiArai 0:0751c92c0f71 88 myled = !myled;
kenjiArai 0:0751c92c0f71 89 wait(1.0);
kenjiArai 0:0751c92c0f71 90 while(1) {
kenjiArai 0:0751c92c0f71 91 seconds = time(NULL);
kenjiArai 0:0751c92c0f71 92 strftime(buf, 40, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
kenjiArai 4:a9cebfe4715f 93 if (xtal){
kenjiArai 4:a9cebfe4715f 94 pc.printf("[Time] %s", buf);
kenjiArai 4:a9cebfe4715f 95 } else {
kenjiArai 4:a9cebfe4715f 96 pc.printf("[Time by Internal Clock] %s", buf);
kenjiArai 4:a9cebfe4715f 97 }
kenjiArai 0:0751c92c0f71 98 #if defined(USE_LCD)
kenjiArai 0:0751c92c0f71 99 lcd.locate(0, 0); // 1st line top
kenjiArai 0:0751c92c0f71 100 strftime(buf, 40, "%b%d'%y", localtime(&seconds));
kenjiArai 0:0751c92c0f71 101 lcd.printf(buf);
kenjiArai 0:0751c92c0f71 102 lcd.locate(0, 1); // 2nd line top
kenjiArai 0:0751c92c0f71 103 strftime(buf, 10, "%H:%M:%S", localtime(&seconds));
kenjiArai 0:0751c92c0f71 104 lcd.printf(buf);
kenjiArai 0:0751c92c0f71 105 #endif
kenjiArai 2:77ec44bf1fa5 106 --counter;
kenjiArai 0:0751c92c0f71 107 if (counter){
kenjiArai 0:0751c92c0f71 108 // 012345678901234567890123456789012345678901234567890123456789012
kenjiArai 1:7a48c475bbd2 109 pc.printf("Is time correct? If no, hit any key.\r");
kenjiArai 2:77ec44bf1fa5 110 }
kenjiArai 4:a9cebfe4715f 111 wait_counter = 0;
kenjiArai 2:77ec44bf1fa5 112 while (seconds == time(NULL)){
kenjiArai 0:0751c92c0f71 113 if (pc.readable() == 1){
kenjiArai 0:0751c92c0f71 114 buf[0] = pc.getc(); // dummy read
kenjiArai 0:0751c92c0f71 115 time_enter_mode();
kenjiArai 0:0751c92c0f71 116 }
kenjiArai 2:77ec44bf1fa5 117 if (userSW == 0){
kenjiArai 0:0751c92c0f71 118 #if defined(USE_LCD)
kenjiArai 2:77ec44bf1fa5 119 lcd.locate(0, 0); // 1st line top
kenjiArai 2:77ec44bf1fa5 120 // 12345678
kenjiArai 2:77ec44bf1fa5 121 lcd.printf(" Enter ");
kenjiArai 2:77ec44bf1fa5 122 lcd.locate(0, 1); // 2nd line top
kenjiArai 2:77ec44bf1fa5 123 // 12345678
kenjiArai 2:77ec44bf1fa5 124 lcd.printf(" Sleep " );
kenjiArai 0:0751c92c0f71 125 #endif
kenjiArai 3:7b3edf54c706 126 // 123456789012345678901234567890123456789012345678
kenjiArai 3:7b3edf54c706 127 pc.printf("\r\nEnter Standby Mode, please push RESET to wake-up\r\n");
kenjiArai 2:77ec44bf1fa5 128 wait(1.0);
kenjiArai 2:77ec44bf1fa5 129 myled = 0;
kenjiArai 3:7b3edf54c706 130 goto_standby();
kenjiArai 2:77ec44bf1fa5 131 }
kenjiArai 4:a9cebfe4715f 132 wait(0.05);
kenjiArai 4:a9cebfe4715f 133 if (++wait_counter > (2000 / 50)){
kenjiArai 4:a9cebfe4715f 134 if (xtal){
kenjiArai 4:a9cebfe4715f 135 pc.printf("Time was not updated! External Xtal does NOT oscillate.\r\n");
kenjiArai 4:a9cebfe4715f 136 } else {
kenjiArai 4:a9cebfe4715f 137 pc.printf("Time was not updated! LSI does NOT work.\r\n");
kenjiArai 4:a9cebfe4715f 138 }
kenjiArai 4:a9cebfe4715f 139 break;
kenjiArai 4:a9cebfe4715f 140 }
kenjiArai 0:0751c92c0f71 141 }
kenjiArai 2:77ec44bf1fa5 142 if (counter){
kenjiArai 3:7b3edf54c706 143 // 12345678901234567890123456789012345678901234567890
kenjiArai 3:7b3edf54c706 144 pc.printf(" \r");
kenjiArai 2:77ec44bf1fa5 145 }
kenjiArai 2:77ec44bf1fa5 146 myled = !myled;
kenjiArai 0:0751c92c0f71 147 }
kenjiArai 0:0751c92c0f71 148 }