Skip to content

Real Time Clock (RTC)

lbuild module: modm:platform:rtc

The STM32 RTC implements a full calendar in hardware to provide a date and time in binary-coded decimal (BCD) format. Several optimized methods are provided to provide an efficient conversion from this hardware format to a software representation.

The epoch of the RTC is chosen to be the 1st of January 1970 to be compatible with UNIX timestamps. Since the year is limited to two BCD digits, the RTC will roll over in 2070.

Note that the RTC hardware has no support for time zones, so you have to handle that in software.

Initialization

The RTC keeps running during a reset of the microcontroller when the backup domain is powered. To prevent clock drift, the initialize() function will check if the RTC is already running and only initialize the prescaler differs from the programmed one. If the return value is false the RTC was already initialized and running:

struct SystemClock
{
    static constexpr uint32_t Rtc = 32'768;
};
const bool inited = Rtc::initialize<SystemClock>();
if (not inited) { /* RTC was already running from before reset */ }

To always initialize the RTC, set the forced argument to true:

Rtc::initialize<SystemClock>(true);

To give the RTC an initial date and time, use the setDateTime() function. You can use the compile time as a basic reference time, and only set the time forward to not reset the time on every reset:

constexpr auto cdt = modm::DateTime::fromBuildTime();
if (Rtc::dateTime() < cdt) Rtc::setDateTime(cdt);

Accessing Date and Time

The RTC hardware provides the date and time in BCD format which can be atomically read out with the dateTime() function, which returns a DateTime object that can be used to access the individual date and time components:

const auto dt = Rtc::dateTime();
dt.year_month_day();
dt.day_of_year();
dt.weekday();

dt.hours();
dt.minutes();
dt.seconds();
dt.subseconds();

// prints ISO encoding: 2024-12-22 18:39:21.342
MODM_LOG_INFO << dt << modm::endl;

// Efficient conversion to std::tm
const std::tm tm = dt.tm();

Please note that while the DateTime object provides methods to compute to seconds and milliseconds since epoch, these are slow and should be avoided. Instead, use the Rtc::now(), Rtc::time_t() and Rtc::timeval() functions to access optimized and cached conversion methods which are much faster:

const Rtc::time_point tp = Rtc::now();
// instead of Rtc::dateTime().time_since_epoch();
const std::time_t tt = Rtc::time_t();
// instead of Rtc::dateTime().time_t();
const struct timeval tv = Rtc::timeval();
// instead of Rtc::dateTime().timeval();

This module is only available for stm32{c0,f0,f2,f3,f4,f7,g0,g4,h7,l0,l1,l4,l5,u5}.

Dependencies

modm:platform:rtc modm_platform_rtc modm: platform: rtc modm_architecture_fiber modm: architecture: fiber modm_platform_rtc->modm_architecture_fiber modm_cmsis_device modm: cmsis: device modm_platform_rtc->modm_cmsis_device modm_math_calendar modm: math: calendar modm_platform_rtc->modm_math_calendar modm_platform_rcc modm: platform: rcc modm_platform_rtc->modm_platform_rcc

Limited availability: Check with 'lbuild discover' if this module is available for your target!