mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-23 16:52:22 +00:00
fix(nrf52): avoid CCCD flash reset on Full Companion
This commit is contained in:
1 parent
ff50589b69
commit
af86517059
3 files changed
+86
No files matched your search
@@ -155,6 +155,7 @@ platform_packages =
|
||||
extra_scripts = create-uf2.py
|
||||
pre:scripts/nrf52_usb_power_fix.py
|
||||
pre:scripts/nrf52_internal_flash_fix.py
|
||||
pre:scripts/nrf52_ble_cccd_fix.py
|
||||
pre:scripts/nrf52_internal_bootloader_link.py
|
||||
; Nordic's builder otherwise overwrites the LTO-aware archive tools.
|
||||
pre:scripts/nrf52_lto_toolchain.py
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
"""Avoid Bluefruit's unstable live CCCD persistence on nRF52 Full Companions.
|
||||
|
||||
The pinned core saves every bonded CCCD write from its callback worker into
|
||||
InternalFS. On a T1000-E Full Companion this reproducibly resets the radio as
|
||||
the client enables notifications, even after formatting InternalFS. Bond-key
|
||||
persistence still works. The Companion client re-subscribes on connection;
|
||||
this workaround sacrifices CCCD persistence, not key-based reconnection.
|
||||
Patch a private build copy; never edit PlatformIO's shared framework cache.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
OLD_SAVE = """ {
|
||||
conn->saveCccd();
|
||||
}
|
||||
"""
|
||||
FIXED_SAVE = """ {
|
||||
#if !defined(COMPANION_RADIO_FULL) || !COMPANION_RADIO_FULL
|
||||
conn->saveCccd();
|
||||
#endif
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def patched_source(source):
|
||||
source = source.replace("\r\n", "\n")
|
||||
if FIXED_SAVE in source and OLD_SAVE not in source:
|
||||
return source
|
||||
if source.count(OLD_SAVE) != 1:
|
||||
raise RuntimeError(
|
||||
"nRF52 BLE CCCD fix: unrecognized framework source; review before building"
|
||||
)
|
||||
return source.replace(OLD_SAVE, FIXED_SAVE)
|
||||
|
||||
|
||||
def replace_framework_source(build_env, node):
|
||||
source = Path(node.srcnode().get_abspath())
|
||||
if source.name != "BLEGatt.cpp" or source.parent.name != "src":
|
||||
return node
|
||||
patched = patched_source(source.read_text(encoding="utf-8"))
|
||||
build_env.AppendUnique(CPPPATH=[str(source.parent)])
|
||||
destination = Path(build_env.subst("$BUILD_DIR")) / "patched-nrf52-ble" / "BLEGatt.cpp"
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not destination.exists() or destination.read_text(encoding="utf-8") != patched:
|
||||
destination.write_text(patched, encoding="utf-8")
|
||||
print("nRF52 BLE: Full Companion CCCD persistence workaround enabled")
|
||||
return build_env.File(str(destination))
|
||||
|
||||
|
||||
if "Import" in globals():
|
||||
Import("env")
|
||||
env.AddBuildMiddleware(replace_framework_source, "*BLEGatt.cpp")
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Guard the nRF52 Full Companion CCCD build-local workaround."""
|
||||
|
||||
from importlib.util import module_from_spec, spec_from_file_location
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SCRIPT = ROOT / "scripts/nrf52_ble_cccd_fix.py"
|
||||
spec = spec_from_file_location("nrf52_ble_cccd_fix", SCRIPT)
|
||||
module = module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
|
||||
class Nrf52BleCccdFixTest(unittest.TestCase):
|
||||
def test_only_full_companions_skip_persistence(self):
|
||||
patched = module.patched_source("before\n" + module.OLD_SAVE + "after\n")
|
||||
self.assertIn("!defined(COMPANION_RADIO_FULL) || !COMPANION_RADIO_FULL", patched)
|
||||
self.assertIn("conn->saveCccd();", patched)
|
||||
self.assertEqual(module.patched_source(patched), patched)
|
||||
|
||||
def test_unrecognized_core_fails_closed(self):
|
||||
with self.assertRaises(RuntimeError):
|
||||
module.patched_source("changed SDK layout")
|
||||
|
||||
def test_nrf52_base_loads_workaround(self):
|
||||
ini = (ROOT / "platformio.ini").read_text(encoding="utf-8")
|
||||
self.assertIn("pre:scripts/nrf52_ble_cccd_fix.py", ini)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user