mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-19 18:01:30 +10:00
stm32wl: add hardware RTC support (rak3172) (#10961)
* stm32wl: add hardware RTC support infrastructure Wires the STM32WL chip's internal RTC (running off the LSE 32.768kHz crystal) into meshtastic's existing time-of-day framework (perhapsSetRTC()/readFromRTC()), following the same pattern already used for I2C RTC chips (RV3028, PCF8563/85063, RX8130CE). LSE is started and polled manually before ever calling into the STM32RTC library, with our own bounded timeout - the library's own internal LSE startup path has no bounded fallback and hangs forever via Error_Handler() if the crystal never locks, so this is required for a board with a missing/faulty crystal to boot normally rather than hang. Gated behind a new HAS_LSE variant flag (currently unset everywhere, so this is inert until a variant opts in - see follow-up commit). Signed-off-by: Andrew Yong <me@ndoo.sg> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> * gps: qualify RTC.h includes to avoid case-insensitive filesystem collision with STM32RTC The stm32duino STM32RTC library (added to lib_deps in a follow-up commit) ships its own src/rtc.h. On case-insensitive filesystems (the macOS default), an unqualified #include "RTC.h"/<RTC.h> from any file outside src/gps/ resolves to the library's rtc.h instead of src/gps/RTC.h, since PlatformIO's LDF puts lib_deps include paths ahead of the project's own -Isrc/gps. Qualify every include as gps/RTC.h so it can't collide with any same-named header a future dependency might ship, regardless of filesystem case sensitivity. Purely mechanical, no behavior change. Signed-off-by: Andrew Yong <me@ndoo.sg> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> * stm32wl(rak3172): enable hardware RTC support Opts rak3172 into the HAS_LSE infrastructure added previously: sets STM32WL_LSE_DRIVE to a conservative default and pulls in the STM32RTC library. rak3172 has ~63KB flash headroom going in; build-verified at 76.7% flash usage after this change (up from a 73.8% baseline), well within budget. wio-e5 is not opted in here despite sharing the same STM32WLE5 chip - it's already at 96.8% flash usage today (GPS + I2C sensor support compiled in, unlike rak3172), leaving too little headroom to safely add STM32RTC without first trimming something else. Signed-off-by: Andrew Yong <me@ndoo.sg> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> * stm32wl: add docstrings for LSE/RTC setup functions Addresses CodeRabbit's docstring coverage check on PR #10961. Signed-off-by: Andrew Yong <me@ndoo.sg> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> * stm32wl: address CodeRabbit nitpicks on PR #10961 - Brace the single-statement HAS_LSE branch in perhapsSetRTC() to match the sibling readFromRTC() branch's style. - Quote the RTC.h include in PhoneAPI.cpp for consistency with every other qualified include site. Signed-off-by: Andrew Yong <me@ndoo.sg> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> --------- Signed-off-by: Andrew Yong <me@ndoo.sg> Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
co-authored by
Ben Meadors
parent
cf0cb9087a
commit
b71c1adb26
@@ -16,6 +16,22 @@
|
||||
#ifndef HAS_WIRE
|
||||
#define HAS_WIRE 1
|
||||
#endif
|
||||
#ifndef HAS_LSE
|
||||
#define HAS_LSE 0
|
||||
#endif
|
||||
|
||||
// How long to wait for the LSE 32.768kHz crystal to lock before giving up on hardware RTC support.
|
||||
// Override in a variant's variant.h if that board's crystal needs longer to stabilize.
|
||||
#ifndef STM32WL_LSE_TIMEOUT_MS
|
||||
#define STM32WL_LSE_TIMEOUT_MS 2000
|
||||
#endif
|
||||
|
||||
// A variant that sets HAS_LSE must also define STM32WL_LSE_DRIVE - catch that mistake here, not as a confusing
|
||||
// HAL compile error deep in main-stm32wl.cpp.
|
||||
#if HAS_LSE && !defined(STM32WL_LSE_DRIVE)
|
||||
#error \
|
||||
"HAS_LSE is set but STM32WL_LSE_DRIVE is not defined - set it in the variant's variant.h to one of RCC_LSEDRIVE_LOW/MEDIUMLOW/MEDIUMHIGH/HIGH"
|
||||
#endif
|
||||
|
||||
//
|
||||
// set HW_VENDOR
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "gps/RTC.h"
|
||||
#include <Throttle.h>
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <stm32wle5xx.h>
|
||||
#include <stm32wlxx_hal.h>
|
||||
|
||||
#if HAS_LSE
|
||||
#include <STM32RTC.h>
|
||||
|
||||
// LSEDRV is a 2-bit RCC_BDCR field where every combination is a legal drive level, so this covers all 4 values.
|
||||
static_assert((STM32WL_LSE_DRIVE & ~RCC_LSEDRIVE_HIGH) == 0,
|
||||
"STM32WL_LSE_DRIVE must be one of RCC_LSEDRIVE_LOW/MEDIUMLOW/MEDIUMHIGH/HIGH");
|
||||
|
||||
static bool stm32wlRtcValid = false;
|
||||
#endif
|
||||
|
||||
// ─── Bootloader redirect ──────────────────────────────────────────────────────
|
||||
//
|
||||
// Why .noinit + constructor instead of TAMP backup registers:
|
||||
@@ -86,6 +97,47 @@ bool getDeviceId(uint8_t *deviceId)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if HAS_LSE
|
||||
// Starts the LSE crystal with a bounded timeout and, if it locks, brings up the STM32 hardware RTC on it.
|
||||
void stm32wlSetup()
|
||||
{
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
__HAL_RCC_LSEDRIVE_CONFIG(STM32WL_LSE_DRIVE);
|
||||
__HAL_RCC_LSE_CONFIG(RCC_LSE_ON);
|
||||
|
||||
uint32_t start = millis();
|
||||
bool lseReady = false;
|
||||
while (Throttle::isWithinTimespanMs(start, STM32WL_LSE_TIMEOUT_MS)) {
|
||||
if (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY)) {
|
||||
lseReady = true;
|
||||
break;
|
||||
}
|
||||
delay(5);
|
||||
}
|
||||
|
||||
if (lseReady) {
|
||||
STM32RTC &rtc = STM32RTC::getInstance();
|
||||
rtc.setClockSource(STM32RTC::LSE_CLOCK);
|
||||
rtc.begin();
|
||||
stm32wlRtcValid = true;
|
||||
LOG_INFO("STM32WL: LSE locked, hardware RTC available");
|
||||
} else {
|
||||
// Don't leave a failed oscillator burning current.
|
||||
__HAL_RCC_LSE_CONFIG(RCC_LSE_OFF);
|
||||
LOG_WARN("STM32WL: LSE failed to start within %dms (crystal missing/faulty?) - hardware RTC unavailable",
|
||||
STM32WL_LSE_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
// True once stm32wlSetup() has confirmed the LSE crystal is locked and the hardware RTC is running.
|
||||
bool stm32wlRtcAvailable()
|
||||
{
|
||||
return stm32wlRtcValid;
|
||||
}
|
||||
#else
|
||||
void stm32wlSetup() {}
|
||||
#endif
|
||||
|
||||
void cpuDeepSleep(uint32_t msecToWake) {}
|
||||
|
||||
// Hacks to force more code and data out.
|
||||
|
||||
Reference in New Issue
Block a user