t4as

Research note · 2026-05-11

nRF54L15 Adapted Minimal PAwR/PAST Reproducer Result

Date: 2026-05-11

This test forks the stock Zephyr PAwR/PAST samples into isolated diagnostics under samples_nrf54/central_esl/diagnostics/. The production tag application was not edited. After the test, the nRF52840 tag was restored from 1wire_blesensro_prod/build_debug/merged.hex, and the nRF54L15 AP was restored from samples_nrf54/central_esl/build_nrf54l15_connectkit/merged.hex.

Diagnostic Samples

AP / PAST sender:

  • ../diagnostics/pawr_esl_profile_adv/src/main.c
  • Board: nrf54l15_connectkit/nrf54l15/cpuapp
  • Default profile: SID 8, periodic interval 1408, one subevent, subevent interval 11, response slot delay 8, response slot spacing 3, response slots 8, forced LE 1M secondary, extended advertising interval 160.

Tag / PAST receiver:

  • ../diagnostics/pawr_esl_profile_sync/src/main.c
  • Board: adafruit_itsybitsy/nrf52840
  • Based on Zephyr periodic_sync_rsp, with additional diagnostic prints for sync, timing writes, receive OK, and receive fail paths. The board did not expose those prints on a usable serial console in this setup, so AP-side responses are the primary pass/fail signal for these runs.

Baseline Comparison

The unmodified stock Zephyr samples worked on the same hardware, as documented in NRF54L15_MINIMAL_ZEPHYR_SAMPLE_RESULT.md. That positive control produced 176 AP-side Response: subevent markers after PAST in a 150-second capture.

ESL-Profile Timing Run

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_esl_profile_timing/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=1,subevent_interval=11,rsp_delay=8,rsp_spacing=3,rsp_slots=8,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 8
  • PAwR config written: 8
  • #DIAG_ADV_SET_OK: 103
  • #DIAG_ADV_RESPONSE: 1
  • Disconnected, reason: 8

Only one response was observed:

#DIAG_ADV_RESPONSE:subevent=0,slot=6,len=5
    0xFF: 590024

Interpretation: the minimal Zephyr-derived sample reproduces the non-sustained response behavior when moved to the ESL-like PAwR profile. This clears the production ESL application as the required trigger for the basic failure.

Long-Interval / Wide-Slot Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_wide_slots_real/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=1,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 5
  • PAwR config written: 5
  • #DIAG_ADV_SET_OK: 85
  • #DIAG_ADV_RESPONSE: 0
  • Disconnected, reason: 5

Interpretation: widening the response-slot timing did not recover sustained responses. The trigger is therefore not only the tight ESL response-slot spacing. The next split should isolate long periodic interval 1408 from one-subevent PAwR, because this wide-slot comparison still used both.

Long-Interval / One-Subevent / Single-Sync Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_one_subevent_single_sync_retry/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=1,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • Connected: 1
  • PAST sent: 1
  • PAwR config written: 1
  • #DIAG_KEEP_SYNC_ACTIVE: 1
  • #DIAG_ADV_SET_OK: 86
  • #DIAG_ADV_RESPONSE: 0
  • Disconnected, reason: 0
  • Maximum number of syncs onboarded: 0

Configured subevent/slot pair:

  • Subevent 0, slot 0, kept active for the rest of the capture.

Interpretation: repeated PAST/re-onboarding is not required to reproduce the long-interval / one-subevent failure. A single successful PAST/config write followed by an intentionally held connection produced no AP-side responses while the AP continued accepting subevent-data updates.

Stock-Interval / One-Subevent Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_stock_interval_one_subevent/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=255,num_subevents=1,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 4
  • PAwR config written: 4
  • #DIAG_ADV_SET_OK: 376
  • #DIAG_ADV_RESPONSE: 270
  • Disconnected, reason: 3

Interpretation: one-subevent PAwR is not sufficient to trigger the failure. With the stock periodic interval 255 and one subevent, the same diagnostic sample sustained responses. This points the next investigation at the long periodic interval 1408, or the interaction between long interval and PAST/re-onboarding.

Long-Interval / Five-Subevent Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_5_subevents/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=5,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 15
  • PAwR config written: 15
  • #DIAG_ADV_SET_OK: 170
  • #DIAG_ADV_RESPONSE: 12
  • Disconnected, reason: 14

Interpretation: long periodic interval 1408 is not sufficient by itself to trigger the zero-or-one-response failure. With stock-style 5 subevents and wide response slots, the same diagnostic sample repeatedly produced AP-side responses after PAST/config cycles. This narrows the suspicious profile to the combination of long interval 1408 and one response-capable subevent.

Long-Interval / One-Subevent / 2M Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_one_subevent_2m/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=1,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=2M

Marker counts:

  • PAST sent: 5
  • PAwR config written: 5
  • #DIAG_ADV_SET_OK: 69
  • #DIAG_ADV_RESPONSE: 0
  • Disconnected, reason: 5
  • Maximum number of syncs onboarded: 1

Interpretation: changing the secondary PHY back to 2M does not recover the failing long-interval / one-subevent / wide-slot profile. Forced 1M is therefore not the root cause.

Long-Interval / Two-Subevent Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_2_subevents/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=2,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 10
  • PAwR config written: 10
  • #DIAG_ADV_SET_OK: 69
  • #DIAG_ADV_RESPONSE: 5
  • Disconnected, reason: 10
  • Maximum number of syncs onboarded: 1

Configured subevent/slot pairs:

  • Subevent 0, slots 0 through 4: configured once each, no AP-side responses observed.
  • Subevent 1, slots 0 through 4: configured once each, one AP-side response observed for each slot.

Interpretation: this is a partial recovery compared with the one-subevent failing profile. It shows that adding a second subevent can restore responses, but only for subevent 1 in this run. The next question is therefore not only num_subevents=1 versus greater than one, but also whether the first subevent/phase in a long-interval train is treated differently by the controller path after PAST.

Long-Interval / Two-Subevent / Repeated Subevent-0 Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_2_subevents_subevent0/ttyACM0.log

Profile printed by the AP:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=2,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 10
  • PAwR config written: 10
  • #DIAG_ADV_SET_OK: 68
  • #DIAG_ADV_RESPONSE: 0
  • Disconnected, reason: 10
  • Maximum number of syncs onboarded: 1

Configured subevent/slot pairs:

  • Subevent 0, slots 0 through 4: configured twice each.
  • No AP-side responses were observed.

Interpretation: subevent 0 remained silent even when repeatedly configured in the two-subevent long-interval profile. Combined with the prior two-subevent alternating run, where only subevent 1 produced responses, this points at subevent index/phase as a real discriminator.

Long-Interval / Two-Subevent / Repeated Subevent-1 Comparison

Capture artifact:

  • ../logs/minimal_pawr_past/20260511_long_interval_2_subevents_subevent1/ttyACM0.log

AP profile used for this build:

#DIAG_ADV_PROFILE:sid=8,interval=1408,num_subevents=2,subevent_interval=48,rsp_delay=5,rsp_spacing=80,rsp_slots=5,ext_adv_interval=160,phy=1M

Marker counts:

  • PAST sent: 8
  • PAwR config written: 8
  • #DIAG_ADV_SET_OK: 68
  • #DIAG_ADV_RESPONSE: 8
  • Disconnected, reason: 8
  • Maximum number of syncs onboarded: 1

Configured subevent/slot pairs:

  • Subevent 1, slots 2, 3, 4, 0, 1, 2, 3, 4.
  • Every configured PAST/config cycle produced an AP-side response.

Observed response pairs:

  • Subevent 1, slot 0: one response.
  • Subevent 1, slot 1: one response.
  • Subevent 1, slots 2 through 4: two responses each.

Interpretation: subevent 1 remained responsive when repeatedly configured in the same two-subevent long-interval profile where repeated subevent 0 produced no responses. This confirms the positive side of the subevent-index split and makes a random alternating-run artifact unlikely.

One-Subevent Interval Sweep

After the long-interval and subevent-index split, the one-subevent diagnostic was swept downward with the wide-slot timing. Each run used SID 8, one subevent, subevent interval 48, response slot delay 5, response slot spacing 80, response slots 5, extended advertising interval 160, and forced LE 1M.

Interval Artifact PAST sent #DIAG_ADV_SET_OK #DIAG_ADV_RESPONSE Result
288 ../logs/minimal_pawr_past/20260511_interval_0288_one_subevent/ttyACM0.log 5 223 9 pass
296 ../logs/minimal_pawr_past/20260511_interval_0296_one_subevent/ttyACM0.log 5 268 9 pass
300 ../logs/minimal_pawr_past/20260511_interval_0300_one_subevent/ttyACM0.log 5 263 4 pass, weaker
302 ../logs/minimal_pawr_past/20260511_interval_0302_one_subevent/ttyACM0.log 5 262 5 pass, weaker
303 ../logs/minimal_pawr_past/20260511_interval_0303_one_subevent/ttyACM0.log 4 201 0 fail
303 retry ../logs/minimal_pawr_past/20260511_interval_0303_one_subevent_retry/ttyACM0.log 2 262 0 fail
304 ../logs/minimal_pawr_past/20260511_interval_0304_one_subevent/ttyACM0.log 5 261 0 fail
320 ../logs/minimal_pawr_past/20260511_interval_0320_one_subevent/ttyACM0.log 5 193 0 fail
384 ../logs/minimal_pawr_past/20260511_interval_0384_one_subevent/ttyACM0.log 5 206 0 fail
512 ../logs/minimal_pawr_past/20260511_interval_0512_one_subevent/ttyACM0.log 5 155 0 fail
768 ../logs/minimal_pawr_past/20260511_interval_0768_one_subevent/ttyACM0.log 5 104 0 fail

Interpretation: the one-subevent diagnostic has a sharp response boundary around 302/303 or 303/304 in this setup. Interval 288 was selected as a conservative diagnostic/release-candidate value because it is below the cliff and still leaves margin from the weak 300/302 results.

Current Narrowing

The evidence now has four tiers:

  • Stock Zephyr sample profile: works and sustains responses.
  • Zephyr-derived sample with ESL-like profile: fails with only one response across eight PAST/config cycles.
  • Zephyr-derived sample with long interval and one subevent but wider stock-like slots: fails with zero responses across five PAST/config cycles.
  • Zephyr-derived sample with long interval and one subevent but no repeated re-onboarding: fails with zero responses after one PAST/config cycle while subevent data continues to be set.
  • Zephyr-derived sample with stock interval and one subevent: works and sustains responses.
  • Zephyr-derived sample with long interval and stock-style five subevents: produces repeated AP-side responses.
  • Zephyr-derived sample with long interval, one subevent, wide slots, and 2M secondary: fails with zero responses across five PAST/config cycles.
  • Zephyr-derived sample with long interval and two subevents: produces responses only for subevent 1, not subevent 0.
  • Zephyr-derived sample with long interval and two subevents while repeatedly configuring subevent 0: fails with zero responses.
  • Zephyr-derived sample with long interval and two subevents while repeatedly configuring subevent 1: produces responses for every configured PAST/config cycle.
  • Zephyr-derived one-subevent interval sweep: intervals 288, 296, 300, and 302 produce responses; interval 303 and above produce zero responses in the captured runs.

Best current hypothesis: the failing boundary is a controller/host interaction around PAwR + PAST when using a small subevent set, especially the first/only response-capable subevent or subevent phase, with a threshold emerging in the one-subevent interval sweep near 303/304. It is not explained by production ESL association, encrypted ESL payload parsing, application-level subevent data staging, one-subevent PAwR by itself, long interval by itself, repeated re-onboarding by itself, forced 1M, or tight response-slot timing by itself.

Next Parameter Splits

The next minimal test matrix should change one group at a time from the passing stock sample:

  1. Repeat the 302/303/304 threshold on a newer controller stack if practical.
  2. Add a SyncInfo-following sniffer mode to predict event channel/time and determine whether the AP periodic train stays schedule-correct after PAST.
  3. Test whether assigning product tags away from subevent 0 changes sustained post-ACL behavior.

The most DevZone-useful request can now include the stock positive control, the adapted one-subevent negative reproducer, the single-sync negative result, the paired two-subevent split where subevent 0 is silent while subevent 1 responds, and the interval sweep showing a sharp boundary near 303/304.