|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Cortex-M85 SysTick + DWT cycle-counter timebase implementation. More...
#include "ra8_systick.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_systick_reg_addr_t : uintptr_t { k_ra8_systick_csr = 0xE000E010UL , k_ra8_systick_rvr = 0xE000E014UL , k_ra8_systick_cvr = 0xE000E018UL , k_ra8_dwt_demcr = 0xE000EDFCUL , k_ra8_dwt_ctrl = 0xE0001000UL , k_ra8_dwt_cyccnt = 0xE0001004UL } |
| Arm v8-M SCS timebase register addresses (PPB 0xE000Exxx). More... | |
| enum | ra8_systick_bit_t : uint32_t { k_ra8_systick_csr_enable = 0x00000001UL , k_ra8_systick_csr_tickint = 0x00000002UL , k_ra8_systick_csr_clksource = 0x00000004UL , k_ra8_dwt_demcr_trcena = 0x01000000UL , k_ra8_dwt_ctrl_cyccntena = 0x00000001UL } |
| Control bits for SYST_CSR, DEMCR, and DWT_CTRL. More... | |
Functions | |
| static volatile uint32_t * | internal_systick_reg (ra8_systick_reg_addr_t addr) |
| Typed pointer to a 32-bit SCS timebase register. | |
| 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). | |
Variables | |
| static const char *const | s_tag = "ra8_systick" |
| Module log tag. | |
Cortex-M85 SysTick + DWT cycle-counter timebase implementation.
Implements ::ra8_systick.h against the Arm v8-M System Control Space (PPB window 0xE000Exxx). SysTick is programmed through SYST_CSR / SYST_RVR / SYST_CVR; the DWT free-running cycle counter is unlocked via DEMCR.TRCENA, started via DWT_CTRL.CYCCNTENA, and sampled from DWT_CYCCNT.
These are Arm-architecture registers, so the inline comments reference the Arm v8-M Architecture Reference Manual (the "Arm v8-M ARM") rather than the RA8D2 Hardware User's Manual. On a host build the SCS window is backed by the fake MMIO map, so the writes are observable to unit tests and the reload / range logic runs exactly as on silicon – there is no RA8_OFF_TARGET guard around the accesses here, unlike a driver that reaches a real peripheral bus.
Definition in file ra8_systick.c.
| enum ra8_systick_bit_t : uint32_t |
Control bits for SYST_CSR, DEMCR, and DWT_CTRL.
Arm v8-M ARM register descriptions for SYST_CSR, DEMCR, and DWT_CTRL.
Definition at line 58 of file ra8_systick.c.
| enum ra8_systick_reg_addr_t : uintptr_t |
Arm v8-M SCS timebase register addresses (PPB 0xE000Exxx).
Arm v8-M ARM: SysTick registers live in the System Control Block and DWT registers in the Data Watchpoint and Trace unit. Both are mapped into the fake core window (0xE0000000) on a host build, real PPB on silicon.
Definition at line 43 of file ra8_systick.c.
|
inlinestatic |
Typed pointer to a 32-bit SCS timebase register.
Trivial address-cast helper shared by every access below, so no register store or load in this file is written as a raw pointer-cast dereference.
| [in] | addr | One of ra8_systick_reg_addr_t. |
| (volatile | uint32_t*)addr Always the aliasing register pointer. |
addr is a valid SCS timebase-register address. Definition at line 87 of file ra8_systick.c.
Referenced by ra8_dwt_cyccnt_enable(), ra8_dwt_cyccnt_read(), ra8_dwt_cyccnt_reset(), ra8_systick_configure(), ra8_systick_current_value(), and ra8_systick_set_reload().
| 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.
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().
|
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.
| 0..UINT32_MAX | CPU cycles counted since the counter was last zeroed, modulo 2^32. |
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().
| 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.
Definition at line 176 of file ra8_systick.c.
References internal_systick_reg(), and k_ra8_dwt_cyccnt.
Referenced by demo_emit_measurement().
|
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.
| [in] | reload | SYST_RVR reload value; must be <= k_ra8_systick_rvr_max. |
| [in] | src | Counter clock source (ra8_systick_clock_source_t). |
| [in] | tick_irq | When 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. |
| k_ra8_ok | SysTick armed and counting. |
| k_ra8_err_out_of_range | reload exceeds k_ra8_systick_rvr_max. |
reload was produced by ra8_systick_reload_for or is otherwise known to fit the 24-bit field. reload and the counter is enabled. 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().
|
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.
| 0..k_ra8_systick_rvr_max | Current down-counter value. |
Definition at line 161 of file ra8_systick.c.
References internal_systick_reg(), and k_ra8_systick_cvr.
|
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.
| [in] | cpu_hz | Core (SysTick) clock in Hz. |
| [in] | tick_hz | Desired tick rate in Hz (e.g. 1000 for a 1 ms tick). |
| [out] | out_reload | On success, receives the SYST_RVR reload value. |
| k_ra8_ok | Reload computed and written to out_reload. |
| k_ra8_err_null_ptr | out_reload is NULL. |
| k_ra8_err_invalid_arg | cpu_hz or tick_hz is zero, or cpu_hz is below one tick period. |
| k_ra8_err_out_of_range | The reload exceeds k_ra8_systick_rvr_max (cpu_hz far too high for tick_hz). |
out_reload is a valid, writable uint32_t. tick_hz is the rate the caller will actually program. out_reload is left unmodified.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().
|
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.
| [in] | reload | New SYST_RVR reload value; <= k_ra8_systick_rvr_max. |
| k_ra8_ok | Reload re-armed; current value cleared. |
| k_ra8_err_out_of_range | reload exceeds k_ra8_systick_rvr_max. |
reload fits the 24-bit SYST_RVR field. reload and SYST_CVR reads zero. 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().
|
static |
Module log tag.
Definition at line 33 of file ra8_systick.c.