Fit RAK4631 Full OTA image by reusing regulator recovery code
This commit is contained in:
1 parent
e8d1e537e4
commit
f7b5c40c3b
5 files changed
+32
-16
No files matched your search
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Qualify RAK4631 Full Companion with linked Meshtext support
|
||||
run: >-
|
||||
bash build.sh build-firmware RAK_4631_companion_radio_full
|
||||
--firmware-version v1.17.1.10-halo-keymind-cascade-dev
|
||||
--firmware-version v1.18.0.1-halo-keymind-cascade-dev
|
||||
--radio-preset usa-cascade-fixed --profile cascade --require-ota
|
||||
|
||||
- name: Verify linked Companion crypto, retained Reader and ARM stack use
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
# This configuration has no Meshtext/Ethernet application callbacks.
|
||||
run: >-
|
||||
bash build.sh build-firmware Xiao_nrf52_companion_radio_full
|
||||
--firmware-version v1.17.1.10-halo-keymind-cascade-dev
|
||||
--firmware-version v1.18.0.1-halo-keymind-cascade-dev
|
||||
--radio-preset usa-cascade-fixed --profile cascade --require-ota
|
||||
|
||||
- name: Qualify unified T114 Full Companion with automatic screen detection
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "PersistentStoreFormat.h"
|
||||
|
||||
namespace mesh { namespace power {
|
||||
|
||||
@@ -143,14 +144,11 @@ class RecoveryPolicy {
|
||||
static uint32_t elapsed(uint32_t now, uint32_t then) { return now - then; }
|
||||
|
||||
static uint32_t checksum(const RecoveryRecord& record) {
|
||||
uint32_t crc = 0xffffffff;
|
||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&record);
|
||||
for (size_t i = 0; i < offsetof(RecoveryRecord, crc); ++i) {
|
||||
crc ^= bytes[i];
|
||||
for (uint8_t bit = 0; bit < 8; ++bit)
|
||||
crc = (crc >> 1) ^ (0xedb88320u & (0u - (crc & 1u)));
|
||||
}
|
||||
return ~crc;
|
||||
// Retained records use the same IEEE polynomial as persistent storage,
|
||||
// with a final complement. Reuse its already-linked implementation while
|
||||
// preserving the record layout and checksum across firmware updates.
|
||||
return ~storage::updateCRC32(0xffffffffUL,
|
||||
reinterpret_cast<const uint8_t*>(&record), offsetof(RecoveryRecord, crc));
|
||||
}
|
||||
|
||||
static bool isValid(const RecoveryRecord& record) {
|
||||
|
||||
@@ -300,12 +300,10 @@ bool handleRegulatorCommand(const char* command, char* reply, size_t capacity) {
|
||||
}
|
||||
|
||||
void markRegulatorCleanReset() {
|
||||
if (initialized) recovery().markCleanReset();
|
||||
else {
|
||||
RecoveryPolicy policy(platformRecoveryRecord());
|
||||
policy.begin(ResetKind::Intentional, 0);
|
||||
policy.markCleanReset();
|
||||
}
|
||||
// Early resets still initialize the retained record, using the same policy
|
||||
// object as normal startup instead of constructing another on the stack.
|
||||
if (!initialized) recovery().begin(ResetKind::Intentional, 0);
|
||||
recovery().markCleanReset();
|
||||
}
|
||||
|
||||
void resumeRegulatorRecovery() {
|
||||
|
||||
@@ -25,6 +25,7 @@ class CompanionOtaIncludeTest(unittest.TestCase):
|
||||
with tempfile.TemporaryDirectory(prefix="meshcore-companion-includes-") as temp:
|
||||
directory = Path(temp)
|
||||
for header in (
|
||||
"helpers/RegulatorSettings.h",
|
||||
"helpers/ui/StartupScreen.h", "helpers/ui/DisplayPowerSettings.h",
|
||||
"helpers/UsbLoggingWatchdog.h", "helpers/UsbLoggingClientActivity.h",
|
||||
"Mesh.h", "helpers/BluetoothMac.h", "CompanionBluetooth.h",
|
||||
|
||||
@@ -212,6 +212,24 @@ int main(int argc, char** argv) {
|
||||
// A sample apparently newer than the last heartbeat is conservative until
|
||||
// that heartbeat catches up; subtraction cannot turn it into a fresh age.
|
||||
{ RecoveryPolicy p(r); p.begin(ResetKind::Crash, 0); assertCounts(p, 0, 0); }
|
||||
} else if (scenario == 16) {
|
||||
// Frozen retained record with two MCU crashes and one radio crash. Its CRC
|
||||
// and the fresh-record CRC below were independently calculated by zlib.
|
||||
const uint8_t legacy[] = {
|
||||
0x52, 0x47, 0x50, 0x52, 0x01, 0x00, 0x20, 0x00,
|
||||
0xbc, 0xcc, 0x5b, 0x07, 0x15, 0xcd, 0x5b, 0x07,
|
||||
0x0c, 0xcd, 0x5b, 0x07, 0x03, 0x00, 0x02, 0x01,
|
||||
0x4b, 0x05, 0x00, 0x00, 0x6b, 0x64, 0x72, 0xa2,
|
||||
};
|
||||
static_assert(sizeof(legacy) == sizeof(r), "frozen retained format");
|
||||
std::memcpy(&r, legacy, sizeof(r));
|
||||
{ RecoveryPolicy p(r); p.begin(ResetKind::Crash, 0);
|
||||
assertCounts(p, 3, 2, RECOVERY_MCU); }
|
||||
// Losing the final complement, seed or payload extent must fail this
|
||||
// compatibility check even if newly written records remain self-consistent.
|
||||
std::memset(&r, 0, sizeof(r));
|
||||
initial(r, RECOVERY_DOMAINS, 75, true, 123456789);
|
||||
assert(r.crc == 0x1d384636u);
|
||||
} else assert(false);
|
||||
std::cout << "PASS: regulator recovery " << scenario << '\n';
|
||||
}
|
||||
@@ -256,6 +274,7 @@ class RegulatorRecoveryTests(unittest.TestCase):
|
||||
"a boot is disarmed until the actual modes are selected",
|
||||
"saved and retained fallback masks merge",
|
||||
"future sample is ineligible until heartbeat catches up",
|
||||
"retained CRC remains compatible with independently encoded records",
|
||||
)
|
||||
for number, scenario in enumerate(scenarios):
|
||||
with self.subTest(scenario=scenario):
|
||||
|
||||
Reference in new issue
Block a user