mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-25 23:42:24 +00:00
Avoid unreachable regulator persistence on integrated STM32WL targets
This commit is contained in:
1 parent
c604a1a165
commit
0da54991cc
4 files changed
+128
-1
No files matched your search
@@ -11,6 +11,44 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// Current STM32WL boards expose neither MCU nor radio regulator selection.
|
||||
// Their radio and MCU share a supply, so adding that support requires a
|
||||
// coordinated implementation rather than the independent controls used by
|
||||
// nRF52 plus an external radio. Do not retain the unreachable persistence and
|
||||
// recovery machinery on these flash-constrained targets. Match this exact
|
||||
// driver: an STM32 target with a different radio keeps the ordinary path.
|
||||
#define MESH_REGULATOR_FIXED_RADIO_CustomSTM32WLx 1
|
||||
#define MESH_REGULATOR_FIXED_RADIO_I(type) MESH_REGULATOR_FIXED_RADIO_##type
|
||||
#define MESH_REGULATOR_FIXED_RADIO(type) MESH_REGULATOR_FIXED_RADIO_I(type)
|
||||
#if defined(STM32_PLATFORM) && MESH_REGULATOR_FIXED_RADIO(RADIO_CLASS)
|
||||
namespace mesh { namespace power {
|
||||
bool beginRegulatorSettings(MainBoard&, Radio&, FILESYSTEM*) { return true; }
|
||||
void serviceRegulatorSettings() {}
|
||||
const char* regulatorModeName(RegulatorMode mode) {
|
||||
return mode == RegulatorMode::Dcdc ? "dcdc" : mode == RegulatorMode::Ldo ? "ldo" : "auto";
|
||||
}
|
||||
uint8_t configuredRegulatorModes(bool) { return 0; }
|
||||
RegulatorMode requestedRegulatorMode(bool) { return RegulatorMode::Default; }
|
||||
RegulatorMode activeRegulatorMode(bool) { return RegulatorMode::Default; }
|
||||
const char* activeRegulatorModeName(bool) { return "unknown"; }
|
||||
bool regulatorFallbackActive(bool) { return false; }
|
||||
bool regulatorRecoveryAvailable() { return false; }
|
||||
bool handleRegulatorCommand(const char* command, char* reply, size_t capacity) {
|
||||
if (strncmp(command, "get ", 4) != 0 && strncmp(command, "set ", 4) != 0) return false;
|
||||
const char* key = command + 4;
|
||||
bool mcu;
|
||||
size_t length;
|
||||
if (strncmp(key, "mcu.regulator", 13) == 0) { mcu = true; length = 13; }
|
||||
else if (strncmp(key, "radio.regulator", 15) == 0) { mcu = false; length = 15; }
|
||||
else return false;
|
||||
if (key[length] != 0 && key[length] != ' ') return false;
|
||||
snprintf(reply, capacity, "Error: %s regulator selection unsupported", mcu ? "MCU" : "radio");
|
||||
return true;
|
||||
}
|
||||
void markRegulatorCleanReset() {}
|
||||
void resumeRegulatorRecovery() {}
|
||||
}} // namespace mesh::power
|
||||
#else
|
||||
namespace mesh { namespace power {
|
||||
namespace {
|
||||
MainBoard* main_board = nullptr;
|
||||
@@ -289,6 +327,10 @@ void resumeRegulatorRecovery() {
|
||||
}
|
||||
|
||||
}} // namespace mesh::power
|
||||
#endif
|
||||
#undef MESH_REGULATOR_FIXED_RADIO
|
||||
#undef MESH_REGULATOR_FIXED_RADIO_I
|
||||
#undef MESH_REGULATOR_FIXED_RADIO_CustomSTM32WLx
|
||||
|
||||
extern "C" void meshRegulatorCleanReset() {
|
||||
// Intentional resets can happen before the settings/filesystem is ready.
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ uint8_t configuredBatteryPercent(uint16_t mv) {
|
||||
}
|
||||
}}
|
||||
#endif
|
||||
#if !defined(NRF52_PLATFORM)
|
||||
#if !defined(NRF52_PLATFORM) && !defined(STM32_PLATFORM)
|
||||
#include <helpers/RegulatorPlatform.cpp>
|
||||
#endif
|
||||
#if defined(NRF52_PLATFORM)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <helpers/IdentityStore.h>
|
||||
#include <Dispatcher.h>
|
||||
uint32_t mock_now = 0;
|
||||
#include <helpers/RegulatorSettings.cpp>
|
||||
|
||||
int main() {
|
||||
using namespace mesh::power;
|
||||
mesh::MainBoard board;
|
||||
mesh::Radio radio;
|
||||
MockFS fs;
|
||||
assert(beginRegulatorSettings(board, radio, &fs));
|
||||
for (bool mcu : {false, true}) {
|
||||
assert(configuredRegulatorModes(mcu) == 0);
|
||||
assert(requestedRegulatorMode(mcu) == RegulatorMode::Default);
|
||||
assert(activeRegulatorMode(mcu) == RegulatorMode::Default);
|
||||
assert(strcmp(activeRegulatorModeName(mcu), "unknown") == 0);
|
||||
assert(!regulatorFallbackActive(mcu));
|
||||
}
|
||||
assert(!regulatorRecoveryAvailable());
|
||||
assert(strcmp(regulatorModeName(RegulatorMode::Default), "auto") == 0);
|
||||
assert(strcmp(regulatorModeName(RegulatorMode::Dcdc), "dcdc") == 0);
|
||||
assert(strcmp(regulatorModeName(RegulatorMode::Ldo), "ldo") == 0);
|
||||
for (const char* command : {"get mcu.regulator", "set mcu.regulator dcdc",
|
||||
"set mcu.regulator ldo", "set mcu.regulator auto", "get radio.regulator",
|
||||
"set radio.regulator dcdc", "set radio.regulator ldo", "set radio.regulator auto"}) {
|
||||
char reply[80];
|
||||
assert(handleRegulatorCommand(command, reply, sizeof(reply)));
|
||||
assert(std::string(reply) == std::string("Error: ")
|
||||
+ (strstr(command, "mcu.") ? "MCU" : "radio") + " regulator selection unsupported");
|
||||
for (size_t capacity = 0; capacity <= sizeof(reply); ++capacity) {
|
||||
memset(reply, 0xa5, sizeof(reply));
|
||||
assert(handleRegulatorCommand(command, reply, capacity));
|
||||
if (capacity) assert(memchr(reply, 0, capacity));
|
||||
for (size_t i = capacity; i < sizeof(reply); ++i) assert(uint8_t(reply[i]) == 0xa5);
|
||||
}
|
||||
}
|
||||
for (const char* command : {"get mcu.regulatorx", "set radio.regulators ldo", "get name", "help"}) {
|
||||
char reply[80];
|
||||
assert(!handleRegulatorCommand(command, reply, sizeof(reply)));
|
||||
}
|
||||
for (unsigned i = 0; i < 10; ++i) {
|
||||
mock_now += 30000;
|
||||
serviceRegulatorSettings();
|
||||
meshRegulatorCleanReset();
|
||||
meshRegulatorResumeRecovery();
|
||||
}
|
||||
assert(board.applies == 0 && board.sample_index == 0);
|
||||
assert(radio.configures == 0 && radio.inits == 0);
|
||||
assert(fs.files.empty() && fs.writes == 0 && fs.renames == 0);
|
||||
assert(mock_now == 300000); // No ADC sampling delays or other hardware work.
|
||||
}
|
||||
@@ -153,6 +153,8 @@ class RegulatorSettingsTests(unittest.TestCase):
|
||||
path.write_text(content)
|
||||
cls.binaries = {}
|
||||
for platform, flags in {'esp32': ['-DESP32=1'],
|
||||
'esp32_fixed_radio_name': ['-DESP32=1','-DRADIO_CLASS=CustomSTM32WLx'],
|
||||
'stm32_future_external_radio': ['-DSTM32_PLATFORM=1','-DRADIO_CLASS=CustomSX1262'],
|
||||
'rp2040': ['-DRP2040_PLATFORM=1'],
|
||||
'nrf52': ['-DNRF52_PLATFORM=1','-DNRF52_POWER_MANAGEMENT=1'],
|
||||
'no_retention': ['-DESP32=1','-DSOC_RTC_SLOW_MEM_SUPPORTED=0']}.items():
|
||||
@@ -164,6 +166,34 @@ class RegulatorSettingsTests(unittest.TestCase):
|
||||
if result.returncode:
|
||||
raise AssertionError(result.stdout+result.stderr)
|
||||
cls.binaries[platform] = binary
|
||||
binary = folder / 'stm32_fixed'
|
||||
result = subprocess.run([compiler, '-std=c++17','-Wall','-Wextra','-Werror',
|
||||
*SANITIZER_FLAGS,'-DSTM32_PLATFORM=1','-DRADIO_CLASS=CustomSTM32WLx',
|
||||
'-I',str(folder),'-I',str(ROOT/'src'),
|
||||
str(ROOT/'test/fixtures/regulator_settings_stm32_fixed.cpp'),'-o',str(binary)],
|
||||
text=True,capture_output=True,timeout=45)
|
||||
if result.returncode:
|
||||
raise AssertionError(result.stdout+result.stderr)
|
||||
cls.stm32_fixed = binary
|
||||
|
||||
def test_fixed_stm32wl_driver_rejects_selection_without_hardware_or_storage_work(self):
|
||||
result = subprocess.run([str(self.stm32_fixed)], text=True,capture_output=True,timeout=10)
|
||||
self.assertEqual(result.returncode,0,result.stdout+result.stderr)
|
||||
|
||||
def test_fixed_stm32wl_guard_must_be_revisited_if_current_classes_gain_selection(self):
|
||||
# These are the classes excluded by the exact platform/driver guard.
|
||||
# A future implementation must remove or narrow that guard as it adds
|
||||
# coordinated shared-supply support, rather than silently hiding it.
|
||||
paths = [ROOT/'src/helpers/stm32/STM32Board.h',
|
||||
ROOT/'src/helpers/radiolib/CustomSTM32WLx.h',
|
||||
ROOT/'src/helpers/radiolib/CustomSTM32WLxWrapper.h']
|
||||
for variant in (ROOT/'variants').glob('*/platformio.ini'):
|
||||
if 'extends = stm32_base' in variant.read_text():
|
||||
paths.extend(variant.parent.glob('*.h'))
|
||||
paths.extend(variant.parent.glob('*.cpp'))
|
||||
for path in paths:
|
||||
with self.subTest(path=path.relative_to(ROOT)):
|
||||
self.assertNotRegex(path.read_text(), r'\b(?:mcuRegulatorModes|regulatorModes)\s*\(')
|
||||
|
||||
def scenario(self, scenario):
|
||||
for platform, binary in self.binaries.items():
|
||||
|
||||
Reference in new issue
Block a user