Group runtime timers and flags to recover nRF52 repeater RAM

This commit is contained in:
mikecarper committed 2026-10-28 04:57:03 -07:00
1 parent 8f20fe5d83
commit acacf548ef
4 files changed
+45 -32

No files matched your search

+29 -23
View File
@@ -355,53 +355,59 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks
size_t serial_log_remaining = 0;
size_t serial_log_pending_size = 0;
char serial_log_pending[640];
int serial_acl_next = -1;
int serial_acl_count = 0;
int serial_recent_next = -1;
int serial_recent_count = 0;
SimpleMeshTables::RecentRepeaterInfo serial_recent_cursor;
int serial_recent_cursor_index = -1;
bool serial_log_active = false;
bool serial_log_eof_pending = false;
bool serial_log_skip_line = false;
int serial_acl_next = -1;
int serial_acl_count = 0;
bool serial_acl_header = false;
int serial_recent_next = -1;
int serial_recent_count = 0;
bool serial_recent_header = false;
bool serial_recent_has_cursor = false;
SimpleMeshTables::RecentRepeaterInfo serial_recent_cursor;
int serial_recent_cursor_index = -1;
#endif
// Runtime only: group scalar timers and flags to avoid gaps before aligned
// members. No persisted preferences or queue capacities depend on this order.
uint64_t uptime_millis;
uint64_t last_battery_alert_sent;
#if MESH_ENABLE_HOST_CLI
uint64_t host_cli_nonce;
uint64_t host_cli_claim_challenge;
#endif
uint32_t last_millis;
uint64_t uptime_millis;
unsigned long next_local_advert, next_flood_advert;
uint32_t primary_radio_mutation_generation = 0;
uint32_t radio_reply_deadline = 0;
#if MESH_ENABLE_HOST_CLI
unsigned long host_cli_deadline;
unsigned long host_cli_claim_emit_at;
#endif
uint32_t pending_self_advert_delay;
unsigned long next_battery_alert_check;
unsigned long next_recent_repeater_sweep;
mesh::DeferredCliCommand deferred_cli_command;
mesh::RemoteCliReplyCache remote_cli_reply_cache;
mesh::ReplayResetNonce replay_reset_nonce;
bool replay_clock_set = false;
mesh::TempRadioReplyBarrier temp_radio_reply_barrier;
uint32_t primary_radio_mutation_generation = 0;
bool primary_radio_mutation_starts_temp = false;
uint32_t radio_reply_deadline = 0;
bool radio_reply_secondary = false;
void finishRadioReply(bool delivered);
void serviceRadioReplyDeadline();
TransportKey deferred_cli_reply_scope;
mesh::RxInactivityWatchdog rx_inactivity_watchdog;
mesh::RepeaterRadioTiming radio_timing;
mesh::Packet* pending_battery_alert_packet;
bool replay_clock_set = false;
bool primary_radio_mutation_starts_temp = false;
bool radio_reply_secondary = false;
bool deferred_cli_reply_scoped;
#if MESH_ENABLE_HOST_CLI
bool host_cli_waiting;
bool host_cli_claimed;
bool host_cli_claim_emit;
unsigned long host_cli_deadline;
unsigned long host_cli_claim_emit_at;
uint64_t host_cli_nonce;
uint64_t host_cli_claim_challenge;
#endif
uint32_t pending_self_advert_delay;
bool pending_self_advert;
bool pending_self_advert_flood;
unsigned long next_battery_alert_check;
mesh::RxInactivityWatchdog rx_inactivity_watchdog;
mesh::RepeaterRadioTiming radio_timing;
unsigned long next_recent_repeater_sweep;
uint64_t last_battery_alert_sent;
mesh::Packet* pending_battery_alert_packet;
bool battery_alert_sent;
bool _logging;
#ifdef DISPLAY_ACTIVITY_DASHBOARD
+6 -3
View File
@@ -944,7 +944,6 @@ class CommonCLI {
#if MESH_ENABLE_EMERGENCY_POWER
FILESYSTEM* _emergency_power_fs = nullptr;
mesh::emergencypower::State _emergency_power;
bool _emergency_radio_sleeping = false;
void loadEmergencyPower(FILESYSTEM* fs);
bool saveEmergencyPower(const mesh::emergencypower::Settings& settings);
void loopEmergencyPower();
@@ -968,7 +967,6 @@ class CommonCLI {
SensorManager* _sensors;
RegionMap* _region_map;
uint32_t _media_regions_retry_ms = 0;
bool _media_regions_ready = false;
static bool mediaMeshRegionStoreMissing(FILESYSTEM* fs);
void recoverMediaMeshRegions();
static bool updateMediaMeshScope(void* context, bool enable, bool commit);
@@ -989,6 +987,12 @@ class CommonCLI {
bool _observer_save_result_known = false;
bool _observer_save_succeeded = false;
#endif
// Runtime flags share padding; persisted NodePrefs retains its own layout.
bool _media_regions_ready = false;
#if MESH_ENABLE_EMERGENCY_POWER
bool _emergency_radio_sleeping = false;
#endif
uint8_t _rx_settings_pending = 0;
bool _com_prefs_needs_upgrade = false; // old-format legacy prefs detected; rewrite once after load
bool _common_save_result_known = false;
bool _common_save_succeeded = false;
@@ -1004,7 +1008,6 @@ class CommonCLI {
RxGain = 1, RxPowerSaving = 2, RxSideDetectors = 4, RxRfRx = 8,
RxPendingMask = 15, RxRfRxDisabled = 128
};
uint8_t _rx_settings_pending = 0;
uint32_t _rx_settings_retry_at = 0;
uint32_t _prefs_save_failures = 0;
mesh::RadioProfileCLI _radio_profiles;
+9 -6
View File
@@ -44,18 +44,19 @@ inline bool decode(const uint8_t* in, size_t size, Settings& settings) {
}
struct State {
Settings settings;
// Runtime only: keep aligned timers together without packing accesses.
uint32_t sampledAt = 0;
uint16_t millivolts = 0;
uint8_t percentage = 0;
bool sampled = false;
bool valid = false;
bool lowBattery = false;
uint32_t phaseMs = 0;
uint32_t lastTick = 0;
uint32_t activationStarted = 0;
uint32_t awakeStarted = 0;
uint32_t awakeDuration = 0;
uint16_t millivolts = 0;
uint8_t percentage = 0;
Settings settings;
bool sampled = false;
bool valid = false;
bool lowBattery = false;
bool activationHold = false;
void begin(const Settings& loaded, uint32_t now) {
@@ -118,5 +119,7 @@ struct State {
return phase < AwakeWindowMs ? 0 : HourMs - phase;
}
};
static_assert(sizeof(State) <= 32, "Emergency timers must retain their compact RAM layout");
static_assert(alignof(State) >= alignof(uint32_t), "Emergency timers must remain aligned");
}} // namespace mesh::emergencypower
+1
View File
@@ -174,6 +174,7 @@ class EmergencyPowerTests(unittest.TestCase):
start = header.index(marker)
return header[start:header.index("#endif", start) + len("#endif")]
private = api_block("#if MESH_ENABLE_EMERGENCY_POWER\n FILESYSTEM* _emergency_power_fs")
private += "\n" + api_block("#if MESH_ENABLE_EMERGENCY_POWER\n bool _emergency_radio_sleeping")
public = api_block("#if MESH_ENABLE_EMERGENCY_POWER\n uint32_t emergencySleepMilliseconds")
implementation = (ROOT / "src/helpers/CommonCLI_Emergency.cpp").read_text(encoding="ascii")
implementation = re.sub(r"^#include[^\n]*\n", "", implementation, flags=re.MULTILINE)