|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
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"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" |
TSN scheduled-traffic demo: 802.1Qbv time-aware + 802.1Qav credit shaper.
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:
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.
Definition in file main.c.
| enum tsn_band_t : uint8_t |
| enum tsn_const_t : uint32_t |
Demo tunables (illustrative shaper values).
| enum tsn_flatten_limit_t : uint64_t |
| enum tsn_fmt_t : uint8_t |
| enum tsn_gate_t : uint8_t |
| enum tsn_gptp_const_t : uint32_t |
| 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.
The application entry point Reset_Handler hands control to.
Brings up CGC + BSP audio then plays blocks.
The application entry point Reset_Handler hands control to.
Brings up CGC + GPT triple, runs sweep.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART + RMII pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART, then enters ThreadX.
The application entry point Reset_Handler hands control to.
Brings up LED, console, SDHI pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
See file header.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Profiles power modes once a second.
The application entry point Reset_Handler hands control to.
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.
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.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
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.
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.
The application entry point Reset_Handler hands control to.
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).
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.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
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.
The application entry point Reset_Handler hands control to.
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().
|
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.
| k_ra8_ok | gPTP timer running and port 0 is in CONFIG mode. |
| Other | Forwarded from tsn_arm_time_base / ra8_etha_init. |
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().
|
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.
| k_ra8_ok | The gPTP counter is programmed and running. |
| Other | Forwarded from the failing driver call. |
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().
|
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.
| true | The advance matched SysTick inside the tolerance band. |
| false | A read failed, or the counter did not track SysTick. |
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().
|
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.
| [in] | sec | Seconds field. |
| [in] | nsec | Nanoseconds field. |
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().
|
static |
Read + log the ETHA port-0 status (TAS cycle-time monitor).
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().
|
static |
Park forever after a fatal init error.
Definition at line 149 of file main.c.
Referenced by main(), and tsn_setup_or_halt().
|
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.
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().
|
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).
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().
|
static |
Run one cycle: check the time base, program TAS + CBS, read status.
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().
|
static |
Core bring-up: CGC -> MSTP -> TIME -> console + LED.
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().
|
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.
| [in] | index | TAS RAM entry address to read. |
| [in] | want | The entry that was programmed at that address. |
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().
|
static |
Serialise an unsigned 32-bit value into decimal ASCII.
| [out] | buf | Destination, at least k_tsn_dec_u32_max bytes. |
| [in] | val | Value to serialise. |
Definition at line 186 of file main.c.
References k_tsn_dec_u32_max, and k_tsn_radix.
Referenced by tsn_write_u32().
|
static |
Write a byte span to the SCI8 console, discarding the status.
| [in] | data | Non-NULL byte span to transmit. |
| [in] | len | Byte count (0 is a no-op). |
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().
|
static |
Log one unsigned 32-bit value as decimal ASCII.
| [in] | val | Value to print. |
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().
|
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".
| [in] | val | Value to print. |
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().
|
static |
Definition at line 136 of file main.c.
Referenced by tsn_check_time_base().
|
static |
Definition at line 137 of file main.c.
Referenced by tsn_check_time_base().
|
static |
Definition at line 134 of file main.c.
Referenced by tsn_program_cbs().
|
static |
Definition at line 133 of file main.c.
Referenced by tsn_program_cbs().
|
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().
|
static |
Definition at line 135 of file main.c.
Referenced by tsn_log_status().
|
static |
Definition at line 132 of file main.c.
Referenced by tsn_program_tas().
|
static |