Solution how to fix broken RTC on Nucleo_F103RB / STM32F103 BluePill etc..
Fork of Nucleo_RTC_battery_bkup_pwr_off_okay by
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
main.cpp
- Committer:
- kenjiArai
- Date:
- 2016-07-02
- Revision:
- 8:bf593344668e
- Parent:
- 7:27a1cf7f8921
- Child:
- 9:6a64b0207f72
File content as of revision 8:bf593344668e:
/* * mbed Application program * RTC (inside STM32x CPU) test program * * Copyright (c) 2015,'16 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 * * 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" // 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 #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 #if (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG)) #define PUSHED_SW 1 // Active high #else #define PUSHED_SW 0 // Active low #endif // 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 ------------------------------------------------------------------------------------------- // 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 --------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- // 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); myled = !myled; wait(1.0); 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(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 == 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; goto_standby(); } wait(0.05); if (++wait_counter > (2000 / 50)){ if (xtal){ pc.printf(msg3); } else { pc.printf(msg4); } break; } } 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; } }