In the past, you need modify rtc_api.c in mbed-dev source code. From this revision, you can just use RTC function all of conditions (Normal, Reset, Stand-by, Power OFF).
Note
From now on, you do NOT need any modification for mbed-dev library because STM team updates rtc_api.c source code and support RTC function under reset & standby condition includes power off condition (You need additional VBAT back-up hardware).
Please refer following NOTE information.
/users/kenjiArai/notebook/nucleo-series-rtc-control-under-power-onoff-and-re/
main.cpp
- Committer:
- kenjiArai
- Date:
- 2021-03-06
- Revision:
- 14:4b03106ece1f
- Parent:
- 13:c1f984932e98
File content as of revision 14:4b03106ece1f:
/* * mbed Application program * RTC (inside STM32x CPU) test program * * Copyright (c) 2015,'16,'17,'20, '21 Kenji Arai / JH1PJL * http://www7b.biglobe.ne.jp/~kenjia/ * https://os.mbed.com/users/kenjiArai/ * Created: January 17th, 2015 * Revised: March 6th, 2021 */ /* 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. --> Right now, you don't worry thoese issue. */ /* ----- 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) not support on Mbed-os6.6.0 Nucleo-F334R8 Nucleo-L476RG / ok / ok / ok (need following Back-up Circuit) DISCO-L45VG-IOT/ ok / ok / ok (Need additional hardware) Nucleo-L152RE / ok / ok / no check (Need additional hardware) Nucleo-L073RZ / ok / ok / no check (Need additional hardware) not support on Mbed-os6.6.0 Nucleo-L053R8 ----- add tested board ----- Nucleo-F446ZE DISCO-F746NG Nucleo-F746ZG DISCO-F769NI Nucleo-H743ZI2 Nucleo-F303K8 Nucleo-L432KC < Back-up circuit > CN7 VIN <- SBD <- 330 Ohm <- CR2032 + - -> CN7 GND Remove SB45 Zero Ohm resistor ----- PLEASE REFER FOLLOWS ---- https://os.mbed.com/users/kenjiArai/notebook/ nucleo-series-rtc-control-under-power-onoff-and-re/ */ // Include -------------------------------------------------------------------- #include "mbed.h" #include "uart_as_stdio.h" // Definition ----------------------------------------------------------------- #if defined(TARGET_DISCO_F746NG) \ || defined(TARGET_NUCLEO_F746ZG) \ || defined(TARGET_DISCO_F769NI) \ || defined(TARGET_DISCO_F469NI) \ || defined(TARGET_NUCLEO_F446ZE) \ || defined(TARGET_NUCLEO_H743ZI2) #define PUSHED_SW 1 // Active high #elif defined(TARGET_NUCLEO_F303K8) \ || defined(TARGET_NUCLEO_L432KC) #define USER_BUTTON A0 // temporary setting #define PUSHED_SW 0 // Active low #else #define PUSHED_SW 0 // Active low #endif #define LONGLONGTIME 2147483647s // Object --------------------------------------------------------------------- DigitalIn userSW(USER_BUTTON); DigitalOut myled(LED1); // Indicate the sampling period // RAM ------------------------------------------------------------------------ // ROM / Constant data -------------------------------------------------------- const char *const msg0 = "Is a time correct? If no, please hit any key. "; const char *const msg1 = "<Push USER SW then enter the Standby mode> "; // Function prototypes -------------------------------------------------------- FileHandle *mbed::mbed_override_console(int fd); static void time_enter_mode(void); static void chk_and_set_time(char *ptr); static int32_t xatoi (char **str, int32_t *res); static void get_line (char *buff, int32_t len); static void usr_sw_irq(void); extern void print_revision(void); //------------------------------------------------------------------------------ // Control Program //------------------------------------------------------------------------------ int main() { char buf[64]; time_t seconds; uint8_t wait_counter = 0; puts("\r\n\r\nTest Nucleo RTC Function."); print_revision(); myled = !myled; ThisThread::sleep_for(500ms); myled = !myled; ThisThread::sleep_for(500ms); while(true) { seconds = time(NULL); strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds)); printf("[Time] %s", buf); printf("%s", msg0); printf("%s", msg1); puts("\r"); wait_counter = 0; while (seconds == time(NULL)) { if (readable() == 1) { buf[0] = getc(); // dummy read time_enter_mode(); } if (userSW == PUSHED_SW) { // goto sleep while (userSW == PUSHED_SW) { ThisThread::sleep_for(10ms); } ThisThread::sleep_for(10ms); puts("Entered the standby mode. "); #if defined(TARGET_NUCLEO_F303K8) || defined(TARGET_NUCLEO_L432KC) puts("Please change A0 level for wake-up(Reset)."); #else puts("Please push USER BUTTON to wake-up(Reset)."); #endif myled = 0; InterruptIn usr_sw(USER_BUTTON); ThisThread::sleep_for(1s); DigitalIn dmy0(LED1); DigitalIn dmy1(USBTX); DigitalIn dmy2(USBRX); usr_sw.fall(&usr_sw_irq); // actual push or chattering sleep_preparation(); ThisThread::sleep_for(LONGLONGTIME); } ThisThread::sleep_for(50ms); if (++wait_counter > (2000 / 50)) { break; } } // delete previous strings // https://en.wikipedia.org/wiki/ANSI_escape_code#CSIsection // \33[ = CSI sequences, 1A=Cursor Up (one line), 2K=Erase in Line(all) // G=Cursor Horizontal Absolute printf("\33[1A\033[2K\033[G"); myled = !myled; } } // Interrupt for wake up static void usr_sw_irq(void) { system_reset(); // restart from RESET condition } // Time adjustment static void time_enter_mode(void) { char *ptr; char linebuf[64]; puts("Set time into RTC."); puts(" e.g. >21 3 3 3 33 33 -> March 03,'21, 03:33:33"); puts(" If time is fine, just hit enter key."); putc('>'); ptr = linebuf; get_line(ptr, sizeof(linebuf)); putc('\r'); chk_and_set_time(ptr); } // Change string -> integer static int32_t xatoi(char **str, int32_t *res) { uint32_t val; uint8_t 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 static void get_line(char *buff, int32_t len) { char c; int32_t idx = 0; for (;;) { c = getc(); //printf("0x%x \r\n", c); if (c == '\r') { buff[idx++] = c; break; } if ((c == '\b') && idx) { idx--; const char bf_bs[] = {0x1b, '[', '1', 'D', ' ', 0x1b, '[', '1', 'D'}; printf(bf_bs, 9); } if (((uint8_t)c >= ' ') && (idx < len - 1)) { buff[idx++] = c; putc(c); } } buff[idx] = 0; putc('\n'); } // Check key input strings and set time static void chk_and_set_time(char *ptr) { int32_t p1; struct tm t; time_t seconds; if (xatoi(&ptr, &p1)) { t.tm_year = (uint8_t)p1 + 100; printf("Year:%d ",p1); xatoi( &ptr, &p1 ); t.tm_mon = (uint8_t)p1 - 1; printf("Month:%d ",p1); xatoi( &ptr, &p1 ); t.tm_mday = (uint8_t)p1; printf("Day:%d ",p1); xatoi( &ptr, &p1 ); t.tm_hour = (uint8_t)p1; printf("Hour:%d ",p1); xatoi( &ptr, &p1 ); t.tm_min = (uint8_t)p1; printf("Min:%d ",p1); xatoi( &ptr, &p1 ); t.tm_sec = (uint8_t)p1; printf("Sec: %d \r\n",p1); } else { return; } seconds = mktime(&t); set_time(seconds); // Show Time with several example // ex.1 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 ); char buf[64]; // ex.2 strftime(buf, 40, "%x %X", localtime(&seconds)); printf("Date: %s\r\n", buf); // ex.3 strftime(buf, 40, "%I:%M:%S %p (%Y/%m/%d)", localtime(&seconds)); printf("Date: %s\r\n", buf); // ex.4 strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds)); printf("Date: %s\r\n", buf); }