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

TSN scheduled-traffic demo: 802.1Qbv time-aware + 802.1Qav credit shaper. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_eth_gptp.h"
#include "ra8_etha.h"
#include "ra8_isr.h"
#include "ra8_mstp.h"
#include "ra8_time.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  tsn_const_t : uint32_t {
  k_tsn_baud = 115200U ,
  k_tsn_period_ms = 1000U ,
  k_tsn_win_units = 125000U ,
  k_tsn_cycle_units = 250000U ,
  k_tsn_cbs_increment = 1500U ,
  k_tsn_cbs_upper_lim = 65536U
}
 Demo tunables (illustrative shaper values). More...
enum  tsn_fmt_t : uint8_t {
  k_tsn_radix = 10U ,
  k_tsn_dec_u32_max = 10U ,
  k_tsn_dec_u64_max = 20U ,
  k_tsn_gate_entries = 2U
}
 Formatting + iteration constants. More...
enum  tsn_gptp_const_t : uint32_t {
  k_tsn_gptp_window_ms = 200U ,
  k_tsn_ns_per_ms = 1000000U ,
  k_tsn_ns_per_sec = 1000000000U
}
 gPTP time-base check parameters. More...
enum  tsn_flatten_limit_t : uint64_t { k_tsn_sec_flatten_max = 18446744073ULL }
 Largest seconds value that can be flattened to nanoseconds. More...
enum  tsn_band_t : uint8_t {
  k_tsn_tolerance_pct = 10U ,
  k_tsn_pct_full = 100U
}
 Accuracy band the gPTP advance must fall inside. More...
enum  tsn_gate_t : uint8_t { k_tsn_gate_ptp_only = 0x80U }
 EATASIGSC initial gate-state bitmap: bit q is queue q's gate. More...

Functions

static void tsn_panic_halt (void)
 Park forever after a fatal init error.
static void tsn_write (const uint8_t *data, uint32_t len)
 Write a byte span to the SCI8 console, discarding the status.
static uint32_t tsn_u32_to_dec (uint8_t *buf, uint32_t val)
 Serialise an unsigned 32-bit value into decimal ASCII.
static void tsn_write_u32 (uint32_t val)
 Log one unsigned 32-bit value as decimal ASCII.
static void tsn_write_u64 (uint64_t val)
 Log one unsigned 64-bit value as decimal ASCII.
static uint64_t tsn_flatten_ns (uint64_t sec, uint32_t nsec)
 Flatten a GPTP sample to nanoseconds.
static bool tsn_check_time_base (void)
 Verify the gPTP time base the TAS scheduler references is running.
static bool tsn_tas_entry_matches (uint8_t index, const ra8_etha_tas_entry_t *want)
 Read one TAS RAM entry back and compare it with what was programmed.
static bool tsn_program_tas (void)
 Program + arm the 802.1Qbv time-aware shaper on port 0.
static bool tsn_program_cbs (void)
 Configure the 802.1Qav credit-based shaper on traffic class 2.
static bool tsn_log_status (void)
 Read + log the ETHA port-0 status (TAS cycle-time monitor).
static bool tsn_run_cycle (void)
 Run one cycle: check the time base, program TAS + CBS, read status.
static void tsn_setup_or_halt (void)
 Core bring-up: CGC -> MSTP -> TIME -> console + LED.
static ra8_err_t tsn_arm_time_base (void)
 Start the gPTP time base the TAS scheduler references.
static ra8_err_t tsn_arm (void)
 Bring up the gPTP time base and ETHA port 0 in CONFIG mode.
void main (void)
 The application entry point Reset_Handler hands control to.

Variables

static const uint8_t k_tsn_tas_prefix [] = "tsn: tas_entries="
static const uint8_t k_tsn_cbs_prefix [] = "tsn: cbs_en="
static const uint8_t k_tsn_cbs_gate_sep [] = " gate="
static const uint8_t k_tsn_cyc_prefix [] = "tsn: tas_cycle="
static const uint8_t k_tsn_base_prefix [] = "tsn: gptp_adv_ns="
static const uint8_t k_tsn_base_sep [] = " sys_ms="
static const uint8_t k_tsn_crlf [] = "\r\n"
static const uint8_t k_tsn_verdict_pass [] = "tsn: schedule PASS\r\n"
static const uint8_t k_tsn_verdict_fail [] = "tsn: schedule FAIL\r\n"

Detailed Description

TSN scheduled-traffic demo: 802.1Qbv time-aware + 802.1Qav credit shaper.

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

Programs the RA8D2 Ethernet Agent (ETHA) time-sensitive-networking shapers that no other example referenced (recon gap #134).

NOTE on the gap: recon #134 named ra8_tsn as the "time-sensitive networking" driver, but libs/ra8_hal/ra8_tsn is the on-die temperature sensor (already demonstrated by adc_diag_tsn_demo, #183). The real TSN networking surface on this part is the ETHA shaper block: the time-aware shaper (TAS / 802.1Qbv scheduled traffic) and the credit-based shaper (CBS / 802.1Qav), exposed by ra8_etha_set_tas_schedule / ra8_etha_enable_tas and ra8_etha_configure_cbs / ra8_etha_get_cbs_state (HUM Ch 32 "Ethernet Agent"). Those are what this example drives.

TAS needs the gPTP time base as its schedule reference (the shaper's @pre PTP timer (ra8_eth_gptp) provides the time reference), so the app starts that counter for real first – ESWCLK up, PTPTIVCt derived from the live frequency, timer unit enabled – then:

  1. ra8_etha_init on port 0 in CONFIG mode (shaper registers are only writable in CONFIG).
  2. ra8_etha_tas_ram_reset, then ra8_etha_set_tas_schedule with a 2-entry gate list on descriptor queue 7 (PTP / control): one window open, one shut. Every entry is read back out of the TAS RAM with ra8_etha_read_tas_entry and compared. ra8_etha_enable_tas arms the scheduler.
  3. ra8_etha_configure_cbs on traffic class 2 (AVB class A) with an illustrative credit increment + upper limit, then ra8_etha_get_cbs_state reads the oper-side mirror back.
  4. ra8_etha_get_status reads the TAS cycle-time monitor.
Warning
What the verdict does and does not prove. "tsn: schedule PASS" requires three things: that the gPTP time base advanced by the measured wall-clock interval (the counter is read twice around a SysTick-timed window), that every TAS entry read back out of the TAS RAM matches what was written to it, and that every shaper call returned k_ra8_ok. The first two are hardware assertions. The third only proves the arguments were accepted: ETHA stays in CONFIG mode here, so no frame is ever transmitted and nothing about shaped egress is measured. That needs a multi-node measurement rig (bench wiring #89).

The read-back was added with #539, when the driver was found to be writing gate states into EATASGL0, whose field is the TAS RAM entry ADDRESS. Every call returned k_ra8_ok throughout, which is precisely why a verdict built only out of return codes was worth nothing.

hw_pending: tools/ra8_emulator now models the HUM Ch 35 GPTP timer (board_periph_gptp.c), so the gPTP time-base half of this verdict runs under emulation (the counter advances by the SysTick-measured window). The ETHA shaper half does not: the TAS gate RAM learn/read (EATASGL* / EATASGR*, HUM Ch 32) and the CBS state are indirect-RAM registers the emulator leaves to config-reflect, so ra8_etha_read_tas_entry reads back zero and the entry-match check fails – modelling that RAM is #539 / #292 territory. The EK-RA8D2 Ethernet wire is also marginal (#21). So the whole-app verdict is compile-gated in CI and asserted on the bench, while eth_gptp_timestamp_demo carries the emulator-gated counter-advance check.

Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ tsn_band_t

enum tsn_band_t : uint8_t

Accuracy band the gPTP advance must fall inside.

Enumerator
k_tsn_tolerance_pct 

Allowed drift vs SysTick, in percent.

k_tsn_pct_full 

Denominator for the percentage above.

Definition at line 118 of file main.c.

◆ tsn_const_t

enum tsn_const_t : uint32_t

Demo tunables (illustrative shaper values).

Enumerator
k_tsn_baud 

SCI8 console baud.

k_tsn_period_ms 

Delay between cycles.

k_tsn_win_units 

Per-window gate time, nanoseconds.

k_tsn_cycle_units 

Full GCL cycle = 2 windows, ns.

k_tsn_cbs_increment 

CBS credit increment (20-bit field).

k_tsn_cbs_upper_lim 

CBS upper credit limit (31-bit field).

Definition at line 83 of file main.c.

◆ tsn_flatten_limit_t

enum tsn_flatten_limit_t : uint64_t

Largest seconds value that can be flattened to nanoseconds.

UINT64_MAX / 1e9: above this, sec * 1e9 wraps.

Enumerator
k_tsn_sec_flatten_max 

floor(2^64 - 1 / 1e9).

Definition at line 113 of file main.c.

◆ tsn_fmt_t

enum tsn_fmt_t : uint8_t

Formatting + iteration constants.

Enumerator
k_tsn_radix 

Decimal serialiser radix.

k_tsn_dec_u32_max 

Max decimal digits for a uint32_t.

k_tsn_dec_u64_max 

Max decimal digits for a uint64_t.

k_tsn_gate_entries 

Gate-control-list entry count.

Definition at line 93 of file main.c.

◆ tsn_gate_t

enum tsn_gate_t : uint8_t

EATASIGSC initial gate-state bitmap: bit q is queue q's gate.

Enumerator
k_tsn_gate_ptp_only 

Only queue 7 (PTP / control) starts open.

Definition at line 126 of file main.c.

◆ tsn_gptp_const_t

enum tsn_gptp_const_t : uint32_t

gPTP time-base check parameters.

Enumerator
k_tsn_gptp_window_ms 

SysTick-timed measurement window.

k_tsn_ns_per_ms 

Nanoseconds in one millisecond.

k_tsn_ns_per_sec 

Nanoseconds in one second.

Definition at line 101 of file main.c.

Function Documentation

◆ main()

void main ( void )

The application entry point Reset_Handler hands control to.

Returns void, not int. This is a freestanding image: there is no hosted C environment, no process and nothing to report an exit status to. ISO C fixes main at int only for a hosted implementation; for a freestanding one (C23 5.1.2.1) the startup function's name and type are implementation-defined, and this is that definition. Reset_Handler discards no value because there is none to discard, and if main ever does return, startup halts the CPU rather than resuming anything.

The firmware lane is compiled -ffreestanding (see cmake/ra8_add_app.cmake) and the flag and this signature travel together: without it both GCC and clang reject a non-int main (-Wmain / -Wmain-return-type). Do not remove one without the other.

That coupling is why the declaration sits behind __STDC_HOSTED__ == 0, which -ffreestanding sets and a hosted build does not. The guard is not defensive dressing: this header is reachable from host builds (the unit tests compile ra8_core natively), and an unguarded void main(void); makes every hosted translation unit that includes it fail with conflicting types for 'main' against its own ISO int main. The declaration therefore exists exactly where its contract does.

Hosted first-party code – everything under tests/ and tools/ – uses the ISO int main(...) contract instead, because it genuinely does run under an OS that reads the exit status. scripts/checks/check_entry_points.py holds each domain to its own contract (#707).

Declared here, once, for the same reason SystemInit is: every vector_table.c used to restate it as a local extern int32_t main(void);, sixteen copies that no compiler ever compared against the definition – and roughly thirty of them had silently drifted out of agreement with the main they called.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has configured the clock tree and VTOR.
Postcondition
Control does not return; the image runs until reset or halt.
Any value the application wanted to report has been logged, not returned.
Note
Not thread-safe; single-threaded startup context only.
Warning
Only valid while the translation unit is compiled -ffreestanding. A hosted build rejects this signature.
See also
SystemInit()
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + BSP audio then plays blocks.

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 playback loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + GPT triple, runs sweep.

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 sweep loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART + RMII pins, then ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
Postcondition
On clean entry the kernel runs the worker thread once.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART, then enters ThreadX.

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

The application entry point Reset_Handler hands control to.

Brings up LED, console, SDHI pins, then ThreadX.

Precondition
Reset_Handler has copied .data + zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
CPUCLK0 is raised to the PLL1 target before the kernel starts.
On clean entry the SD card thread runs forever.
On any HAL init failure the function halts in __WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.

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 iso-IN feed loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
SystemInit set VTOR / FPU / priority grouping.

The application entry point Reset_Handler hands control to.

See file header.

Precondition
Boot init has completed.
The secure-boot library's BLXNS into NS image either failed or was skipped (the call site in ra8_trustzone_init is a no-op on host builds).
Postcondition
Diagnostic counter latched, CPU parked in a halt loop.
Function never returns.
Note
Single-threaded entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success g_eoh_chapters / g_eoh_crc hold the parsed results, the banner is emitted, and g_eoh_heartbeat advances once per frame.
On any failure g_eoh_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The chapters/ch0-CRC banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the g_etoc_* result globals hold the parsed TOC values, the banner is emitted, and g_etoc_heartbeat advances once per frame.
On any failure g_etoc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss; SystemInit set VTOR/FPU.
Postcondition
The shelf scans on the panel; taps open books, browse, and read.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The slab/arena/tile/vmem banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the cache globals are latched and g_pc_heartbeat advances.
On any failure g_pc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Profiles power modes once a second.

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 profile + blink loop.
On any HAL hard error LED2 latches ON.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
The shared board boot files installed the vector table.
Postcondition
The demo has run once and its verdict banner is streaming steadily.
The CPU idles re-emitting the banner (or halts after a fatal init error).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up the clocks, console, SPI, and SD card, then runs the shared ra8_io VFS round-trip over the SD-over-SPI block device. On success it prints the exact PASS banner the HIL runner and ra8_emulator smoke gate scrape for; on any failure it prints FAIL and parks the core.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the CPU loops forever after the PASS banner.
On any failure the function prints FAIL and halts in WFI.
Note
Not thread-safe; this is the single-threaded app entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Initialises logging and the console, brings up the OSPI NOR volume, runs the erase-before-write round-trip, and prints a single PASS/FAIL verdict line over SCI8 before parking in an infinite loop.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The OSPI NOR array is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The page-count + render-hash banner is emitted; the CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The cal=OK / cal=SKIP result and the finger-free touchcal: ready sentinel are emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The open=OK touch banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Both USB controllers' clocks and pins come up before the kernel so the workers only deal with stack bring-up.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR, FPU, priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up logging and the clock tree, releases the Cortex-M33 (which then blinks LED1 via ra8_pcntr_set_output()), and idles. See the file header.

Precondition
SystemInit has completed core bring-up.
The M33 is held in reset by hardware until released here.
Postcondition
The M33 has been released and is blinking LED1.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this template.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
The application links ra8_c6link and ESP-hosted generated codecs.
No hardware validation is inferred from this function.
Postcondition
No c6link operation is attempted.
No network or storage state is modified.
Note
Single-threaded compile fixture.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up logging, the clock tree, and the VCOM console, runs the cacheable-SRAM round-trip with the D-cache that SystemInit() enabled through ra8_cache_dcache_enable(), emits the matching PASS / FAIL banner over the console and ra8_log, then parks in WFI. Every byte the self-test touches runs with the L1 caches + MPU enabled by the shared boot (RA8_BOOT_ENABLE_CACHE_MPU + RA8_BOOT_CACHE_VIA_HAL).

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit enabled the MPU + I-cache + D-cache via the ra8_cache HAL.
Postcondition
Exactly one banner (PASS or FAIL) has been emitted.
The core is parked in WFI.
Note
Single-threaded; no RTOS and no IRQ sources in this template.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Publishes the mailbox, releases the Cortex-M33 into the emitter, yields until it signals done, validates the blob the M33 built, then logs the PASS/FAIL verdict and the chapter count read back from the blob. See the file header for the offload narrative.

Precondition
SystemInit has completed core bring-up.
The M33 is held inactive by hardware until released here.
Postcondition
The M33 has built a RABOOK1 blob and the M85 has validated it.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this example.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the CPU heartbeats after epaper: PASS.
On any HAL error the console prints epaper: FAIL and the red LED latches on.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The chapters/toc/cover banner is emitted; CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The reader loop runs forever, redrawing on each tap.
A page-1 banner is emitted once after the first render.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The cover-size / framebuffer-CRC banner is emitted; CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The panel shows the reader screen and the input loop runs forever.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Publishes the mailbox, arms the IPC0 wake and configures the LPM block, releases the Cortex-M33 into the reader, waits for the first held page, logs the page-0 verdict, then runs the #150 mode-switch cycle – parking in low-power WFI and waking on the M33's page-turn pokes – before logging the handoff verdict and parking for good. See the file header for the narrative.

Precondition
SystemInit has completed core bring-up.
The M33 is held inactive by hardware until released here.
Postcondition
The M33 has rendered + re-rendered the held page and the M85 is parked.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this example.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The boot banner is emitted; the reader loop services taps forever.
Since
0.1.0

Definition at line 650 of file main.c.

References k_ra8_board_led1, k_ra8_ok, k_tsn_period_ms, k_tsn_verdict_fail, k_tsn_verdict_pass, ra8_board_led_toggle(), ra8_delay_ms(), ra8_isr_globals_enable(), tsn_arm(), tsn_panic_halt(), tsn_run_cycle(), tsn_setup_or_halt(), and tsn_write().

◆ tsn_arm()

ra8_err_t tsn_arm ( void )
staticnodiscard

Bring up the gPTP time base and ETHA port 0 in CONFIG mode.

tsn_arm_time_base starts the GPTP counter that the TAS scheduler uses as its cycle reference; ra8_etha_init powers ETHA port 0 and enters CONFIG mode (initial_mode = k_ra8_etha_opc_config), which is the only mode in which the TAS / CBS shaper registers are writable.

Returns
ra8_err_t error code from the first failing step.
Return values
k_ra8_okgPTP timer running and port 0 is in CONFIG mode.
OtherForwarded from tsn_arm_time_base / ra8_etha_init.
Precondition
tsn_setup_or_halt has ungated MSTP.
IRQs are masked or this is single-threaded init.
Postcondition
On k_ra8_ok the shaper registers on port 0 are writable.
On failure no partial ETHA state is relied upon by the caller.
Since
0.1.0

Definition at line 635 of file main.c.

References k_ra8_etha_opc_config, k_ra8_etha_port_0, k_ra8_ok, ra8_etha_init(), and tsn_arm_time_base().

Referenced by main().

◆ tsn_arm_time_base()

ra8_err_t tsn_arm_time_base ( void )
staticnodiscard

Start the gPTP time base the TAS scheduler references.

Reads the live ESWCLK frequency, hands it to ra8_eth_gptp_init (which derives PTPTIVCt from it), then enables the timer unit so the counter actually advances.

Returns
ra8_err_t error code from the first failing step.
Return values
k_ra8_okThe gPTP counter is programmed and running.
OtherForwarded from the failing driver call.
Precondition
tsn_setup_or_halt has started ESWCLK and ungated MSTP.
IRQs are masked or this is single-threaded init.
Postcondition
On k_ra8_ok timer unit 0 is counting.
On failure no partial gPTP state is relied upon by the caller.
Note
Boot-time only; not re-entrant.
Since
0.1.0

Definition at line 601 of file main.c.

References k_ra8_gptp_timer_0, k_ra8_ok, ra8_cgc_eswclk_hz(), ra8_eth_gptp_init(), and ra8_eth_gptp_timer_enable().

Referenced by tsn_arm().

◆ tsn_check_time_base()

bool tsn_check_time_base ( void )
static

Verify the gPTP time base the TAS scheduler references is running.

Samples the 78-bit GPTP counter either side of a SysTick-timed window and requires the advance to match to within k_tsn_tolerance_pct. Without this the app would program a gate-control list against a time base that never started, which is exactly the defect issue #498 records.

Returns
True iff the counter advanced by the measured interval.
Return values
trueThe advance matched SysTick inside the tolerance band.
falseA read failed, or the counter did not track SysTick.
Precondition
tsn_arm enabled gPTP timer unit 0.
The console has been initialised.
Postcondition
One tsn: gptp_adv_ns= line has been queued.
No gPTP or ETHA configuration was changed.
Note
Not thread-safe; single-threaded demo loop.
Since
0.1.0

Definition at line 315 of file main.c.

References k_ra8_gptp_timer_0, k_ra8_ok, k_tsn_base_prefix, k_tsn_base_sep, k_tsn_crlf, k_tsn_gptp_window_ms, k_tsn_ns_per_ms, k_tsn_pct_full, k_tsn_tolerance_pct, ra8_delay_ms(), ra8_eth_gptp_get_time(), ra8_time_ms(), tsn_flatten_ns(), tsn_write(), tsn_write_u32(), and tsn_write_u64().

Referenced by tsn_run_cycle().

◆ tsn_flatten_ns()

uint64_t tsn_flatten_ns ( uint64_t sec,
uint32_t nsec )
static

Flatten a GPTP sample to nanoseconds.

The seconds field is 48 bits wide, so sec * 1e9 would wrap a uint64_t above sec ~= 1.8e10. That value comes straight off a hardware register, so an implausible reading is clamped rather than silently wrapped into a small number that could look like a healthy advance.

Parameters
[in]secSeconds field.
[in]nsecNanoseconds field.
Returns
The sample as a nanosecond count, or UINT64_MAX if sec is too large to flatten.
Precondition
nsec is below one second.
sec came from ra8_eth_gptp_get_time (48-bit range).
Postcondition
The result is monotonic in sec and nsec.
No hardware was touched.
Note
Pure and re-entrant.
Since
0.1.0

Definition at line 286 of file main.c.

References k_tsn_ns_per_sec, and k_tsn_sec_flatten_max.

Referenced by tsn_check_time_base().

◆ tsn_log_status()

bool tsn_log_status ( void )
static

Read + log the ETHA port-0 status (TAS cycle-time monitor).

Returns
True iff ra8_etha_get_status returned k_ra8_ok.
Precondition
ra8_etha_init brought up port 0.
The console has been initialised.
Postcondition
One tsn: tas_cycle= line has been queued.
No ETHA register state was mutated (status read is passive).
Since
0.1.0

Definition at line 502 of file main.c.

References k_ra8_etha_port_0, k_ra8_ok, k_tsn_crlf, k_tsn_cyc_prefix, ra8_etha_get_status(), ra8_etha_status_t::tas_cycle, tsn_write(), and tsn_write_u32().

Referenced by tsn_run_cycle().

◆ tsn_panic_halt()

void tsn_panic_halt ( void )
static

Park forever after a fatal init error.

Precondition
Called only after an unrecoverable bring-up failure.
Postcondition
CPU is parked; only a debugger or reset wakes it.
Since
0.1.0

Definition at line 149 of file main.c.

Referenced by main(), and tsn_setup_or_halt().

◆ tsn_program_cbs()

bool tsn_program_cbs ( void )
static

Configure the 802.1Qav credit-based shaper on traffic class 2.

Programs an illustrative credit increment + upper limit on class 2 (AVB class A) via ra8_etha_configure_cbs, then reads the oper-side mirror back with ra8_etha_get_cbs_state and logs the enable + gate-open bits.

Returns
True iff both CBS calls returned k_ra8_ok.
Precondition
ra8_etha_init left port 0 in CONFIG mode.
The console has been initialised.
Postcondition
One tsn: cbs_en=.. gate=.. line has been queued.
Class-2 CBS admin registers reflect the programmed parameters.
Since
0.1.0

Definition at line 465 of file main.c.

References k_ra8_etha_port_0, k_ra8_etha_tc_2, k_ra8_ok, k_tsn_cbs_gate_sep, k_tsn_cbs_increment, k_tsn_cbs_prefix, k_tsn_cbs_upper_lim, k_tsn_crlf, ra8_etha_configure_cbs(), ra8_etha_get_cbs_state(), tsn_write(), and tsn_write_u32().

Referenced by tsn_run_cycle().

◆ tsn_program_tas()

bool tsn_program_tas ( void )
static

Program + arm the 802.1Qbv time-aware shaper on port 0.

Resets the TAS RAM, then gives descriptor queue 7 (PTP / control) a two-entry gate list – one window open, one shut – and commits it via ra8_etha_set_tas_schedule. The gate list belongs to a QUEUE rather than being an interleaved per-class vector, because a TAS entry on this silicon carries a single gate-state bit for the queue whose TAS RAM block holds it (HUM Table 32.6 p 1691).

Every entry is then read back out of the TAS RAM with ra8_etha_read_tas_entry and compared against what was programmed. That read-back is the only part of this function that is evidence: the programming calls returned k_ra8_ok even when the driver was writing gate states into the entry-address register (#539).

Returns
True iff the schedule was committed AND read back byte-identical.
Precondition
ra8_etha_init left port 0 in CONFIG mode.
The gPTP time base is running (ra8_eth_gptp_init).
Postcondition
One tsn: tas_entries= line has been queued.
On success EATASC.TASE is set (scheduler armed).
Since
0.1.0

Definition at line 412 of file main.c.

References ra8_etha_tas_queue_t::count, ra8_etha_tas_queue_t::entries, k_ra8_etha_port_0, k_ra8_etha_tc_7, k_ra8_etha_tc_count, k_ra8_ok, k_tsn_crlf, k_tsn_cycle_units, k_tsn_gate_entries, k_tsn_gate_ptp_only, k_tsn_tas_prefix, k_tsn_win_units, ra8_etha_enable_tas(), ra8_etha_set_tas_schedule(), ra8_etha_tas_ram_reset(), tsn_tas_entry_matches(), tsn_write(), and tsn_write_u32().

Referenced by tsn_run_cycle().

◆ tsn_run_cycle()

bool tsn_run_cycle ( void )
static

Run one cycle: check the time base, program TAS + CBS, read status.

Returns
True iff the gPTP counter advanced and every shaper call returned k_ra8_ok.
Precondition
tsn_arm started gPTP and left ETHA port 0 in CONFIG mode.
The console has been initialised.
Postcondition
One log block (time base + TAS + CBS + status) has been queued.
The shaper schedule is (re)programmed and armed.
Since
0.1.0

Definition at line 528 of file main.c.

References tsn_check_time_base(), tsn_log_status(), tsn_program_cbs(), and tsn_program_tas().

Referenced by main().

◆ tsn_setup_or_halt()

void tsn_setup_or_halt ( void )
static

Core bring-up: CGC -> MSTP -> TIME -> console + LED.

Precondition
Reset defaults are in force (single-threaded boot context).
No peripheral has been claimed yet.
Postcondition
On return every core clock + console + LED is live.
Any failure parks the CPU via tsn_panic_halt.
Since
0.1.0

Definition at line 555 of file main.c.

References k_ra8_board_led1, k_ra8_clock_id_cpuclk0, k_ra8_ok, k_tsn_baud, ra8_board_led_init(), ra8_board_uart_console_init(), ra8_cgc_eswclk_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_mstp_init(), ra8_time_init(), and tsn_panic_halt().

Referenced by main().

◆ tsn_tas_entry_matches()

bool tsn_tas_entry_matches ( uint8_t index,
const ra8_etha_tas_entry_t * want )
static

Read one TAS RAM entry back and compare it with what was programmed.

The read-back half of the TAS verdict. Split into its own predicate so the caller has a single failure branch: a read error and a value mismatch are the same outcome to the demo, and expressing them as two branches with identical bodies is what clang-tidy's bugprone-branch-clone objects to.

Parameters
[in]indexTAS RAM entry address to read.
[in]wantThe entry that was programmed at that address.
Returns
True iff the read succeeded and both fields match.
Precondition
ra8_etha_set_tas_schedule has programmed index.
want points at the entry originally written there.
Postcondition
No hardware state is changed beyond EATASGR.
Since
0.1.0

Definition at line 375 of file main.c.

References ra8_etha_tas_entry_t::gate_open, ra8_etha_tas_entry_t::gate_time_ns, k_ra8_etha_port_0, k_ra8_ok, and ra8_etha_read_tas_entry().

Referenced by tsn_program_tas().

◆ tsn_u32_to_dec()

uint32_t tsn_u32_to_dec ( uint8_t * buf,
uint32_t val )
static

Serialise an unsigned 32-bit value into decimal ASCII.

Parameters
[out]bufDestination, at least k_tsn_dec_u32_max bytes.
[in]valValue to serialise.
Returns
Number of digits written (1..10).
Precondition
buf is non-NULL and sized for the widest uint32_t.
No trailing NUL is required by the caller.
Postcondition
buf holds the most-significant digit first.
The return value is in [1, k_tsn_dec_u32_max].
Since
0.1.0

Definition at line 186 of file main.c.

References k_tsn_dec_u32_max, and k_tsn_radix.

Referenced by tsn_write_u32().

◆ tsn_write()

void tsn_write ( const uint8_t * data,
uint32_t len )
static

Write a byte span to the SCI8 console, discarding the status.

Parameters
[in]dataNon-NULL byte span to transmit.
[in]lenByte count (0 is a no-op).
Precondition
ra8_board_uart_console_init has succeeded.
data points at len readable bytes.
Postcondition
len bytes have been queued to the console UART.
Since
0.1.0

Definition at line 167 of file main.c.

References ra8_board_uart_console_write().

Referenced by main(), tsn_check_time_base(), tsn_log_status(), tsn_program_cbs(), tsn_program_tas(), tsn_write_u32(), and tsn_write_u64().

◆ tsn_write_u32()

void tsn_write_u32 ( uint32_t val)
static

Log one unsigned 32-bit value as decimal ASCII.

Parameters
[in]valValue to print.
Precondition
The console has been initialised.
val fits in a uint32_t (always true).
Postcondition
The decimal digits of val have been queued to the console.
Since
0.1.0

Definition at line 216 of file main.c.

References k_tsn_dec_u32_max, tsn_u32_to_dec(), and tsn_write().

Referenced by tsn_check_time_base(), tsn_log_status(), tsn_program_cbs(), and tsn_program_tas().

◆ tsn_write_u64()

void tsn_write_u64 ( uint64_t val)
static

Log one unsigned 64-bit value as decimal ASCII.

A standalone serialiser rather than a split-at-10^9 pair of tsn_write_u32 calls: the low half would need zero-padding to nine digits, and an unpadded join silently renders 1000000005 as "15".

Parameters
[in]valValue to print.
Precondition
The console has been initialised.
val fits in a uint64_t (always true).
Postcondition
The decimal digits of val have been queued to the console.
Neither scratch buffer outlives the call.
Note
Not thread-safe; single-threaded demo loop.
Since
0.1.0

Definition at line 241 of file main.c.

References k_tsn_dec_u64_max, k_tsn_radix, and tsn_write().

Referenced by tsn_check_time_base().

Variable Documentation

◆ k_tsn_base_prefix

const uint8_t k_tsn_base_prefix[] = "tsn: gptp_adv_ns="
static

Definition at line 136 of file main.c.

Referenced by tsn_check_time_base().

◆ k_tsn_base_sep

const uint8_t k_tsn_base_sep[] = " sys_ms="
static

Definition at line 137 of file main.c.

Referenced by tsn_check_time_base().

◆ k_tsn_cbs_gate_sep

const uint8_t k_tsn_cbs_gate_sep[] = " gate="
static

Definition at line 134 of file main.c.

Referenced by tsn_program_cbs().

◆ k_tsn_cbs_prefix

const uint8_t k_tsn_cbs_prefix[] = "tsn: cbs_en="
static

Definition at line 133 of file main.c.

Referenced by tsn_program_cbs().

◆ k_tsn_crlf

const uint8_t k_tsn_crlf[] = "\r\n"
static

Definition at line 138 of file main.c.

Referenced by tsn_check_time_base(), tsn_log_status(), tsn_program_cbs(), and tsn_program_tas().

◆ k_tsn_cyc_prefix

const uint8_t k_tsn_cyc_prefix[] = "tsn: tas_cycle="
static

Definition at line 135 of file main.c.

Referenced by tsn_log_status().

◆ k_tsn_tas_prefix

const uint8_t k_tsn_tas_prefix[] = "tsn: tas_entries="
static

Definition at line 132 of file main.c.

Referenced by tsn_program_tas().

◆ k_tsn_verdict_fail

const uint8_t k_tsn_verdict_fail[] = "tsn: schedule FAIL\r\n"
static

Definition at line 140 of file main.c.

Referenced by main().

◆ k_tsn_verdict_pass

const uint8_t k_tsn_verdict_pass[] = "tsn: schedule PASS\r\n"
static

Definition at line 139 of file main.c.

Referenced by main().