Skip to content

platform: back the SE poll cadence with the secure SysTick, not a cyle busy-loop - #19

Merged
0xEthamin merged 1 commit into
mainfrom
feat/systick-timer
Jul 11, 2026
Merged

platform: back the SE poll cadence with the secure SysTick, not a cyle busy-loop#19
0xEthamin merged 1 commit into
mainfrom
feat/systick-timer

Conversation

@0xEthamin

Copy link
Copy Markdown
Member

The TROPIC01 L1 poll cadence ran on a Cortex-M cycle busy-loop (mcu-spi CycleWait over mcu_arch::delay). That loop violated the SeWait contract: the per-iteration cost of the subs/bne countdown is cited by no primary source, so delay_ms(25) actually waited 25 to 50 ms, a 1x to 2x unknown. Its rate constant CYCLES_PER_MS = 4000 was a hand-mirror of the core clock buried in a bring-up module, so raising HCLK without editing it would have shortened every delay 40x, an invisible SE ChipBusy on silicon.

Replace it with the secure SysTick polled with TICKINT = 0, behind platform's RegisterBus seam so the reload arithmetic and the poll loop are fully host-testable. Registers, bit positions and the reload rule are all pinned to PM0264 sec 4.4 / Table 83-86 and RM0456 sec 22.2:

  • SYST_CSR/RVR/CVR at the secure PPB view (0xE000_E010/14/18), COUNTFLAG read once per iteration (a second read clears it), CLKSOURCE = 1 to clock from HCLK with no RCC step, TICKINT = 0 so no exception is armed.
  • RELOAD = N - 1, and the programmed period is floored at 2 ticks so RVR is never 0 (RELOAD = 0 is outside the valid range 0x1..0x00FF_FFFF and would hang the poll forever on silicon).

HCLK becomes one source of truth: new platform::HCLK_HZ (4 MHz, the MSIS reset default, RCC never programmed). CYCLES_PER_MS is gone. The future RCC ramp moves only HCLK_HZ.

Dead-code cascade removed with its object: CycleWait, delay_cycles, mcu_arch::delay, delay_iterations, the arm asm block, the host stub, their tests, and the asm-gate delay-countdown check plus has_countdown_loop. start_nonsecure gains #[inline(never)] so the disassembly-gate anchor is robust. The gate keeps the cpsid/cpsie mask pair and the dsb -> isb -> bxns handoff checks.

Security: the driver uses only the secure SysTick instance. It is banked in the PPB outside SAU and GTZC, so the non-secure world cannot reach or disturb it, and AIRCR.PRIS stays neutral with no exception armed.

…le busy-loop

The TROPIC01 L1 poll cadence ran on a Cortex-M cycle busy-loop (mcu-spi
CycleWait over mcu_arch::delay). That loop violated the SeWait contract: the
per-iteration cost of the subs/bne countdown is cited by no primary source, so
delay_ms(25) actually waited 25 to 50 ms, a 1x to 2x unknown. Its rate constant
CYCLES_PER_MS = 4000 was a hand-mirror of the core clock buried in a bring-up
module, so raising HCLK without editing it would have shortened every delay 40x,
an invisible SE ChipBusy on silicon.

Replace it with the secure SysTick polled with TICKINT = 0, behind platform's
RegisterBus seam so the reload arithmetic and the poll loop are fully
host-testable. Registers, bit positions and the reload rule are all pinned to
PM0264 sec 4.4 / Table 83-86 and RM0456 sec 22.2:
  - SYST_CSR/RVR/CVR at the secure PPB view (0xE000_E010/14/18), COUNTFLAG read
    once per iteration (a second read clears it), CLKSOURCE = 1 to clock from
    HCLK with no RCC step, TICKINT = 0 so no exception is armed.
  - RELOAD = N - 1, and the programmed period is floored at 2 ticks so RVR is
    never 0 (RELOAD = 0 is outside the valid range 0x1..0x00FF_FFFF and would
    hang the poll forever on silicon).

HCLK becomes one source of truth: new platform::HCLK_HZ (4 MHz, the MSIS reset
default, RCC never programmed). CYCLES_PER_MS is gone. The future RCC ramp moves
only HCLK_HZ.

Dead-code cascade removed with its object: CycleWait, delay_cycles,
mcu_arch::delay, delay_iterations, the arm asm block, the host stub, their tests,
and the asm-gate delay-countdown check plus has_countdown_loop. start_nonsecure
gains #[inline(never)] so the disassembly-gate anchor is robust. The gate keeps
the cpsid/cpsie mask pair and the dsb -> isb -> bxns handoff checks.

Security: the driver uses only the secure SysTick instance. It is banked in the
PPB outside SAU and GTZC, so the non-secure world cannot reach or disturb it, and
AIRCR.PRIS stays neutral with no exception armed.
@0xEthamin
0xEthamin merged commit b894c21 into main Jul 11, 2026
13 checks passed
@0xEthamin
0xEthamin deleted the feat/systick-timer branch July 11, 2026 14:37
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.

1 participant