BT1035: fix SYS_CTRL power-on sequencing per Feasycom programming guide
The Feasycom BT1035 programming user guide's own pin table (§2.2, pin
34 SYS_CTRL) reads "Delay 100ms, pull high" -- the previous reset
sequence here asserted SYS_CTRL high at the very same instant as
RESET, with zero lead-in delay, racing the module's own documented
power-on requirement (the datasheet's §4.7 separately confirms
SYS_CTRL must be asserted >20ms before internal regulators even start
powering up). Rewrote resetAndInitOnce() to hold both pins low for a
100ms lead-in matching the guide exactly, then bring SYS_CTRL high,
then an extra 50ms settle margin before releasing RESET into a module
that's had a chance to actually power up first.
This is verified correct against the manufacturer's own documented
timing and is worth keeping regardless of its effect on any one
symptom, but it does NOT fully explain this project's intermittent
BT1035 boot failures ("no spontaneous UART bytes after hardware
reset"): a deep investigation session confirmed the same failure
still occurs, at the same rate, across genuine physical power cycles
(not just soft resets) with this fix applied, extended UART listen
windows (tested up to 10s vs the normal 3.5s), and independently
schematic-verified-correct GPIO pin assignments, UART TX/RX wiring,
AT command bytes, and shared 3.3V regulator sizing. Unlike the
Si4684 ARG1-offset bug earlier this session -- which failed 100% of
the time, deterministically, from a real code defect -- this failure
is non-deterministic across identical power-on sequences with
identical code, which does not match a firmware logic-bug signature.
Root cause remains open; see docs/si4684-rf-investigation-report.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0178rASQ6ZETPMUamvpoR2KR
This commit is contained in:
@@ -38,6 +38,12 @@ constexpr int kUartTxBuffer = 256;
|
||||
constexpr int kResponseTimeoutMs = 2000;
|
||||
constexpr int kPostResetMs = 500;
|
||||
constexpr int kPostUartMs = 100;
|
||||
/** Feasycom BT1035 programming user guide §2.2 (pin 34 SYS_CTRL): "Delay
|
||||
* 100ms, pull high". */
|
||||
constexpr int kSysCtlLeadInMs = 100;
|
||||
/** Margin beyond the datasheet's own >20ms SYS_CTRL-assertion-to-power-up
|
||||
* minimum (§4.7), for regulator/crystal settling before RESET releases. */
|
||||
constexpr int kSysCtlSettleMs = 50;
|
||||
/** Observed intermittently: the module sometimes needs a second RESET#
|
||||
* pulse to come up (power-up timing jitter between cold/warm boots) —
|
||||
* a single attempt with no retry was found to explain sporadic total
|
||||
@@ -913,9 +919,20 @@ std::expected<void, Bt1035Error> Bt1035Driver::runInitSequence()
|
||||
|
||||
std::expected<void, Bt1035Error> Bt1035Driver::resetAndInitOnce()
|
||||
{
|
||||
gpio_set_level(static_cast<gpio_num_t>(pins_.sysCtlGpio), 1);
|
||||
// Feasycom BT1035 programming user guide §2.2, pin 34 SYS_CTRL:
|
||||
// "Delay 100ms, pull high" — the datasheet's own OFF-state timing spec
|
||||
// (§4.7) says SYS_CTRL must be asserted >20ms before the internal
|
||||
// regulators start powering up at all, so pulling it high with no
|
||||
// lead-in delay (the previous sequence here) races the chip's own
|
||||
// power-on requirement. Held low with RESET already asserted, then a
|
||||
// 100ms lead-in exactly matching the guide, then SYS_CTRL high, then
|
||||
// extra settle time before releasing RESET into a chip that's had a
|
||||
// chance to actually power up first.
|
||||
gpio_set_level(static_cast<gpio_num_t>(pins_.sysCtlGpio), 0);
|
||||
gpio_set_level(static_cast<gpio_num_t>(pins_.resetGpio), 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
vTaskDelay(pdMS_TO_TICKS(kSysCtlLeadInMs));
|
||||
gpio_set_level(static_cast<gpio_num_t>(pins_.sysCtlGpio), 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(kSysCtlSettleMs));
|
||||
gpio_set_level(static_cast<gpio_num_t>(pins_.resetGpio), 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(kPostResetMs));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user