ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_systick.h File Reference

Cortex-M85 SysTick + DWT cycle-counter timebase primitive. More...

#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_systick.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ra8_systick_limit_t : uint32_t { k_ra8_systick_rvr_max = 0x00FFFFFFUL }
 Architectural range limit of the Cortex-M SysTick reload register. More...
enum  ra8_systick_clock_source_t : uint8_t {
  k_ra8_systick_clk_external = 0U ,
  k_ra8_systick_clk_cpu = 1U
}
 Selects the SysTick counter clock (SYST_CSR.CLKSOURCE). More...

Functions

ra8_err_t ra8_systick_reload_for (uint32_t cpu_hz, uint32_t tick_hz, uint32_t *out_reload)
 Compute the SysTick reload for a given core clock and tick rate.
ra8_err_t ra8_systick_configure (uint32_t reload, ra8_systick_clock_source_t src, bool tick_irq)
 Arm and start SysTick with a reload value and clock source.
ra8_err_t ra8_systick_set_reload (uint32_t reload)
 Re-arm SysTick with a new reload, leaving the control bits untouched.
uint32_t ra8_systick_current_value (void)
 Read the live SysTick current-value register (SYST_CVR).
void ra8_dwt_cyccnt_enable (void)
 Enable the DWT free-running cycle counter (DWT_CYCCNT).
void ra8_dwt_cyccnt_reset (void)
 Zero the DWT cycle counter (DWT_CYCCNT).
uint32_t ra8_dwt_cyccnt_read (void)
 Sample the DWT cycle counter (DWT_CYCCNT).

Detailed Description

Cortex-M85 SysTick + DWT cycle-counter timebase primitive.

A single hardware primitive for the two architectural timekeeping blocks the RA8D2's Cortex-M85 exposes in its System Control Space (PPB window 0xE000Exxx), so no caller has to own a private address-cast accessor:

These are Arm v8-M architectural registers, NOT RA8D2 peripherals, so they carry references to the Arm v8-M Architecture Reference Manual (the "Arm v8-M ARM") rather than the RA8D2 Hardware User's Manual. On a host build (RA8_OFF_TARGET) the SCS window is backed by the fake MMIO map, so every access here is observable to unit tests and the reload / range logic is exercised exactly as on silicon.

Note
This primitive owns register access only; it does NOT own the tick counter, the SysTick IRQ body, or any wall-clock policy. The millisecond tick counter (ra8_time_ms / ra8_delay_ms) and the ThreadX kernel-tick retune are the consumers that layer that policy on top of these accesses.
Lives in ra8_core (a core SCB/timebase block), not ra8_hal, so the Ring-1 ra8_time timebase can consume it without an upward ra8_core -> ra8_hal layering dependency. Higher-ring code (the ThreadX port, apps) includes it by filename just the same.
Since
0.1.0

Definition in file ra8_systick.h.

Enumeration Type Documentation

◆ ra8_systick_clock_source_t

Selects the SysTick counter clock (SYST_CSR.CLKSOURCE).

Arm v8-M ARM: SYST_CSR.CLKSOURCE selects between the processor clock and an implementation-defined external reference clock. On the RA8D2 the processor clock is CPUCLK0, which is what every millisecond timebase in this tree derives its reload against.

Enumerator
k_ra8_systick_clk_external 

CLKSOURCE = 0: external reference clock.

k_ra8_systick_clk_cpu 

CLKSOURCE = 1: processor (CPU) clock.

Definition at line 73 of file ra8_systick.h.

◆ ra8_systick_limit_t

enum ra8_systick_limit_t : uint32_t

Architectural range limit of the Cortex-M SysTick reload register.

Arm v8-M ARM: SYST_RVR.RELOAD is a 24-bit field; the top byte reads as zero. A reload larger than this cannot be represented, so the configure / set-reload / reload-for entry points reject it rather than truncating (which would silently make the tick far too fast).

Enumerator
k_ra8_systick_rvr_max 

Max SYST_RVR reload (24-bit).

Definition at line 61 of file ra8_systick.h.

Function Documentation

◆ ra8_dwt_cyccnt_enable()

void ra8_dwt_cyccnt_enable ( void )

Enable the DWT free-running cycle counter (DWT_CYCCNT).

Sets DEMCR.TRCENA to unlock the DWT unit, then sets DWT_CTRL.CYCCNTENA to start DWT_CYCCNT counting every CPU cycle. Both are read-modify-write so any other trace/debug bits already set are preserved. The counter is PRIMASK-immune: it keeps advancing even while interrupts are globally masked, which is what makes it a usable delay reference in early boot and IRQ-off critical sections.

Precondition
The Cortex-M85 core is running.
The SCS region is accessible.
Postcondition
DEMCR.TRCENA and DWT_CTRL.CYCCNTENA are both set.
DWT_CYCCNT is advancing once per CPU cycle.
Note
Not thread-safe (read-modify-write of two registers); call once at init.
See also
ra8_dwt_cyccnt_read
ra8_dwt_cyccnt_reset
Since
0.1.0

Definition at line 168 of file ra8_systick.c.

References internal_systick_reg(), k_ra8_dwt_ctrl, k_ra8_dwt_ctrl_cyccntena, k_ra8_dwt_demcr, and k_ra8_dwt_demcr_trcena.

Referenced by demo_setup_or_halt(), and ra8_time_init().

◆ ra8_dwt_cyccnt_read()

uint32_t ra8_dwt_cyccnt_read ( void )
nodiscard

Sample the DWT cycle counter (DWT_CYCCNT).

Reads the free-running 32-bit cycle counter. Wraps every 2^32 CPU cycles (~4.3 s at 1 GHz); compare two samples with unsigned subtraction so the elapsed count stays correct across a wrap.

Returns
The current DWT_CYCCNT value.
Return values
0..UINT32_MAXCPU cycles counted since the counter was last zeroed, modulo 2^32.
Precondition
ra8_dwt_cyccnt_enable has been called.
The SCS region is accessible.
Postcondition
No architectural state is modified (pure read).
Successive samples are non-decreasing modulo 2^32.
Note
Thread-safe; single-word read of a volatile register.
See also
ra8_dwt_cyccnt_enable
Since
0.1.0

Definition at line 183 of file ra8_systick.c.

References internal_systick_reg(), and k_ra8_dwt_cyccnt.

Referenced by cam_record_sync_sample(), cam_sync_state_init(), demo_emit_measurement(), and ra8_delay_ms().

◆ ra8_dwt_cyccnt_reset()

void ra8_dwt_cyccnt_reset ( void )

Zero the DWT cycle counter (DWT_CYCCNT).

Writes zero to DWT_CYCCNT so a subsequent ra8_dwt_cyccnt_read measures cycles elapsed from this call. Does not enable or disable the counter; ra8_dwt_cyccnt_enable must already have started it for the reset to matter.

Precondition
ra8_dwt_cyccnt_enable has been called (or the counter is otherwise on).
The SCS region is accessible.
Postcondition
DWT_CYCCNT reads approximately zero (it advances immediately after).
No other DWT or DEMCR bit is modified.
Note
Not thread-safe; intended to bracket a measured region.
See also
ra8_dwt_cyccnt_read
Since
0.1.0

Definition at line 176 of file ra8_systick.c.

References internal_systick_reg(), and k_ra8_dwt_cyccnt.

Referenced by demo_emit_measurement().

◆ ra8_systick_configure()

ra8_err_t ra8_systick_configure ( uint32_t reload,
ra8_systick_clock_source_t src,
bool tick_irq )
nodiscard

Arm and start SysTick with a reload value and clock source.

Performs the full bring-up sequence: disable the counter, program SYST_RVR with reload, clear SYST_CVR so counting restarts from the new reload, then write SYST_CSR to enable the counter with the requested clock source and, optionally, the tick interrupt. This is the exact sequence a millisecond timebase performs once at init.

Parameters
[in]reloadSYST_RVR reload value; must be <= k_ra8_systick_rvr_max.
[in]srcCounter clock source (ra8_systick_clock_source_t).
[in]tick_irqWhen true, enable SYST_CSR.TICKINT so the counter reaching zero raises the SysTick exception; when false, the counter free-runs and callers poll ra8_systick_current_value.
Returns
Error code.
Return values
k_ra8_okSysTick armed and counting.
k_ra8_err_out_of_rangereload exceeds k_ra8_systick_rvr_max.
Precondition
reload was produced by ra8_systick_reload_for or is otherwise known to fit the 24-bit field.
The SCS region is accessible (always true on Cortex-M).
Postcondition
On k_ra8_ok, SYST_RVR holds reload and the counter is enabled.
On any error, no SysTick register is modified.
Note
Not thread-safe; intended for single-threaded init or an IRQ-masked critical section.
See also
ra8_systick_set_reload
ra8_systick_reload_for
Since
0.1.0

Definition at line 122 of file ra8_systick.c.

References internal_systick_reg(), k_ra8_err_out_of_range, k_ra8_ok, k_ra8_systick_clk_cpu, k_ra8_systick_csr, k_ra8_systick_csr_clksource, k_ra8_systick_csr_enable, k_ra8_systick_csr_tickint, k_ra8_systick_cvr, k_ra8_systick_rvr, k_ra8_systick_rvr_max, ra8_log_error, and s_tag.

Referenced by demo_setup_or_halt(), and ra8_time_init().

◆ ra8_systick_current_value()

uint32_t ra8_systick_current_value ( void )
nodiscard

Read the live SysTick current-value register (SYST_CVR).

Returns the counter's current value, which counts down from SYST_RVR to zero and reloads. Reading it never clears it (only a write does), so this is a side-effect-free sample of the running counter.

Returns
The 24-bit SYST_CVR value in the low bits of the result.
Return values
0..k_ra8_systick_rvr_maxCurrent down-counter value.
Precondition
SysTick has been configured and is counting.
The SCS region is accessible.
Postcondition
No architectural state is modified (pure read).
Successive samples move monotonically down until the reload wrap.
Note
Thread-safe; single-word read of a volatile register.
Since
0.1.0

Definition at line 161 of file ra8_systick.c.

References internal_systick_reg(), and k_ra8_systick_cvr.

◆ ra8_systick_reload_for()

ra8_err_t ra8_systick_reload_for ( uint32_t cpu_hz,
uint32_t tick_hz,
uint32_t * out_reload )
nodiscard

Compute the SysTick reload for a given core clock and tick rate.

Derives the SYST_RVR reload value as cpu_hz / tick_hz - 1, the pure arithmetic every SysTick consumer needs. Validates that neither input is zero, that the clock is at least one tick period (cpu_hz >= tick_hz), and that the resulting reload fits the 24-bit SYST_RVR field. No register is touched, so this half is fully deterministic and host-testable on its own.

Parameters
[in]cpu_hzCore (SysTick) clock in Hz.
[in]tick_hzDesired tick rate in Hz (e.g. 1000 for a 1 ms tick).
[out]out_reloadOn success, receives the SYST_RVR reload value.
Returns
Error code.
Return values
k_ra8_okReload computed and written to out_reload.
k_ra8_err_null_ptrout_reload is NULL.
k_ra8_err_invalid_argcpu_hz or tick_hz is zero, or cpu_hz is below one tick period.
k_ra8_err_out_of_rangeThe reload exceeds k_ra8_systick_rvr_max (cpu_hz far too high for tick_hz).
Precondition
out_reload is a valid, writable uint32_t.
tick_hz is the rate the caller will actually program.
Postcondition
On k_ra8_ok, *out_reload <= k_ra8_systick_rvr_max.
On any error, out_reload is left unmodified.
Note
Pure function; trivially thread-safe.
Example:
uint32_t reload = 0U;
// 1 GHz core, 1 kHz tick -> reload = 999999.
(void)ra8_systick_reload_for(1000000000U, 1000U, &reload);
ra8_err_t ra8_systick_reload_for(uint32_t cpu_hz, uint32_t tick_hz, uint32_t *out_reload)
Compute the SysTick reload for a given core clock and tick rate.
Definition ra8_systick.c:92
See also
ra8_systick_configure
ra8_systick_set_reload
Since
0.1.0

Definition at line 92 of file ra8_systick.c.

References k_ra8_err_invalid_arg, k_ra8_err_out_of_range, k_ra8_ok, k_ra8_systick_rvr_max, RA8_CHECK_NULL_PTR, ra8_log_error, and s_tag.

Referenced by demo_setup_or_halt().

◆ ra8_systick_set_reload()

ra8_err_t ra8_systick_set_reload ( uint32_t reload)
nodiscard

Re-arm SysTick with a new reload, leaving the control bits untouched.

Writes SYST_RVR with reload and clears SYST_CVR so the next count starts from the new reload. Unlike ra8_systick_configure this does NOT touch SYST_CSR, so the enable / clock-source / tick-interrupt bits already in force are preserved. This is the retune path: adjust the reload for a live clock change without a disable/enable glitch on the running tick.

Parameters
[in]reloadNew SYST_RVR reload value; <= k_ra8_systick_rvr_max.
Returns
Error code.
Return values
k_ra8_okReload re-armed; current value cleared.
k_ra8_err_out_of_rangereload exceeds k_ra8_systick_rvr_max.
Precondition
SysTick has already been configured (its control bits are set).
reload fits the 24-bit SYST_RVR field.
Postcondition
On k_ra8_ok, SYST_RVR holds reload and SYST_CVR reads zero.
On any error, no SysTick register is modified.
Note
Not thread-safe; write from a single context.
See also
ra8_systick_configure
Since
0.1.0

Definition at line 146 of file ra8_systick.c.

References internal_systick_reg(), k_ra8_err_out_of_range, k_ra8_ok, k_ra8_systick_cvr, k_ra8_systick_rvr, k_ra8_systick_rvr_max, ra8_log_error, and s_tag.

Referenced by ra8_threadx_systick_retune().