From 7c4199c8bf94f81fd78c754b7afe829e5b4881b7 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:49:16 +0200 Subject: [PATCH] thinknode m6 gps & regulator fix --- .../nrf52840/thinknode_m6/thinknode_m6.dts | 92 +++++++++++-------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/zephcore/boards/nrf52840/thinknode_m6/thinknode_m6.dts b/zephcore/boards/nrf52840/thinknode_m6/thinknode_m6.dts index 17f6abf..5853725 100644 --- a/zephcore/boards/nrf52840/thinknode_m6/thinknode_m6.dts +++ b/zephcore/boards/nrf52840/thinknode_m6/thinknode_m6.dts @@ -8,7 +8,7 @@ * - nRF52840 SoC with BLE (DCDC regulator, NRF52BoardDCDC) * - SX1262 LoRa radio on SPI1 (DIO2 RF switch, DIO3 TCXO 3.3V, 22dBm) * NSS=P1.12, DIO1=P1.06, RESET=P1.10, BUSY=P1.11 - * - GPS L76K on UART0 (9600 baud, generic NMEA) + * - GPS L76K on UART0 (9600 baud, CASIC/Air530Z — luatos,air530z driver) * Control: GPS_EN=P0.06 (active-HIGH), GPS_RESET=P0.29 (active-LOW), * GPS_STANDBY=P0.30, GPS_PPS=P0.31 * - Battery ADC on AIN4 (P0.28), 1.75:1 voltage divider @@ -116,6 +116,19 @@ startup-delay-us = <1000>; }; + /* ADC_CTRL (PIN_ADC_CTRL = P0.11) — enables the VBAT resistor divider only + * while a battery read is in progress, matching Arduino MeshCore + * (variant.cpp holds it LOW at rest; ThinkNodeM6Board pulses it HIGH for + * the read). ZephyrBoard::getBattMilliVolts() toggles this regulator + * (regulator_enable + 10ms settle, then regulator_disable) around the ADC + * sample. No regulator-boot-on: it stays disabled (P0.11 LOW) until the + * first read, so the divider doesn't leak current continuously. */ + vbat_enable: vbat-enable { + compatible = "regulator-fixed"; + regulator-name = "vbat-enable"; + enable-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + }; + /* GPS enable (GPS_EN = P0.06, active-HIGH) — managed by ZephyrGPSManager */ gps_en: gps-enable { compatible = "gpio-leds"; @@ -125,23 +138,9 @@ }; }; - /* GPS hardware reset (GPS_RESET = P0.29, active-LOW) */ - gps_rst: gps-reset { - compatible = "gpio-leds"; - gps_reset_pin: gps_reset { - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; - label = "GPS Reset"; - }; - }; - - /* GPS standby (GPS_STANDBY = P0.30, active-HIGH = standby) */ - gps_stby: gps-standby { - compatible = "gpio-leds"; - gps_standby_pin: gps_standby { - gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; - label = "GPS Standby"; - }; - }; + /* GPS_RESET (P0.29) is driven statically HIGH (de-asserted) by a gpio-hog + * in &gpio0 below — see the note there. Arduino MeshCore does the same + * (variant.cpp: digitalWrite(PIN_GPS_RESET, HIGH), never pulsed). */ aliases { led0 = &led_red; @@ -150,9 +149,14 @@ sw0 = &user_button; watchdog0 = &wdt0; lora0 = &lora; - gps-enable = &gps_enable_pin; - gps-reset = &gps_reset_pin; - gps-sleep-int = &gps_standby_pin; + /* Only gps-enable is wired into the ZephCore GPS control path. + * gps-reset / gps-sleep-int are intentionally NOT aliased: the + * L76K (CASIC/Air530Z) is driven by the luatos,air530z driver via + * on-off-gpios, and exposing those aliases would push M6 down the + * T1000-E GPS sequence in ZephyrGPSManager (HAS_GPS_SLEEP/RESET). + * GPS_RESET (P0.29) and GPS_STANDBY (P0.30) are hogged HIGH in + * &gpio0 instead — static drive, matching Arduino MeshCore. */ + gps-enable = &gps_enable_pin; }; }; @@ -191,14 +195,30 @@ &gpio0 { status = "okay"; - /* ADC control (PIN_ADC_CTRL = P0.11) — always HIGH to enable battery ADC. - * Arduino code toggles this before/after ADC reads; keeping it permanently - * HIGH is safe and avoids needing custom ADC ctrl support in ZephCore. */ - adc-ctrl-hog { + /* ADC control (P0.11) is driven per-read by the vbat_enable regulator + * (see the / node) — not hogged HIGH — so the VBAT divider only draws + * current during a battery sample, matching Arduino MeshCore. */ + + /* GPS control lines held static, mirroring Arduino MeshCore variant.cpp + * (GPS_EN is driven separately by the luatos,air530z on-off-gpios): + * GPS_STANDBY (P0.30) HIGH — L76K runs, never parked in standby. + * GPS_RESET (P0.29) HIGH — reset de-asserted (active-LOW line). + * M6 has no physical GPS switch; runtime on/off is via GPS_EN + * (gps-enable alias) under software/CLI control. Hogs are used so the + * pins are actively driven at boot without needing a consumer — the + * gpio-leds nodes are not bound by any driver in this build. */ + gps-standby-hog { gpio-hog; - gpios = <11 GPIO_ACTIVE_HIGH>; + gpios = <30 GPIO_ACTIVE_HIGH>; output-high; - line-name = "ADC Ctrl"; + line-name = "GPS Standby"; + }; + + gps-reset-hog { + gpio-hog; + gpios = <29 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "GPS Reset"; }; }; @@ -208,14 +228,12 @@ /* GPS on UART0 (9600 baud) * - * L76K GPS module (generic NMEA, multi-constellation). - * Control pins managed by ZephyrGPSManager via aliases: - * gps-enable (GPS_EN = P0.06): HIGH = GPS powered/active - * gps-reset (GPS_RESET = P0.29): LOW = reset asserted - * gps-sleep-int (GPS_STANDBY = P0.30): HIGH = standby - * - * zephyr,deferred-init: GPS must be powered (GPS_EN HIGH) before NMEA - * output begins. ZephyrGPSManager asserts GPS_EN then calls device_init(). */ + * L76K GPS module — CASIC/Air530Z family, same silicon as the ThinkNode M1. + * Uses the luatos,air530z driver (PCAS/NMEA), which drives GPS power itself + * via on-off-gpios (P0.06 = GPS_EN, shared with the gps-enable alias used for + * runtime power control in ZephyrGPSManager). No zephyr,deferred-init: the + * driver powers the module on-off-gpios HIGH at init before opening the pipe. + * GPS_RESET (P0.29) and GPS_STANDBY (P0.30) are hogged HIGH in &gpio0. */ &uart0 { compatible = "nordic,nrf-uarte"; status = "okay"; @@ -225,8 +243,8 @@ pinctrl-names = "default", "sleep"; gnss: gnss { - compatible = "gnss-nmea-generic"; - zephyr,deferred-init; + compatible = "luatos,air530z"; + on-off-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; }; };