mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-15 07:51:19 +10:00
* 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>
135 lines
5.0 KiB
C++
135 lines
5.0 KiB
C++
#include "PowerStressModule.h"
|
|
#include "MeshService.h"
|
|
#include "NodeDB.h"
|
|
#include "PowerMon.h"
|
|
#include "Router.h"
|
|
#include "configuration.h"
|
|
#include "gps/RTC.h"
|
|
#include "main.h"
|
|
#include "sleep.h"
|
|
#include "target_specific.h"
|
|
#include <Throttle.h>
|
|
|
|
extern void printInfo();
|
|
|
|
PowerStressModule::PowerStressModule()
|
|
: ProtobufModule("powerstress", meshtastic_PortNum_POWERSTRESS_APP, &meshtastic_PowerStressMessage_msg),
|
|
concurrency::OSThread("PowerStress")
|
|
{
|
|
}
|
|
|
|
bool PowerStressModule::handleReceivedProtobuf(const meshtastic_MeshPacket &req, meshtastic_PowerStressMessage *pptr)
|
|
{
|
|
// We only respond to messages if powermon debugging is already on
|
|
if (config.power.powermon_enables) {
|
|
auto p = *pptr;
|
|
LOG_INFO("Received PowerStress cmd=%d", p.cmd);
|
|
|
|
// Some commands we can handle immediately, anything else gets deferred to be handled by our thread
|
|
switch (p.cmd) {
|
|
case meshtastic_PowerStressMessage_Opcode_UNSET:
|
|
LOG_ERROR("PowerStress operation unset");
|
|
break;
|
|
|
|
case meshtastic_PowerStressMessage_Opcode_PRINT_INFO:
|
|
printInfo();
|
|
|
|
// Now that we know we are actually doing power stress testing, go ahead and turn on all enables (so the log is fully
|
|
// detailed)
|
|
powerMon->force_enabled = true;
|
|
break;
|
|
|
|
default:
|
|
if (currentMessage.cmd != meshtastic_PowerStressMessage_Opcode_UNSET)
|
|
LOG_ERROR("PowerStress operation %d already in progress! Can't start new command", currentMessage.cmd);
|
|
else
|
|
currentMessage = p; // copy for use by thread (the message provided to us will be getting freed)
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int32_t PowerStressModule::runOnce()
|
|
{
|
|
if (!config.power.powermon_enables) {
|
|
// Powermon not enabled - stop using CPU/stop this thread
|
|
return disable();
|
|
}
|
|
|
|
int32_t sleep_msec = 10; // when not active check for new messages every 10ms
|
|
|
|
auto &p = currentMessage;
|
|
|
|
if (isRunningCommand) {
|
|
// Done with the previous command - our sleep must have finished
|
|
p.cmd = meshtastic_PowerStressMessage_Opcode_UNSET;
|
|
p.num_seconds = 0;
|
|
isRunningCommand = false;
|
|
LOG_INFO("S:PS:%u", p.cmd);
|
|
} else {
|
|
if (p.cmd != meshtastic_PowerStressMessage_Opcode_UNSET) {
|
|
sleep_msec = (int32_t)(p.num_seconds * 1000);
|
|
isRunningCommand = !!sleep_msec; // if the command wants us to sleep, make sure to mark that we have something running
|
|
LOG_INFO(
|
|
"S:PS:%u",
|
|
p.cmd); // Emit a structured log saying we are starting a powerstress state (to make it easier to parse later)
|
|
|
|
switch (p.cmd) {
|
|
case meshtastic_PowerStressMessage_Opcode_LED_ON:
|
|
// FIXME - implement
|
|
// ledForceOn.set(true);
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_LED_OFF:
|
|
// FIXME - implement
|
|
// ledForceOn.set(false);
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_GPS_ON:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_GPS_OFF:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_LORA_OFF:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_LORA_RX:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_LORA_TX:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_SCREEN_OFF:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_SCREEN_ON:
|
|
// FIXME - implement
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_BT_OFF:
|
|
setBluetoothEnable(false);
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_BT_ON:
|
|
setBluetoothEnable(true);
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_CPU_DEEPSLEEP:
|
|
doDeepSleep(sleep_msec, true, true);
|
|
break;
|
|
case meshtastic_PowerStressMessage_Opcode_CPU_FULLON: {
|
|
uint32_t start_msec = millis();
|
|
while (Throttle::isWithinTimespanMs(start_msec, sleep_msec))
|
|
; // Don't let CPU idle at all
|
|
sleep_msec = 0; // we already slept
|
|
break;
|
|
}
|
|
case meshtastic_PowerStressMessage_Opcode_CPU_IDLE:
|
|
// FIXME - implement
|
|
break;
|
|
default:
|
|
LOG_ERROR("PowerStress operation %d not yet implemented!", p.cmd);
|
|
sleep_msec = 0; // Don't do whatever sleep was requested...
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sleep_msec;
|
|
} |