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

Clock bring-up HIL test for EK-RA8D2 (CGC: HOCO + PLL). More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_isr.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_time.h"
#include "ra8_time_constants.h"
Include dependency graph for main.c:

Go to the source code of this file.

Data Structures

struct  clock_check_expected_t
 Pair of (clock id, expected post-PLL frequency in Hz). More...

Enumerations

enum  clock_check_period_t : uint32_t { k_clock_check_half_period_ms = 500U }
 Half-period of the visible blink, in milliseconds. More...

Functions

static ra8_err_t internal_clock_check_pins_init (void)
 Configure all three EK-RA8D2 user LEDs as outputs (low).
static ra8_err_t internal_clock_check_pins_toggle_all (void)
 Toggle all three LED pins (one HAL call each).
static bool internal_clock_check_verify_all (void)
 Verify every clock-tree readback equals its post-PLL target.
static void internal_clock_check_panic_halt (void)
 Halt forever in WFI – used as a panic stop on init failure.
void main (void)
 Application entry.

Variables

volatile uint32_t g_clock_check_match = 0U
 HIL liveness counter – incremented once per blink iteration when every queried clock-tree domain (CPUCLK0, CPUCLK1, ICLK, PCLKA..E, FCLK, MRICLK) reports its expected target frequency exactly.
volatile uint32_t g_clock_check_mismatch = 0U
 HIL failure counter – incremented whenever any clock-tree readback disagrees with its expected target value (or the ra8_cgc_get_clock_hz call itself errors), or when an LED toggle fails.

Detailed Description

Clock bring-up HIL test for EK-RA8D2 (CGC: HOCO + PLL).

Tag
[Ring 6 / APP] {World: S}

Brings the chip from reset-default MOCO (~8.4 MHz) up to its rated operating speed via the CGC driver, then blinks the user LEDs at a stopwatch-checkable 1 Hz so we can confirm SysTick timing matches the new clock rate.

Sequence:

  1. ra8_cgc_init() – HOCO on, PLL1 locked, CPUCLK0 + bus clocks live. This is the first time the CGC driver runs on real silicon end-to-end.
  2. ra8_cgc_get_clock_hz(k_ra8_clock_id_cpuclk0, &hz) – read back the configured rate so SysTick can use the actual value rather than a hardcoded constant.
  3. ra8_time_init(hz) – programme SysTick for a 1 ms tick at the new clock rate.
  4. ra8_gpio_output_init() for each LED, then a 1 Hz toggle loop using ra8_delay_ms(500).

Verification: the LEDs should toggle at exactly 1 Hz on a stopwatch (within whatever PLL accuracy the chip guarantees – typically tens of ppm). If the period is off by orders of magnitude, the reported CPUCLK0 value disagrees with the actual silicon clock and something in the CGC bring-up went wrong.

Compared to examples/blink_hal: that demo runs on MOCO ~8.4 MHz and ra8_delay_ms(500) is therefore ~500 ms. This demo runs on the real CPUCLK0 (e.g. ~480 MHz post-PLL on Cortex-M85), so any SysTick-arithmetic bug in ra8_time.c will show up immediately as a wrong-by-100x blink rate.

Architectural ring
[Ring 6 / APP] {World: S} – application-layer code that runs in the Secure world.
Author
Brighton Sikarskie
Date
2026-04-28
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ clock_check_period_t

enum clock_check_period_t : uint32_t

Half-period of the visible blink, in milliseconds.

Enumerator
k_clock_check_half_period_ms 

Clock check half period ms.

Definition at line 63 of file main.c.

Function Documentation

◆ internal_clock_check_panic_halt()

void internal_clock_check_panic_halt ( void )
static

Halt forever in WFI – used as a panic stop on init failure.

Preserves the failed clock or GPIO state in a low-activity loop for an attached debugger.

Returns
None.
Precondition
Called only after a fatal error in boot.
Any desired HIL failure state has already been recorded.
Postcondition
CPU is parked; only a debugger or external reset wakes it.
No further clock validation or LED transition occurs.
Note
Interrupt wakeups return immediately to the permanent loop.
Since
0.1.0

Definition at line 148 of file main.c.

References RA8_INTERNAL.

Referenced by main().

◆ internal_clock_check_pins_init()

ra8_err_t internal_clock_check_pins_init ( void )
staticnodiscard

Configure all three EK-RA8D2 user LEDs as outputs (low).

Returns
Error code from the first failing GPIO init or k_ra8_ok.
Return values
k_ra8_okEvery LED pin is now a digital output.
k_ra8_err_invalid_argA pin id was rejected by the HAL.
k_ra8_err_gpio_conflictA pin was already claimed.
Precondition
IOPORT module is reachable (true on reset).
Caller is single-threaded init context.
Postcondition
On success P6_00, P3_03, P10_07 are output-low.
Since
0.1.0

Definition at line 219 of file main.c.

References k_ra8_board_led1, k_ra8_board_led2, k_ra8_board_led3, k_ra8_ok, ra8_board_led_init(), and RA8_INTERNAL.

Referenced by main().

◆ internal_clock_check_pins_toggle_all()

ra8_err_t internal_clock_check_pins_toggle_all ( void )
staticnodiscard

Toggle all three LED pins (one HAL call each).

Returns
Error code from the first failing toggle or k_ra8_ok.
Return values
k_ra8_okAll three pins toggled.
k_ra8_err_invalid_argA pin id became invalid (shouldn't happen).
Precondition
internal_clock_check_pins_init() has succeeded.
Postcondition
Each LED's output latch is inverted from its prior value.
Since
0.1.0

Definition at line 246 of file main.c.

References k_ra8_board_led1, k_ra8_board_led2, k_ra8_board_led3, k_ra8_ok, ra8_board_led_toggle(), and RA8_INTERNAL.

Referenced by main().

◆ internal_clock_check_verify_all()

bool internal_clock_check_verify_all ( void )
staticnodiscard

Verify every clock-tree readback equals its post-PLL target.

Walks a fixed table of (id, expected_hz) tuples and asks the CGC driver what each clock is currently running at. The function returns true only if every readback succeeds and matches the constant exactly – the values are programmed deterministically by ra8_cgc_init so there is no tolerance to allow for.

Returns
true All queried clocks match their expected target.
false At least one clock readback errored or disagreed.
Precondition
ra8_cgc_init() returned k_ra8_ok earlier this boot.
Caller is single-threaded (the CGC driver is non-reentrant).
Postcondition
No clock-tree state is mutated.
On false the table walk short-circuits at the first failure.
Note
Called from the main loop only; not ISR-safe.
Since
0.1.0

Definition at line 281 of file main.c.

References k_ra8_clock_id_cpuclk0, k_ra8_clock_id_cpuclk1, k_ra8_clock_id_fclk, k_ra8_clock_id_iclk, k_ra8_clock_id_mriclk, k_ra8_clock_id_pclka, k_ra8_clock_id_pclkb, k_ra8_clock_id_pclkc, k_ra8_clock_id_pclkd, k_ra8_clock_id_pclke, k_ra8_cpuclk0_hz, k_ra8_cpuclk1_hz, k_ra8_fclk_hz, k_ra8_iclk_hz, k_ra8_mriclk_hz, k_ra8_ok, k_ra8_pclka_hz, k_ra8_pclkb_hz, k_ra8_pclkc_hz, k_ra8_pclkd_hz, k_ra8_pclke_hz, ra8_cgc_get_clock_hz(), and RA8_INTERNAL.

Referenced by main().

◆ main()

void main ( void )

Application entry.

The application entry point Reset_Handler hands control to.

Lights HOCO + PLL, then runs a 1 Hz blink.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the toggle loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

Definition at line 166 of file main.c.

References g_clock_check_match, g_clock_check_mismatch, internal_clock_check_panic_halt(), internal_clock_check_pins_init(), internal_clock_check_pins_toggle_all(), internal_clock_check_verify_all(), k_clock_check_half_period_ms, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_delay_ms(), ra8_isr_globals_enable(), and ra8_time_init().

Variable Documentation

◆ g_clock_check_match

volatile uint32_t g_clock_check_match = 0U

HIL liveness counter – incremented once per blink iteration when every queried clock-tree domain (CPUCLK0, CPUCLK1, ICLK, PCLKA..E, FCLK, MRICLK) reports its expected target frequency exactly.

Read externally by scripts/hil/jlink_memprobe.sh via SWD. The probe asserts this counter advances by >= HIL_PROBE_MIN_ADVANCE over the sample window, proving the CGC bring-up not only completed without faulting but also produced the targeted PLL1P-derived clock tree. If the chip silently fell back to MOCO, the readback would not match k_ra8_cpuclk0_hz and this counter would freeze.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 85 of file main.c.

Referenced by main().

◆ g_clock_check_mismatch

volatile uint32_t g_clock_check_mismatch = 0U

HIL failure counter – incremented whenever any clock-tree readback disagrees with its expected target value (or the ra8_cgc_get_clock_hz call itself errors), or when an LED toggle fails.

The memprobe asserts this stays at 0 (or below HIL_PROBE_MAX_FAILURE). Catches "PLL never locked", "wrong divider programmed", and "CGC driver returned a stale value" – previously invisible because alive-mode could only see that the toggle loop kept running, not what frequency it was actually running at.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 104 of file main.c.

Referenced by main().