* NimBLE-Arduino -> Arduino "BLE" (3.3.x) migration
* More NimBLE
* Fix Device Name in ATT Read Request (0x2A00).
Device Name is exposed in two places:
- Advertisement data: this is set properly in startAdvertising.
- GATT attribute Device Name (0x2A00). This one is handled internally in NimBLE
and comes from ble_svc_gap_device_name_set. This is set initially, but then
BLEDevice::createServer calls ble_svc_gap_init which resets the device name.
This causes the device to apparently "change name after pairing":
< ACL Data TX:... flags 0x00 dlen 7 #113 [hci0] 14.241149
ATT: Read Request (0x0a) len 2
Handle: 0x0003 Type: Device Name (0x2a00)
> ACL Data RX: Handle 2048 flags 0x02 dlen 11 #115 [hci0] 14.269050
ATT: Read Response (0x0b) len 6
Value[6]: 6e696d626c65 # "nimble"
Workaround this by setting the device name once again after
BLEDevice::createServer.
* Temporarily lower CORE_DEBUG_LEVEL to INFO to avoid triggering an apparent ESP-IDF Bluetooth bug when re-connecting to Pixel 8 Android devices.
Initial pairing works, but after ESP32 is rebooted, phone fails to reconnect. Meshtastic app shows it as disconnecting immediately. LightBlue shows a more detailed error "Peripheral Connection - Warning: onConnectionStatusChange: status 61" (0x3D - MIC Failure).
Bug report to Espresssif: https://github.com/espressif/esp-idf/issues/18126#issuecomment-4286197744
* Temporarily disable ble_gap_set_data_len, causes crash with Pixel 8 Android reconnect.
Crash looks like this:
[ 11966][E][BLEAdvertising.cpp:341] setScanResponseData(): ble_gap_adv_rsp_set_data: 22
[ 11975][E][BLEAdvertising.cpp:1554] start(): Host reset, wait for sync.
ERROR | ??:??:?? 11 BLE failed to start advertising
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x420e6190 PS : 0x00060730 A0 : 0x820e158b A1 : 0x3fce50c0
A2 : 0x00000000 A3 : 0x3fcb8600 A4 : 0x3fcb85cc A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000c03 A8 : 0x00000000 A9 : 0x3fce50b0
A10 : 0x0000000e A11 : 0x00000000 A12 : 0x00000010 A13 : 0x3fce50e0
A14 : 0x00000c03 A15 : 0x00000001 SAR : 0x0000001e EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0x00000000
Backtrace: 0x420e618d:0x3fce50c0 0x420e1588:0x3fce5110 0x420dfe87:0x3fce5200 0x420dfefb:0x3fce5220 0x420dff3f:0x3fce5240 0x4219602b:0x3fce5260 0x4037b0e5:0x3fce5280 0x4201edf3:0x3fce52a0
Connection seems fast enough even without this. We'll investigate the
reason for the crash and re-enable once it's safe.
---------
Co-authored-by: Catalin Patulea <cronos586@gmail.com>
* Infinite calibration loop fix
* Save calibration
* Screen refresh
* reduce repeated code
* reduce repeated code to reduce flash
* fix Waypoint compass size and no fix no heading labels
* Don't show compass unless we have a heading and location
* If no calculated heading from moving, we should have no heading
* Slow walking calculated heading and auto stale heading when not moving
* Triming flash space
* cleanup
* show "?" when no location or heading for distance and heading screen
* cleanup
* Stale heading logic
* final trim
* Compass Calibration screen redesign
* Trunk Fix
* Compile fix
* patch
* Update src/motion/MotionSensor.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update WaypointModule.cpp
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Implementation of Status Message
* Change drawNodeInfo to drawFavoriteNode
* Truncate overflow on Favorite frame
* Set MAX_RECENT_STATUSMESSAGES to 5 to meet memory usage targets
The linker script was created by merging variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/ldscript.ld and system/ldscript.ld from stm32duino/Arduino_Core_STM32.
mallinfo().fordblks counts only free bytes within the committed arena.
On STM32WL (newlib sbrk heap) the arena grows lazily from _end toward SP,
so fordblks reads near-zero at early boot even when ~48 KB of addressable
space remains. This caused NodeDB::isFull() to fire prematurely and evict
nodes on a freshly booted device.
Fix getFreeHeap() to include uncommitted sbrk headroom (SP - sbrk(0)) so
the returned value reflects true available memory throughout the boot
lifecycle.
Introduce MESHTASTIC_DYNAMIC_SBRK_HEAP as an opt-in build flag (set in
stm32.ini) so the fix is gated to platforms with a dynamic sbrk heap
rather than a static heap. Future platforms with the same heap model can
opt in by adding this flag.
Signed-off-by: Andrew Yong <me@ndoo.sg>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrate STM32 battery monitoring into AnalogBatteryLevel, supporting
external GPIO ADC pins as well as internal VBAT channel.
Features:
- ADC reading using STM32 LL (Lower Layer) macros supporting external
ADC channels and internal VBAT channel (AVBAT)
- ADC compensation using STM32 LL macros with factory-calibrated VREFINT
(AVREF) for accurate voltage measurement
- LFP battery OCV curve for STM32WL using AVBAT (STM32 VDD absolute
maximum supply voltage 3.9V, direct connection of Li-Po batteries is
not supported)
Internal VBAT channel implemented in:
- Russell
- RAK3172
In these variants, ADC_MULTIPLIER = (1.01f * 3) = 3.30 as there is a
3:1 internal divider (DS13105 Rev 12 §5.3.21), and a bit of tolerance
as the actual 10% spec leads to readings much too high.
Assisted-by: Claude:sonnet-4-5
Signed-off-by: Andrew Yong <me@ndoo.sg>
* Fix heap blowout on TBeams
* Update src/graphics/draw/MessageRenderer.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Set MESSAGE_HISTORY_LIMIT to 10 for original ESP32 to optimize RAM usage
* Optimize message frame allocation to prevent excessive memory usage
* Refine message history limits for resource-constrained builds and cap cached lines to prevent heap overflow
* Update src/graphics/draw/MessageRenderer.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix heap blowout on TBeams
* Update src/graphics/draw/MessageRenderer.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Set MESSAGE_HISTORY_LIMIT to 10 for original ESP32 to optimize RAM usage
* Optimize message frame allocation to prevent excessive memory usage
* Refine message history limits for resource-constrained builds and cap cached lines to prevent heap overflow
* Update src/graphics/draw/MessageRenderer.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix(native): implement BinarySemaphorePosix with proper pthread synchronization
The BinarySemaphorePosix class (used on all Linux/portduino/native builds)
had stub implementations: give() was a no-op and take() just called
delay(msec) and returned false. This broke the cooperative thread scheduler
on native platforms — threads could not wake the main loop, radio RX
interrupts were missed, and telemetry never transmitted over the mesh.
Replace the stubs with a proper binary semaphore using pthread_mutex_t +
pthread_cond_t + bool signaled:
- take(msec): pthread_cond_timedwait with CLOCK_REALTIME timeout, consumes
signal atomically (binary semaphore semantics)
- give(): sets signaled=true, signals condition variable
- giveFromISR(): delegates to give(), sets pxHigherPriorityTaskWoken
Tested on Raspberry Pi 3 Model B (ARM64, Debian Bookworm) with Adafruit
LoRa Radio Bonnet (SX1276). Before fix: no radio TX/RX, no telemetry on
mesh. After fix: bidirectional LoRa, MQTT gateway, telemetry all working.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ARCH_PORTDUINO
* Refactor BinarySemaphorePosix header for ARCH_PORTDUINO
* Change preprocessor directive from ifndef to ifdef
* Gate new Semaphore code to Portduino and fix STM compilation
* Binary Semaphore Posix better error handling
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
* fix(native): implement BinarySemaphorePosix with proper pthread synchronization
The BinarySemaphorePosix class (used on all Linux/portduino/native builds)
had stub implementations: give() was a no-op and take() just called
delay(msec) and returned false. This broke the cooperative thread scheduler
on native platforms — threads could not wake the main loop, radio RX
interrupts were missed, and telemetry never transmitted over the mesh.
Replace the stubs with a proper binary semaphore using pthread_mutex_t +
pthread_cond_t + bool signaled:
- take(msec): pthread_cond_timedwait with CLOCK_REALTIME timeout, consumes
signal atomically (binary semaphore semantics)
- give(): sets signaled=true, signals condition variable
- giveFromISR(): delegates to give(), sets pxHigherPriorityTaskWoken
Tested on Raspberry Pi 3 Model B (ARM64, Debian Bookworm) with Adafruit
LoRa Radio Bonnet (SX1276). Before fix: no radio TX/RX, no telemetry on
mesh. After fix: bidirectional LoRa, MQTT gateway, telemetry all working.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ARCH_PORTDUINO
* Refactor BinarySemaphorePosix header for ARCH_PORTDUINO
* Change preprocessor directive from ifndef to ifdef
* Gate new Semaphore code to Portduino and fix STM compilation
* Binary Semaphore Posix better error handling
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
* Add powerlimits to reconfigured radio settings as well as init settings.
* Refactor preamble length handling for wide LoRa configurations
* Moved the preamble setting to the main class and made the references static