Skip to content

Commit

Permalink
lora/sx126x: Fix busy timeout handling.
Browse files Browse the repository at this point in the history
- If no reset pin was set, calling standby() in the constructor
  would enable the TCXO (XOSC) before the timeout was correctly set.

- This manifested as a BUSY timeout on the STM32WL5, first time after power
on reset.

- Clean up the general handling of BUSY timeouts, but also add some safety
margin to the base timeout just in case (not an issue, is only a stop-gap
to prevent the modem blocking indefinitely.)

Signed-off-by: Angus Gratton <[email protected]>
  • Loading branch information
projectgus authored and dpgeorge committed Aug 26, 2023
1 parent 0bdecbc commit 7fcc728
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 6 deletions.
2 changes: 1 addition & 1 deletion micropython/lora/lora-stm32wl5/lora/stm32wl5.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def __init__(
DIO1(),
False, # dio2_rf_sw
tcxo_millivolts, # dio3_tcxo_millivolts
1000, # dio3_tcxo_start_time_us
10_000, # dio3_tcxo_start_time_us, first time after POR is quite long
None, # reset
lora_cfg,
ant_sw,
Expand Down
12 changes: 7 additions & 5 deletions micropython/lora/lora-sx126x/lora/sx126x.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
# In any case, timeouts here are to catch broken/bad hardware or massive driver
# bugs rather than commonplace issues.
#
_CMD_BUSY_TIMEOUT_BASE_US = const(3000)
_CMD_BUSY_TIMEOUT_BASE_US = const(7000)

# Datasheet says 3.5ms needed to run a full Calibrate command (all blocks),
# however testing shows it can be as much as as 18ms.
Expand Down Expand Up @@ -148,7 +148,9 @@ def __init__(
if hasattr(dio1, "init"):
dio1.init(Pin.IN)

self._busy_timeout = _CMD_BUSY_TIMEOUT_BASE_US
self._busy_timeout = _CMD_BUSY_TIMEOUT_BASE_US + (
dio3_tcxo_start_time_us if dio3_tcxo_millivolts else 0
)

self._buf = bytearray(9) # shared buffer for commands

Expand All @@ -168,7 +170,8 @@ def __init__(
reset(1)
time.sleep_ms(5)
else:
self.standby() # Otherwise, at least put the radio to a known state
# Otherwise, at least put the radio to a known state
self._cmd("BB", _CMD_SET_STANDBY, 0) # STDBY_RC mode, not ready for TCXO yet

status = self._get_status()
if (status[0] != _STATUS_MODE_STANDBY_RC and status[0] != _STATUS_MODE_STANDBY_HSE32) or (
Expand All @@ -187,7 +190,6 @@ def __init__(
#
# timeout register is set in units of 15.625us each, use integer math
# to calculate and round up:
self._busy_timeout = (_CMD_BUSY_TIMEOUT_BASE_US + dio3_tcxo_start_time_us) * 2
timeout = (dio3_tcxo_start_time_us * 1000 + 15624) // 15625
if timeout < 0 or timeout > 1 << 24:
raise ValueError("{} out of range".format("dio3_tcxo_start_time_us"))
Expand Down Expand Up @@ -668,7 +670,7 @@ def _wait_not_busy(self, timeout_us):
while self._busy():
ticks_diff = time.ticks_diff(time.ticks_us(), start)
if ticks_diff > timeout_us:
raise RuntimeError("BUSY timeout")
raise RuntimeError("BUSY timeout", timeout_us)
time.sleep_us(1)
if _DEBUG and ticks_diff > 105:
# By default, debug log any busy time that takes longer than the
Expand Down

0 comments on commit 7fcc728

Please sign in to comment.