mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-07 07:33:54 +00:00
PM debug v1
This commit is contained in:
@@ -49,6 +49,14 @@
|
||||
# excellent on a current meter. Check that log line before trusting any
|
||||
# measurement.
|
||||
#
|
||||
# PAD HOLD — light sleep powers down RTC_PERIPH, so every RTC-capable pad
|
||||
# (GPIO 0-21, which is all of them on these boards) loses its level unless
|
||||
# held. The paired overlay holds the SX1262 NSS and RESET; without that, a
|
||||
# floating NSS lets the sleeping radio clock garbage into its own retention
|
||||
# RAM and the node transmits ~30 dB down until the next reboot. The overlay
|
||||
# hardcodes NSS GPIO8 / RESET GPIO12 / &spi2 — verify a new board matches
|
||||
# before adding it to the allowlist below.
|
||||
#
|
||||
# Also required and supplied by the paired pm_esp32.overlay:
|
||||
# - &rtc_timer enabled. soc/espressif/common/power.c refuses to sleep without
|
||||
# it, logging "Sleep skipped. Make sure '&rtc_timer' is enabled as a wakeup
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* enough; this file does not need to be listed separately.
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/dt-bindings/gpio/espressif-esp32-gpio.h>
|
||||
|
||||
/*
|
||||
* The RTC timer is the wake source for every timed sleep. Upstream leaves it
|
||||
* status = "disabled" (zephyr/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi),
|
||||
@@ -34,3 +37,57 @@
|
||||
&gpio0 {
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
/*
|
||||
* Hold the SX1262 chip-select across light sleep.
|
||||
*
|
||||
* Light sleep powers down RTC_PERIPH on this SoC, and every LoRa pin on the
|
||||
* allowlisted boards is an RTC-capable pad (GPIO 0-21), so their levels are
|
||||
* NOT retained unless explicitly held. The chain:
|
||||
*
|
||||
* 1. patches/zephyr/0012 passes GPIO_INT_WAKEUP on DIO1. On the S3 that
|
||||
* lands on esp_sleep_enable_ext1_wakeup_io() (drivers/gpio/gpio_esp32.c,
|
||||
* SOC_PM_SUPPORT_EXT1_WAKEUP), i.e. RTC_EXT1_TRIG_EN.
|
||||
* 2. esp_sleep_start() only forces ESP_PD_DOMAIN_RTC_PERIPH on for
|
||||
* RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN. EXT1 is not in that mask, so the
|
||||
* domain is left AUTO and powered OFF for the whole sleep.
|
||||
* 3. ext1_wakeup_prepare() then calls rtcio_hal_hold_enable() for the EXT1
|
||||
* pin *only*, and only because RTC_PERIPH is off — IDF's own code
|
||||
* treating "RTC_PERIPH down" as "this pad cannot hold its own state".
|
||||
* DIO1 survives; nothing else does.
|
||||
* 4. Zephyr's general mechanism, esp32_sleep_gpio_prepare(), holds only pins
|
||||
* carrying ESP32_GPIO_SLEEP_HOLD_EN. Hence this override.
|
||||
*
|
||||
* NSS is the pin that matters. Undriven, it floats, and the SX1262 samples
|
||||
* SPI commands whenever NSS is low — so a sleeping chip sitting in warm-start
|
||||
* sleep with its entire configuration (PA config, OCP, SetTxParams) in
|
||||
* retention RAM is exposed to whatever the floating bus does. Nothing in the
|
||||
* driver ever re-issues SetTxParams: lora_config() is its only writer and
|
||||
* LoRaRadioBase::configure() short-circuits on every transmit after the first,
|
||||
* so a corrupted TX power persists until reboot or a `set tx <new value>`.
|
||||
* Symptom is a node that still relays but transmits ~30 dB down.
|
||||
*
|
||||
* Holding NSS high for the duration deselects the chip, which also makes SCK
|
||||
* and MOSI harmless — nothing can be clocked in while CS is deasserted, so
|
||||
* those pins do not need the pinctrl-side `sleep-hold-en`.
|
||||
*
|
||||
* All five allowlisted boards (heltec_wifi_lora32_v3/v4/v43,
|
||||
* heltec_wireless_tracker/_v2) wire the radio identically — &spi2, NSS GPIO8,
|
||||
* RESET GPIO12 — which is what lets this live in one shared overlay. Re-check
|
||||
* that before adding a board to the allowlist in CMakeLists.txt.
|
||||
*/
|
||||
&spi2 {
|
||||
cs-gpios = <&gpio0 8 (GPIO_ACTIVE_LOW | ESP32_GPIO_SLEEP_HOLD_EN)>;
|
||||
};
|
||||
|
||||
/*
|
||||
* RESET is open-drain active-low against the SX1262's internal pull-up, so an
|
||||
* unheld pad going high-Z already reads as "not reset" and this is belt and
|
||||
* braces rather than a known fault. It costs nothing and removes the question
|
||||
* of what the pad does on the way into and out of power-down — a spurious low
|
||||
* here would reset the radio outright.
|
||||
*/
|
||||
&lora0 {
|
||||
reset-gpios = <&gpio0 12 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW |
|
||||
ESP32_GPIO_SLEEP_HOLD_EN)>;
|
||||
};
|
||||
|
||||
@@ -71,7 +71,7 @@ diff --git a/drivers/lora/native/sx126x/sx126x.c b/drivers/lora/native/sx126x/sx
|
||||
index 30243ba5dc7..f0794661515 100644
|
||||
--- a/drivers/lora/native/sx126x/sx126x.c
|
||||
+++ b/drivers/lora/native/sx126x/sx126x.c
|
||||
@@ -6,14 +6,21 @@
|
||||
@@ -6,14 +6,52 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/lora.h>
|
||||
@@ -89,6 +89,37 @@ index 30243ba5dc7..f0794661515 100644
|
||||
+ * system work queue so USB/BLE/timer work items cannot delay packet RX. */
|
||||
+#define SX126X_DIO1_WQ_STACK_SIZE 2560
|
||||
+K_THREAD_STACK_DEFINE(sx126x_dio1_wq_stack, SX126X_DIO1_WQ_STACK_SIZE);
|
||||
+
|
||||
+/* PA ramp time handed to SetTxParams at every site that programs TX power.
|
||||
+ *
|
||||
+ * Deliberately 800 us where RadioLib, loramac-node and Arduino MeshCore all
|
||||
+ * use 200 us -- do not "fix" this back to match them without reading the
|
||||
+ * following, and do not change one call site alone: two writers disagreeing
|
||||
+ * on the ramp would make TX spectral behaviour depend on which ran last.
|
||||
+ *
|
||||
+ * What it buys: a slower PA envelope puts less spectral energy at the burst
|
||||
+ * edges, which is mask margin (ETSI EN 300 220 / FCC) at TX start and stop.
|
||||
+ * That is worth most on the boards carrying an external PA or FEM, where
|
||||
+ * splatter gets amplified along with the wanted signal.
|
||||
+ *
|
||||
+ * What it does NOT buy, despite being an easy assumption: any link-budget or
|
||||
+ * noise-immunity benefit. Ramp time shapes our own transmitter's skirts. It
|
||||
+ * does not raise TX power, change what a distant receiver hears in-band, or
|
||||
+ * help its demodulator. The only way it helps anyone's reception is by not
|
||||
+ * desensitising a CO-SITED or adjacent-channel radio -- real on a hilltop
|
||||
+ * with several co-located nodes, negligible between nodes kilometres apart.
|
||||
+ *
|
||||
+ * What it costs: 600 us more TX startup than the 200 us default, and nothing
|
||||
+ * else. The ramp completes before modulation begins -- the chip holds BUSY
|
||||
+ * after SetTx until ramp-up is done, which is why RadioLib waits on exactly
|
||||
+ * that edge -- so it consumes no preamble symbols at any SF/BW and does not
|
||||
+ * eat into the RX duty-cycle preamble budget. Airtime is unchanged; both
|
||||
+ * reference stacks likewise exclude ramp from their time-on-air maths. The
|
||||
+ * one behavioural side effect is that the gap between "LBT reports the
|
||||
+ * channel clear" and "we are actually radiating" grows by those 600 us,
|
||||
+ * which is negligible against a contention window measured in milliseconds.
|
||||
+ */
|
||||
+#define SX126X_TX_RAMP_TIME SX126X_RAMP_800_US
|
||||
+
|
||||
#define SX126X_REST_STATE \
|
||||
(IS_ENABLED(CONFIG_LORA_SX126X_NATIVE_SLEEP) \
|
||||
@@ -728,7 +759,7 @@ index 30243ba5dc7..f0794661515 100644
|
||||
ret = sx126x_hal_configure_tx_params(dev, config->tx_power,
|
||||
config->frequency,
|
||||
- SX126X_RAMP_200_US);
|
||||
+ SX126X_RAMP_800_US);
|
||||
+ SX126X_TX_RAMP_TIME);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -862,10 +893,41 @@ index 30243ba5dc7..f0794661515 100644
|
||||
data->tx_async_signal = async;
|
||||
k_msgq_purge(&data->tx_msgq);
|
||||
|
||||
@@ -777,6 +1349,31 @@ static int sx126x_lora_send_async(const struct device *dev,
|
||||
@@ -777,6 +1349,62 @@ static int sx126x_lora_send_async(const struct device *dev,
|
||||
/* Enable antenna and set TX path */
|
||||
sx126x_set_rf_path(dev, true, true);
|
||||
|
||||
+ /* Re-assert PA config, OCP and TX power immediately before SetTx.
|
||||
+ *
|
||||
+ * sx126x_config() is otherwise the only writer of these three, and the
|
||||
+ * C++ adapter's config cache (LoRaRadioBase::configure) short-circuits
|
||||
+ * on every transmit after the first -- so between two lora_config()
|
||||
+ * calls nothing re-verifies what the chip is actually holding. The
|
||||
+ * chip keeps them in warm-start retention RAM across its sleep cycles,
|
||||
+ * which makes them precisely the state a disturbed SPI bus or a stray
|
||||
+ * command corrupts silently: the node goes on relaying, because
|
||||
+ * restart_rx re-issues SetRx constantly, while transmitting tens of dB
|
||||
+ * down until someone reboots it. That is not hypothetical -- ESP32
|
||||
+ * light sleep leaving NSS undriven produced exactly it; the cause is
|
||||
+ * fixed at source in boards/common/pm_esp32.overlay and this is the
|
||||
+ * belt-and-braces half that stops the class of fault rather than the
|
||||
+ * one instance.
|
||||
+ *
|
||||
+ * Costs no receive time. It runs after LBT has passed, with the chip
|
||||
+ * already committed to TX, and is ~15 bytes of SPI -- unlike forcing a
|
||||
+ * full lora_config(), which would have to tear RX down first (its
|
||||
+ * entry CAS rejects SX126X_STATE_RX) and re-run image calibration.
|
||||
+ *
|
||||
+ * Keep the ramp time identical to the sx126x_config() call site: two
|
||||
+ * writers disagreeing on it would make TX spectral behaviour depend on
|
||||
+ * which one ran last. */
|
||||
+ ret = sx126x_hal_configure_tx_params(dev, data->config.tx_power,
|
||||
+ data->config.frequency,
|
||||
+ SX126X_TX_RAMP_TIME);
|
||||
+ if (ret < 0) {
|
||||
+ goto out_error;
|
||||
+ }
|
||||
+
|
||||
+#ifdef CONFIG_LORA_SX126X_NATIVE_STANDALONE /* STM32WL HAL clamps in its own configure_tx_params; its config has no is_sx1261 */
|
||||
+ /* Sec 15.2 TX Clamp workaround (datasheet errata) -- SX1262 only.
|
||||
+ * Set bits [4:1] of register 0x08D8 before SetTx to prevent
|
||||
@@ -986,7 +1048,7 @@ index 30243ba5dc7..f0794661515 100644
|
||||
/* Set PA config and TX power */
|
||||
ret = sx126x_hal_configure_tx_params(dev, tx_power, frequency,
|
||||
- SX126X_RAMP_200_US);
|
||||
+ SX126X_RAMP_800_US);
|
||||
+ SX126X_TX_RAMP_TIME);
|
||||
if (ret < 0) {
|
||||
sx126x_set_sleep(dev);
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
||||
Reference in New Issue
Block a user