Skip to content

drivers/touch/cst816: reset chip after prolonged idle#5

Open
gmarull wants to merge 2088 commits into
mainfrom
touch/cst816-idle-watchdog
Open

drivers/touch/cst816: reset chip after prolonged idle#5
gmarull wants to merge 2088 commits into
mainfrom
touch/cst816-idle-watchdog

Conversation

@gmarull

@gmarull gmarull commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

Workaround for the CST816 touch controller occasionally wedging and ceasing to assert its INT line, which leaves touch unresponsive until the next power cycle.

Adds an idle watchdog: while touch is enabled, a once-a-minute regular_timer checks the time since the last interrupt and, after 10 minutes of inactivity, hard-resets the chip (existing cst816_hw_reset()) and re-arms the EXTI.

Details

  • s_last_activity_ms is updated on every processed interrupt (any EXTI fire = chip alive).
  • The periodic check runs on the regular-timer (NewTimers) task and stays cheap — it only schedules the reset.
  • The actual reset is offloaded to the system task because cst816_hw_reset() sleeps ~120 ms and must not block the regular-timer task.
  • The watchdog timer is started/stopped together with touch_sensor_set_enabled().

Notes / open questions

  • The 10-minute timeout is a starting point; tune against real telemetry if available.
  • "Activity" is defined as any interrupt (proves the INT line works). If the observed failure is "INT stuck asserted", keying off finger up/down transitions instead would be more robust.
  • Constants are hardcoded; can add a Kconfig knob if desired.

🤖 Generated with Claude Code

jplexer and others added 30 commits May 21, 2026 17:07
The ANCS alive-check fires every 15 minutes; if iOS doesn't respond
within 5 seconds, prv_is_ancs_alive_response_timeout_launcher_task_cb
attempts to recover by re-subscribing to the ANCS characteristics. The
timer is only re-armed on the success path, via ancs_handle_subscribe()
when the Data characteristic's CCCD response arrives without error.

If anything in that recovery path fails -- characteristics already
invalidated, gatt_client_subscriptions_subscribe() returns non-OK
synchronously, or iOS never sends a CCCD response -- the alive-check
timer stays stopped permanently. The watch then appears connected
but silently drops every notification until reboot, which is the
symptom in this bug and the related FIRM-1692 / FIRM-951 reports.

Always re-schedule the next alive check at the end of the timeout
handler. On the happy path ancs_handle_subscribe() will cancel and
reschedule via prv_ancs_is_alive_start_tracking(); on the failure
paths we still tick again in 15 minutes and get another shot at
recovery instead of dying silently.

Fixes FIRM-1936

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
If some path leaks s_user_controlled_state set to true (e.g. a voice
window that disappears before its exit handler resets the light), the
backlight ends up pinned in LIGHT_STATE_ON: button release skips the
auto-off timer transition because the flag is honored, and the only
ways out are light_enable(false), light_reset_user_controlled(), or a
reboot.

Users hit this by toggling the backlight setting off and back on, which
is exactly the workaround the FIRM-1874 reporter described. But
light_toggle_enabled() only drives the state machine
(LIGHT_STATE_OFF -> LIGHT_STATE_ON_TIMED) and never clears
s_user_controlled_state, so the flag survives the round-trip and the
next button release still skips the fade-out timer. The user thinks
they fixed it because the light went off, but the underlying state is
still wrong.

Clear s_user_controlled_state at the top of light_toggle_enabled() and
light_toggle_ambient_sensor_enabled() so the user's escape hatch
actually restores normal behavior. This is defense-in-depth: it does
not address whatever upstream path leaked the flag, but it guarantees
that the documented recovery procedure works.

Fixes FIRM-1874

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
prv_mic_window_appear() pins the backlight via
sys_light_enable_respect_settings(true) for the duration of the
dictation session. The light is released by prv_exit_and_send_result_event()
(back button, errors, success), the StateTransitionToText branch,
and voice_window_pop() (external pop / destroy). prv_mic_window_disappear()
itself, however, only calls prv_cancel_dictation() and leaves the
backlight held on, even though the window is no longer visible.

In normal flows a later exit path runs and resets the light, so this
is harmless. The hole is that disappear can fire on its own when the
mic window is interrupted (modal preempt, voice_window_lose_focus,
StateError) and the owning context goes away without a subsequent
voice_window_pop -- the light stays pinned until something else
clears s_user_controlled_state.

Call sys_light_reset_to_timed_mode() at the top of the disappear
handler so the appear/disappear pair is symmetric. If a later
exit path also resets the light, that's a no-op; if no later path
runs, the backlight no longer leaks.

Fixes FIRM-1874

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
prv_handle_timezone_set() ran a one-shot "pivot RTC from localtime to
UTC" block whenever clock_is_timezone_set() was false. That migration
was meant for the era when classic Pebbles stored wall-clock localtime
in the RTC; modern firmware always stores UTC, and on Asterix/Obelix
the RTC has never held anything else.

The pivot re-arms on every dead-battery boot, because retained RAM is
wiped and rtc_is_timezone_set() goes back to returning false. When a
subsequent timezone-only update comes in (e.g.
clock_set_timezone_by_region_id() triggered by the BlobDB watch-prefs
sync of timezoneSource shortly after reconnect), there is no UTC time
in the same call to overwrite the pivot's result, so it adds the
timezone offset (+7h for PDT) to an already-correct UTC value and
leaves the RTC permanently shifted.

Drop the pivot. The migration has been a no-op on every supported
platform for years, and removing it eliminates the double-offset path.

Fixes FIRM-2000

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
It looks like Claude loves to write lots of text to often explain simple
changes. Ask agents to use Git history for that, instead of comments in
the code.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Commit 499b9e1 made the status bar clock bold across the whole UI by
keying off StatusBarLayerModeClock. Add an opt-in style preference
that only affects the notification window so the rest of the UI goes
back to the regular weight default.

Modeled as an enum (Default / Bold) so an upcoming larger-status-bar
mode can slot in without another schema bump. The notification window
flips its status bar to a new StatusBarLayerModeClockBold when the
pref selects Bold; everywhere else keeps the existing Clock mode and
renders non-bold. The mode-checking call sites accept either clock
mode via a small helper.

Settings -> Notifications gains a "Status Bar" row that opens a
submenu mirroring the Banner Style pattern.

Test goldens touched by 499b9e1 are restored to their pre-bold
versions since none of them go through the bold path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Shashvat Prabhu <shashvatprabhu2006@gmail.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
The periodic flush iterated all sessions under s_list_mutex on
KernelBG. Each session's comm_session_send_buffer_begin_write can
stall up to 500 ms, so once DLS_MAX_NUM_SESSIONS slots fill up the
worst case is ~10 s -- well past the KernelBG watchdog threshold.
Because sessions persist across reboots, hitting this once puts the
device in an unrecoverable boot loop until a factory reset clears
flash.

Snapshot the session list under the mutex, then chain one send per
system task callback (mirroring prv_reopen_next_session_system_task_cb)
so KernelBG yields between sends and the watchdog gets fed.

Fixes FIRM-1860

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
prv_refill_bg (system task) and the public speaker_service APIs
(KernelMain / app threads) had no synchronization. The observed
fallout was a PBL_ASSERTN in stop_mode_enable: two callers of
prv_stop_internal both passed the state==Idle guard before either
cleared state, so audec_stop()->stop_mode_enable(InhibitorAudio) ran
twice and underflowed s_num_items_disallowing_stop_mode. The same
race also lets a stop on one thread interleave with a play on
another — both touching the AUDCODEC HAL, DMA buffers and
pcm_stream lifecycle.

Add s_lock (PebbleMutex *) and take it on every public entry point
that mutates state or audio HW, plus prv_refill_bg's system-task
callback. prv_refill_bg becomes a lock-take wrapper around
prv_refill_locked; the priming callers (play_note_seq / play_tone /
play_tracks) already hold the lock and call prv_refill_locked
directly. Keep state-first ordering inside prv_stop_internal so it
stays idempotent if called twice.

Trivial single-word getters (get_state, is_muted, set_owner_task)
are left unlocked.

No ISR enters speaker_service.c directly (DMA ISR posts via
system_task_add_callback_from_isr), so a plain PebbleMutex matches
the pattern used by voice.c.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
…e is not Started

The idempotency guard in bt_driver_start() short-circuited whenever
ble_hs_is_enabled() reported true, regardless of our own driver state,
and returned without running ble_hs_util_ensure_addr(0). After a prior
ble_hs_stop (e.g. an err-path stop) had run ble_hs_id_reset(), the
identity addresses were left empty, and the next call to
bt_driver_id_copy_local_identity_address from bt_local_id_configure_driver
tripped PBL_ASSERTN(rc == 0) on the return value of ble_hs_id_infer_auto.

Split the guard: keep the no-op only when our driver state already says
Started. If NimBLE thinks the host is on but our state disagrees, drive
a clean stop and fall into the fresh-start path so ble_hs_util_ensure_addr
runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
The caller-id text layer's frame was pinned to the style's static
caller_id_height (60px), while only its bounds grew to fit the chosen
font. At PreferredContentSizeLarge the title font (GOTHIC_28_BOLD) plus
the forced second line needed ~66px, so the layer's frame clipped the
bottom of the rendered phone number.

Set the frame height alongside the bounds so it scales with the font
instead of relying on a per-style magic number. The frame never shrinks
below the style's caller_id_height, preserving the existing single-line
top margin.

Fixes FIRM-1944

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
The ANCS alive-check fires a Control Point write every 15 minutes and
treats iOS' reply as proof the watch is still receiving notifications.
That probe only verifies the CP path. iOS can wedge in a state where it
keeps responding to CP requests but its Notification Source push has
been silently dropped (commonly after airplane-mode toggles and timezone
swings during travel), so the watch reports itself healthy while no
notifications arrive. Re-opening the iOS Pebble app is currently the
only way to recover, which is what the FIRM-1692 reporter had to do
after a 7-day silent outage.

Track how many consecutive alive-check intervals pass without any NS
traffic. After ANCS_NO_NS_TIMEOUT_HOURS (6 h, derived from the
alive-check interval so the two don't desync) we force a CCCD
re-subscribe to nudge iOS into pushing again, skip the CP probe that
round to avoid interleaving with the CCCD writes, and schedule the
next alive check as a backup in case the CCCD response never lands.
Any NS event (add/modify/remove) resets the counter, so users with
normal notification volume never see the refresh fire; users with
genuinely quiet phones absorb at most one harmless CCCD rewrite per
6 h window.

Fixes FIRM-1692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Add a 32-entry ring buffer (s_lcdc_irq_log) to record LCDC IRQs with
timestamp, IRQ before/after, JDI_PAR_CTRL, STATUS and per-interrupt
flags.
Register the buffer as the Memfault extra region "lcdc_irq_log" so it
appears in coredumps. Mark EOF completions via s_lcdc_eof_cb_fired in
the
HAL callback so the logger can detect interrupts that saw EOF but never
hit the completion path.

Add tools/extract_irq_log.py to decode the ring buffer from a firmware
ELF and core file and highlight lost-EOF interrupts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
…p resets

The AW2016 LED driver on Obelix can spontaneously reset (PUIS=1) when
VBAT briefly dips below 1.25V or its I2C watchdog trips on SCL held low
>130ms. After such a reset the chip comes up with CHIPEN=0 and all
registers cleared, but there's no INT line wired back to the MCU so the
firmware has no way to notice.

Today the AW2016 driver only writes GCR1 CHIPEN_EN + LCTR/LCFG on the
0->nonzero brightness transition. Once it's cached s_brightness>0,
subsequent writes only touch PWM registers, which silently do nothing
while CHIPEN=0.

Expose a new backlight_refresh() driver entry point that re-applies the
chip-enable, configures the LED registers, and re-emits the current
color. On AW2016 it's a real recovery path; on the PWM, AW9364E, QEMU,
and stub backends it's a harmless no-op since those drivers can't desync
from cached state in the same way.

Signed-off-by: Joshua Jun <joshuajun@proton.me>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
The light-service state machine short-circuits in prv_change_state when
the target brightness matches the cached value, so a tap or wrist-flick
arriving while we're already in ON_TIMED never reaches the backlight
driver. That's normally fine, but on AW2016-equipped boards (Obelix) the
chip can silently reset on a VBAT dip or I2C watchdog with no signal
back to firmware, leaving the chip stuck off while we still believe the
light is on. The user then sees the backlight fail to respond to taps,
and each new tap just re-arms the fade-out timer -- extending the
outage from a single fade cycle (~3-5s) to multiple minutes if they
keep trying.

Call backlight_refresh() on the no-brightness-change branch when the
target state is ON or ON_TIMED. backlight_refresh() is a no-op on
drivers that can't desync, and on AW2016 it re-enables the chip and
re-applies the configured color, so user-initiated wake actions always
heal a previously-reset chip.

Fixes FIRM-1929

Signed-off-by: Joshua Jun <joshuajun@proton.me>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Mearman and others added 27 commits June 12, 2026 12:41
test_pow compared pblibc_pow against the host libm at runtime: it
defined pow_theirs() before the pblibc_private.h rename so it called the
host pow, then compared pblibc_pow within 1 ulp. glibc and Apple's libm
disagree in the last ulp, so the expected values were host-specific.

Precompute correctly-rounded reference values off-host instead.
gen_pow_reference.py evaluates pow(2, v) as exp(v * ln 2) in the stdlib
decimal module at 80 significant digits and rounds to the nearest double
(round-half-to-even), for v = i * 0.001, i in [0, 10000), matching the
inputs the test exercises. It emits input and expected IEEE-754 bit
patterns into pow_reference.h so no decimal round-trip loss occurs. The
table is identical on every host and the script is checked in so it is
regenerable.

The test now compares pblibc_pow against the table within 1 ulp.
pow.c (newlib) documents its result as "nearly rounded"; measured
against the correctly-rounded reference it is within 1 ulp, so 1 ulp is
the justified tolerance, not an invented one. The host libm is no longer
called.

Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
test_log compared pblibc_log against the host libm at runtime: it
defined log_theirs() before the pblibc_private.h rename so it called the
host log, then compared pblibc_log within 1 ulp. glibc and Apple's libm
disagree in the last ulp, so the expected values were host-specific.

Precompute correctly-rounded reference values off-host instead.
gen_log_reference.py evaluates log(v) in the stdlib decimal module at 80
significant digits and rounds to the nearest double (round-half-to-even),
for v = i * 0.001, i in [1, 10000), matching the inputs the test
exercises. It emits input and expected IEEE-754 bit patterns into
log_reference.h so no decimal round-trip loss occurs. The table is
identical on every host and the script is checked in so it is
regenerable.

The test now compares pblibc_log against the table within 1 ulp.
log.c (newlib) documents its error as always less than 1 ulp relative to
the true value, so 1 ulp against the correctly-rounded reference is the
justified tolerance, not an invented one. The host libm is no longer
called.

Also rename the fixture from test_pow__initialize to
test_log__initialize so clar actually runs it for this suite; the old
name meant the rounding-mode setup never fired here.

Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Batch-migrate every service and driver area that logs and has its own
Kconfig (~70 areas) to the per-module logging macros: each area gains
a log level Kconfig choice sourced from Kconfig.template.log_level,
logs carry the module name and verbosity can be tuned per module.

Naming conventions:

- Services use service_<name> with module = SERVICE_<NAME>, matching
  the existing gating symbol (the merged activity module is renamed
  accordingly). PBL_LOG_MODULE_DEFINE goes in the main unit,
  PBL_LOG_MODULE_DECLARE in the remaining units.
- Drivers use driver_<category>_<model> per concrete driver (e.g.
  driver_ambient_opt3001, driver_mic_nrf5) with module =
  DRIVER_<CATEGORY>, each defining its own module while sharing the
  area-wide log level. Common units use the plain area name
  (driver_vibe, driver_i2c, driver_flash). The merged lis2dw12 module
  is renamed to driver_accel_lis2dw12, and the remaining IMU drivers
  join as driver_accel_lsm6dso and driver_mag_mmc5603nj under
  CONFIG_DRIVER_IMU_LOG_LEVEL.

Verified on asterix, obelix_dvt, getafix_dvt2 and all QEMU boards;
unit tests pass. The PRF variant link failure is pre-existing on main
and unrelated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Replace the LOG_DOMAIN_TOUCH-gated TOUCH_DEBUG macro with plain PBL_LOG
level macros. The on/off domain flag is subsumed by the service_touch
module level. Position updates log at verbose level since they fire
continuously while a finger is down.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Replace the LOG_DOMAIN_VOICE-gated wrappers with plain PBL_LOG level
macros; the voice service files are gated by the service_voice module
level. Messages with ERROR:/WARNING: text prefixes move to the proper
error/warning levels and per-frame encoder logs move to verbose.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Replace the LOG_DOMAIN_ACCEL-gated wrapper with plain PBL_LOG macros.
Per-sample and per-batch logs move to verbose level, matching the
previous off-by-default behavior while remaining selectable through
the module log levels. The qemu accel driver adopts the imu module,
and the prev_timestamp_ms bookkeeping in AccelServiceState becomes
unconditional (the compiler drops the dead computation when verbose
logging is compiled out).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Replace the LOG_DOMAIN_QEMU_COMM-gated wrappers with plain PBL_LOG
macros. Packet parsing and send-path logs (including the outgoing data
hexdump) move to verbose level to match the previous off-by-default
behavior; host event messages log at debug. QEMU_LOG_ERROR was unused.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Replace the ble_log.h wrapper macros with plain PBL_LOG level macros,
level for level (LOG_DOMAIN_BT was always on, so behavior at the
default level is unchanged). The files with converted call sites
declare the bt log module so they are now gated by CONFIG_BT_LOG_LEVEL
alongside the nimble backend. Files that only included ble_log.h for
its transitive includes now include system/logging.h directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
LOG_DOMAIN_BT, LOG_DOMAIN_ACCEL, LOG_DOMAIN_VOICE, LOG_DOMAIN_TOUCH and
LOG_DOMAIN_QEMU_COMM have no users left after the wrapper macro
removals; the per-module log levels replace them. The LOG_DOMAIN_ALL
block only covered LOG_DOMAIN_BT, so it goes too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Now that debug chatter is controllable per module, default builds log
at info level; debug/verbose logging is opt-in via the per-module
Kconfig log level options or DEFAULT_LOG_LEVEL_DEBUG.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
gap_le_advert_workaround.h existed to assist with a bug in the TI
Bluetooth chips, which are no longer supported. The three getters it
declared have had no callers since the original import, so remove the
header and their definitions.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
clang_multi bundles an i686 multilib sysroot (for -m32 unit-test
builds), and nixpkgs throws when evaluating the i686 package set on
non-x86 hosts, so the aarch64-linux dev shell never evaluated. Use
clang_multi only on x86_64 and fall back to plain clang on other
Linux systems; -m32 builds are not possible there anyway.

The x86_64-linux and aarch64-darwin shell derivations are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Replace the drivers/hal/*.c glob with per-module HAL_SIFLI_* Kconfig
options, mirroring Zephyr's modules/hal_sifli/Kconfig. Granularity is
purely at the source-list level: the SDK conf header keeps every
HAL_x_MODULE_ENABLED macro defined, so no SDK changes are needed.

The always-built core is bf0_hal, adc, cortex, dma, efuse, hlp, pmu,
rcc and bf0_sys_cfg: HAL_Init() calls HAL_ADC_HwInit() which in turn
needs DMA, PMU pulls BSP_CONFIG_get() from bf0_sys_cfg.c, and HLP
provides the backup registers and HAL_DBG_printf used by core code.

Intra-HAL dependencies are encoded as selects (AON->RTC, GPIO->AON,
LRC_CAL->LCPU_CONFIG/MAILBOX, IPC_QUEUE->MAILBOX). Consumers select
what they use: the SF32LB52 drivers select their HAL modules, NimBLE
selects IPC_QUEUE and the new LCPU boot support on SF32LB52, and
HAL_SIFLI_SF32LB52 selects the modules required by unconditional
SoC/kernel/system code (AON, GPT, IPC_QUEUE, LPTIM, LRC_CAL, MPI,
PINMUX, RTC).

Verified on obelix_pvt that the set of hal_sifli objects pulled into
the link is identical before and after; getafix_dvt2, obelix PRF and
asterix also build. hal_sifli compiles drop from 74 to 41 TUs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Fixes FIRM-2450
Fixes FIRM-2507

Signed-off-by: Joshua Jun <lets@throw.rocks>
Signed-off-by: Joshua Jun <lets@throw.rocks>
Fixes FIRM-2475

Signed-off-by: Joshua Jun <lets@throw.rocks>
The service-changed path was an empty stub at both layers. The service layer
now sends an indication when the GATT database changes, and the NimBLE driver
emits it over the Service Changed characteristic (0x1801/0x2a05) via
ble_gatts_indicate_custom with the affected handle range.

Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…akes

Port the test off the deleted SS1 fakes onto fake_bt_driver_gatt, which records
the indications the driver emits, and take it out of BROKEN_TESTS.

Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Use PBL_LOG_MODULE_DECLARE / PBL_LOG_ERR matching the pattern in
gatt_client_operations.c and other bluetooth-fw files. LOG_DOMAIN_BT
was removed from logging.h in 5483b6d; the new per-module logging
doesn't need a domain argument.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Change the driver signature from (connection_id, range) to (device,
range) so the NimBLE implementation resolves the connection handle
through its own connection table (ble_gap_conn_find_by_addr) instead
of reaching back into fw/comm/ble under bt_lock.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Joseph Mearman <joseph@mearman.co.uk>
Expose the LIS2DW12 tuning parameters (wake duration/threshold, scale,
FIFO threshold, ADDR pull-up) as Kconfig options instead of board struct
fields. The driver now reads the CONFIG_* values directly, dropping the
corresponding fields from LIS2DW12Config.

Kconfig defaults follow the chip power-on-reset values; each board sets
the values it needs in its defconfig, preserving current behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Populate the --board option choices from the boards directory.

This lets new board definitions become available without editing wscript.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Fold board-specific revision targets into shared board directories.

Use per-revision Kconfig and defconfig overlays for board differences.

Update CI to configure BOARD@REVISION targets while preserving

underscore-based artifact names.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Move device-runner selection into the board manifests and restructure the
runners as a self-contained package modeled on Zephyr's west binary runners.

- Boards declare their supported runners in <board>.yml; the first is the
  default. Drop the hardcoded RUNNERS map and the configure-time --runner.
- New tools/runners package with RunnerCaps/RunnerConfig and a
  capabilities()/do_add_parser()/create()/run()->do_run() dispatch. Runners
  shell out directly, so waftools/{openocd,sftool,nrfutil}.py are removed.
- Runners own their CLI args (e.g. --tty for sftool) via do_add_parser();
  --resources stays a native flash option and the runner fails if it cannot
  program resources.
- OpenOCD configuration lives in the board: boards/asterix/support/openocd.cfg
  (cmsis-dap baked in). Drop the generated openocd.cfg, the template, the JTAG
  fragments and --openocd-jtag.
- Add native ./waf flash/run/debug commands that dispatch through the runner,
  alongside the existing ./pbl commands; both share the runner package.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gmarull gmarull force-pushed the touch/cst816-idle-watchdog branch from c399528 to 766311f Compare June 15, 2026 17:49
The CST816 occasionally wedges and stops asserting its INT line, leaving
touch unresponsive until the next power cycle. Add an idle watchdog: while
touch is enabled, a regular timer periodically checks whether any interrupt
has been seen since the previous check and, if not, hard-resets the chip and
re-arms the EXTI.

The reset is offloaded to the system task because cst816_hw_reset() sleeps
~120ms and must not block the regular-timer task.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gmarull gmarull force-pushed the touch/cst816-idle-watchdog branch from 766311f to 9e76b7f Compare June 15, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.