Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- kenjiArai
- Date:
- 2021-01-11
- Revision:
- 13:c1f984932e98
- Parent:
- 12:8cb1f89541d1
- Child:
- 14:4b03106ece1f
File content as of revision 13:c1f984932e98:
/*
* 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: January 11th, 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"
// Definition -----------------------------------------------------------------
#if defined(TARGET_DISCO_F746NG) \
|| defined(TARGET_NUCLEO_F746ZG) \
|| defined(TARGET_DISCO_F769NI) \
|| 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 2147483647
// Object ---------------------------------------------------------------------
DigitalIn userSW(USER_BUTTON);
DigitalOut myled(LED1); // Indicate the sampling period
// Create a BufferedSerial object to be used by the system I/O retarget code
static BufferedSerial pc(USBTX, USBRX, 9600);
// 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;
thread_sleep_for(500);
myled = !myled;
thread_sleep_for(500);
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 (pc.readable() == 1) {
pc.read(buf,1); // dummy read
time_enter_mode();
}
if (userSW == PUSHED_SW) { // goto sleep
while (userSW == PUSHED_SW) {
thread_sleep_for(10);
}
thread_sleep_for(10);
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);
thread_sleep_for(1000);
DigitalIn dmy0(LED1);
DigitalIn dmy1(USBTX);
DigitalIn dmy2(USBRX);
usr_sw.fall(&usr_sw_irq); // actual push or chattering
thread_sleep_for(LONGLONGTIME);
}
thread_sleep_for(50);
if (++wait_counter > (2000 / 50)) {
break;
}
}
// delete previous strings
printf("\033[2A");
puts(""); // null
uint8_t n = strlen(msg0) + strlen(msg1);
memset(buf, ' ', 64);
if (n > 64) {
n -= 64;
pc.write(buf, 64);
}
if (n > 64) {
pc.write(buf, 64);
} else {
pc.write(buf, n);
}
printf("\033[G");
myled = !myled;
}
}
// the system I/O retarget
FileHandle *mbed::mbed_override_console(int fd)
{
return &pc;
}
// 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 1 6 12 34 56 -> January 06,'21, 12:34:56");
puts(" If time is fine, just hit enter key.");
linebuf[0] = '>';
pc.write(linebuf, 1);
ptr = linebuf;
get_line(ptr, sizeof(linebuf));
puts("\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;
char bf[8];
int32_t idx = 0;
for (;;) {
pc.read(bf, 1);
c = bf[0];
//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'};
pc.write(bf_bs, 9);
}
if (((uint8_t)c >= ' ') && (idx < len - 1)) {
buff[idx++] = c;
pc.write(bf, 1);
}
}
buff[idx] = 0;
bf[0] = '\n';
pc.write(bf, 1);
}
// 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);
}