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

Bring the RA8D2 + ThreadX esp-hosted port up against the ESP32-C6. More...

#include <stdint.h>
#include "c6_hosted.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_esp_hosted_port.h"
#include "ra8_isr.h"
#include "ra8_mstp.h"
#include "ra8_time.h"
#include "tx_api.h"
Include dependency graph for main.c:

Go to the source code of this file.

Functions

static void c6_hosted_panic_halt (void)
 Park the CPU forever after an unrecoverable bring-up failure.
static void c6_hosted_setup_or_halt (void)
 Bring clocks, module-stop state, SysTick and the console up.
static void c6_hosted_heartbeat (void)
 Print heartbeat lines forever, never returning.
static void c6_hosted_worker_entry (ULONG thread_input)
 Worker thread: report the init, exercise the link, then heartbeat.
void tx_application_define (void *first_unused_memory)
 ThreadX define hook: bring the port up and start the worker.
void main (void)
 Application entry: clocks, console, banner, then ThreadX.

Variables

static uint32_t s_c6_hosted_cpuclk_hz
 Cached CPUCLK0 rate, used to programme SysTick.
static uint32_t s_c6_hosted_pclka_hz
 Cached PCLKA rate, the SCI baud-clock source the port divides.
static ra8_err_t s_c6_hosted_init_err = k_ra8_err_not_initialized
 Exact result of ra8_esp_hosted_port_init.
static TX_THREAD s_c6_hosted_worker
 Control block of the single application thread.
static CHAR s_c6_hosted_worker_name [] = "c6_hosted_init"
 Thread name handed to ThreadX.
static UCHAR s_c6_hosted_worker_stack [k_c6_hosted_worker_stack]
 Stack backing s_c6_hosted_worker.

Detailed Description

Bring the RA8D2 + ThreadX esp-hosted port up against the ESP32-C6.

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

First application to consume port/esp-hosted/ – the first-party RA8D2 + ThreadX port of the vendored esp-hosted host driver. It is the port's buildable consumer and its bring-up harness: it initialises the port, states the pin map and interrupt routing the port resolved, reads both side-band lines through the OS-abstraction vtable, clocks exactly one full-duplex transaction, decodes the frame the co-processor returned and prints one PASS/FAIL verdict line.

This file holds the bring-up sequence only; the reporting, the console formatters and the frame work live in src/ behind c6_hosted.h.

Flow
  1. ra8_cgc_init – CPUCLK0 and PCLKA – then ra8_mstp_init, SysTick and the board console. Any failure panic-halts.
  2. Banner: port identity, clocks, SPI parameters, the resolved pin map, and which side-band pin takes the ICU edge path versus the port's software edge detector.
  3. tx_kernel_enter. The port creates ThreadX byte pools, mutexes and timers, so ra8_esp_hosted_port_init runs from tx_application_define – the context where ThreadX permits object creation – and the worker thread reports what it returned.
  4. Worker: sample both side-band lines, run one transaction, dump pool occupancy, then heartbeat forever.
Runtime status – proven on silicon 2026-07-28
This application is the first thing built on port/esp-hosted/ to have run on the board. The port comes up, the vtable samples both side-band lines, and a 5 MHz transaction returns the co-processor's idle filler frame with the transfer reporting RET_OK. just hil::c6 re-runs it against the app's own hil.conf.

The pin map comes from the probe examples/ek_ra8d2/hw_validated/c6/c6_spi_probe, which scope-qualified every J26 hole on 2026-07-27 at SPI mode 3 / 1 MHz with zero bad checksums.

That first run also found a defect in this application rather than in the port: its verdict demanded a payload-header offset of twelve from a frame that legitimately carries zero, so it reported FAIL at a healthy link. The idle filler is now a pass in its own right – see src/c6_hosted_frame.c.

Since
0.1.0

Definition in file main.c.

Function Documentation

◆ c6_hosted_heartbeat()

void c6_hosted_heartbeat ( void )
static

Print heartbeat lines forever, never returning.

Returns
Never returns.
Precondition
The console is up and ThreadX is scheduling.
The caller has finished every one-shot bring-up step.
Postcondition
A line is emitted every k_c6_hosted_heartbeat_ms milliseconds.
No application state is modified beyond the local beat counter.
Note
This is the one deliberately unbounded loop in the application. It exists so a bench with no scope can still see whether the co-processor ever raises a side-band line.
Since
0.1.0

Definition at line 200 of file main.c.

References c6_hosted_event_count(), c6_hosted_put_u32(), c6_hosted_puts(), c6_hosted_report_sideband(), k_c6_hosted_heartbeat_ms, ra8_esp_hosted_port_is_ready(), and tx_thread_sleep.

Referenced by c6_hosted_worker_entry().

◆ c6_hosted_panic_halt()

void c6_hosted_panic_halt ( void )
static

Park the CPU forever after an unrecoverable bring-up failure.

Returns
Never returns.
Precondition
A bring-up step has failed and the application cannot proceed.
The failure was already reported if the console was up.
Postcondition
The CPU is parked in a wait-for-interrupt loop.
No further application state changes.
Note
Never returns; not callable from interrupt context.
Since
0.1.0

Definition at line 146 of file main.c.

Referenced by c6_hosted_setup_or_halt(), and main().

◆ c6_hosted_setup_or_halt()

void c6_hosted_setup_or_halt ( void )
static

Bring clocks, module-stop state, SysTick and the console up.

Returns
Nothing; panic-halts instead of returning on any failure.
Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has completed and the console SCI is unclaimed.
Postcondition
s_c6_hosted_cpuclk_hz and s_c6_hosted_pclka_hz are non-zero and the console transmits at k_c6_hosted_uart_baud, 8N1.
SysTick runs and every peripheral this app uses is out of module-stop.
Note
Never returns on error; a clock failure happens before the console exists, so it is visible only to a debugger.
Since
0.1.0

Definition at line 166 of file main.c.

References c6_hosted_panic_halt(), k_c6_hosted_uart_baud, k_ra8_clock_id_cpuclk0, k_ra8_clock_id_pclka, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_mstp_init(), ra8_time_init(), s_c6_hosted_cpuclk_hz, and s_c6_hosted_pclka_hz.

Referenced by main().

◆ c6_hosted_worker_entry()

void c6_hosted_worker_entry ( ULONG thread_input)
static

Worker thread: report the init, exercise the link, then heartbeat.

Parameters
[in]thread_inputThreadX entry argument; unused.
Returns
Never returns.
Precondition
tx_application_define has recorded s_c6_hosted_init_err.
The console is up.
Postcondition
On a successful init exactly one transaction ran and one verdict was printed.
On a failed init no transaction ran and the error was named.
Note
The failure path deliberately does not continue: a port that did not come up has an unpopulated vtable, and calling through it would fault rather than report.
Since
0.1.0

Definition at line 233 of file main.c.

References c6_hosted_heartbeat(), c6_hosted_puts(), c6_hosted_report_sideband(), c6_hosted_run_transaction(), k_c6_hosted_boot_wait_ms, k_ra8_ok, ra8_delay_ms(), ra8_err_to_str(), ra8_esp_hosted_mem_dump(), and s_c6_hosted_init_err.

Referenced by tx_application_define().

◆ main()

void main ( void )

Application entry: clocks, console, banner, then ThreadX.

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, the FPU and the priority grouping.
Postcondition
The banner and the resolved pin map were printed exactly once.
Control passed to ThreadX and never came back.
Note
Everything after tx_kernel_enter happens on ThreadX; the panic-halt below is reached only if the kernel refuses to start.
Since
0.1.0

Definition at line 308 of file main.c.

References c6_hosted_panic_halt(), c6_hosted_print_banner(), c6_hosted_print_pin_map(), c6_hosted_puts(), c6_hosted_setup_or_halt(), ra8_isr_globals_enable(), s_c6_hosted_cpuclk_hz, and s_c6_hosted_pclka_hz.

◆ tx_application_define()

void tx_application_define ( void * first_unused_memory)

ThreadX define hook: bring the port up and start the worker.

Parameters
[in]first_unused_memoryFree RAM handed over by the ThreadX port; unused, every object here is static.
Returns
Nothing.
Precondition
tx_kernel_enter has been called and the clock cache is valid.
No vendored esp-hosted entry point has been called yet.
Postcondition
s_c6_hosted_init_err holds the exact port-init result.
Exactly one worker thread was created.
Note
The port creates ThreadX byte pools, mutexes and timers, so its init must run where ThreadX permits object creation – here, not from main.
Since
0.1.0

Definition at line 268 of file main.c.

References c6_hosted_on_event(), c6_hosted_puts(), c6_hosted_worker_entry(), k_c6_hosted_edge_poll_ms, k_c6_hosted_sck_hz, k_c6_hosted_worker_prio, k_ra8_board_pmod1_sci_channel, k_ra8_ok, ra8_esp_hosted_port_init(), ra8_esp_hosted_port_set_event_cb(), s_c6_hosted_init_err, s_c6_hosted_pclka_hz, s_c6_hosted_worker, s_c6_hosted_worker_name, s_c6_hosted_worker_stack, TX_AUTO_START, TX_NO_TIME_SLICE, TX_SUCCESS, and tx_thread_create.

Variable Documentation

◆ s_c6_hosted_cpuclk_hz

uint32_t s_c6_hosted_cpuclk_hz
static

Cached CPUCLK0 rate, used to programme SysTick.

Read once during bring-up, before ThreadX starts.

Note
Single-threaded; written once from main.
Warning
Zero until c6_hosted_setup_or_halt has run.
Since
0.1.0

Definition at line 76 of file main.c.

Referenced by c6_hosted_setup_or_halt(), and main().

◆ s_c6_hosted_init_err

ra8_err_t s_c6_hosted_init_err = k_ra8_err_not_initialized
static

Exact result of ra8_esp_hosted_port_init.

Recorded in tx_application_define and reported verbatim by the worker, which is the first context that can print after the init.

Note
Written once before the scheduler starts, read afterwards.
Warning
A non-k_ra8_ok value stops the transaction; the application never continues as though the port had come up.
Since
0.1.0

Definition at line 100 of file main.c.

Referenced by c6_hosted_worker_entry(), and tx_application_define().

◆ s_c6_hosted_pclka_hz

uint32_t s_c6_hosted_pclka_hz
static

Cached PCLKA rate, the SCI baud-clock source the port divides.

Handed to the port as ra8_esp_hosted_port_cfg_t::pclk_hz; a stale value silently mis-programs the SPI bit rate, so it is read from the CGC rather than assumed.

Note
Single-threaded; written once from main.
Warning
Zero until c6_hosted_setup_or_halt has run.
Since
0.1.0

Definition at line 88 of file main.c.

Referenced by c6_hosted_setup_or_halt(), main(), and tx_application_define().

◆ s_c6_hosted_worker

TX_THREAD s_c6_hosted_worker
static

Control block of the single application thread.

ThreadX requires statically allocated control blocks, as does NASA Power of 10 Rule 3.

Note
Owned by ThreadX once tx_thread_create succeeds.
Warning
Never reused for a second thread.
Since
0.1.0

Definition at line 111 of file main.c.

Referenced by tx_application_define().

◆ s_c6_hosted_worker_name

CHAR s_c6_hosted_worker_name[] = "c6_hosted_init"
static

Thread name handed to ThreadX.

A mutable array rather than a string literal: ThreadX takes a non-const CHAR*, and casting the qualifier away would trip the project's -Wcast-qual.

Note
Read by ThreadX for as long as the thread exists.
Warning
Never modified after creation; ThreadX keeps the pointer.
Since
0.1.0

Definition at line 123 of file main.c.

Referenced by tx_application_define().

◆ s_c6_hosted_worker_stack

UCHAR s_c6_hosted_worker_stack[k_c6_hosted_worker_stack]
static

Stack backing s_c6_hosted_worker.

Sized by k_c6_hosted_worker_stack; the deepest call the worker makes is a formatter with a small on-stack digit array.

Note
Written only by ThreadX and the worker itself.
Warning
Shrinking this without re-measuring risks a silent overflow.
Since
0.1.0

Definition at line 134 of file main.c.

Referenced by tx_application_define().