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 ESP32-C6's Wi-Fi station up through the ra8_c6link facade. More...

#include <stdint.h>
#include "c6_wifi.h"
#include "esp_hosted_host_fw_ver.h"
#include "esp_hosted_transport.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_c6link.h"
#include "ra8_c6link_wifi.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_esp_hosted_c6link.h"
#include "ra8_esp_hosted_port.h"
#include "ra8_isr.h"
#include "ra8_mstp.h"
#include "ra8_time.h"
#include "transport_drv.h"
#include "tx_api.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  c6_wifi_expect_t : uint32_t {
  k_c6_wifi_expect_chip = (uint32_t)ESP_PRIV_FIRMWARE_CHIP_ESP32C6 ,
  k_c6_wifi_drain_polls = 8U
}
 What a passing run must observe from the co-processor. More...

Functions

static void c6_wifi_panic_halt (void)
 Park the CPU forever after an unrecoverable bring-up failure.
static void c6_wifi_setup_or_halt (void)
 Bring clocks, module-stop state, SysTick and the console up.
static void c6_wifi_on_event (void *ctx, const ra8_c6link_event_t *ev)
 Narrate one announcement the co-processor volunteered.
static void c6_wifi_report_fault (const char *what, ra8_err_t err)
 Print the co-processor's own error code for the last failed request.
static bool c6_wifi_phase_identity (const ra8_c6link_fw_version_t *fw_in)
 Check the identity the readiness probe already brought back.
static bool c6_wifi_phase_station (void)
 Start the station, read its address, then stop it again.
static ra8_err_t c6_wifi_open_link (void)
 Open the link over the port's transport seam.
static void c6_wifi_heartbeat (bool passed)
 Print a liveness line forever, never returning.
static bool c6_wifi_phase_ready (ra8_c6link_fw_version_t *out)
 Open the link and prove the co-processor is answering.
static void c6_wifi_worker_entry (ULONG thread_input)
 Worker thread: open the link, run both phases, judge, 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_wifi_cpuclk_hz
 Cached CPUCLK0 rate, used to programme SysTick.
static uint32_t s_c6_wifi_pclka_hz
 Cached PCLKA rate, the SCI baud-clock source the port divides.
static ra8_err_t s_c6_wifi_init_err = k_ra8_err_not_initialized
 Exact result of ra8_esp_hosted_port_init.
static TX_THREAD s_c6_wifi_worker
 Control block of the single application thread.
static CHAR s_c6_wifi_worker_name [] = "c6_wifi_link"
 Thread name handed to ThreadX.
static UCHAR s_c6_wifi_worker_stack [k_c6_wifi_worker_stack]
 Stack backing s_c6_wifi_worker.
static uint8_t s_c6_wifi_arena [k_c6_wifi_arena_bytes]
 Decode arena the facade hands to the generated protobuf codec.
static ra8_c6link_t s_c6_wifi_link
 The one link this application drives.
static uint32_t s_c6_wifi_events
 Count of announcements the co-processor volunteered.

Detailed Description

Bring the ESP32-C6's Wi-Fi station up through the ra8_c6link facade.

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

The third application on port/esp-hosted/, and the first that uses libs/ra8_c6link rather than hand-building the protocol. c6_spi_probe established the physical link, c6_hosted_init established the framed transaction and c6_fw_version established one RPC round-trip. This one establishes the facade – and, with it, the only part of the control plane a host test cannot settle:

  1. bring the port up under ThreadX and bind its transport seam;
  2. announce this host and prove the co-processor is answering, by asking who it is rather than by waiting for a boot event the co-processor emits only when IT boots;
  3. check that answer against the vendored host driver's own version and against the ESP32-C6 chip id;
  4. start the Wi-Fi station – Req_WifiInit, Req_SetWifiMode, Req_WifiStart – and read the station's MAC address back;
  5. stop the station and print one PASS or FAIL line.
What only silicon can answer
Req_WifiInit carries twenty scalars that the co-processor's own esp_wifi_init() validates: a magic word, buffer counts, aggregation flags. A host test can prove this firmware encodes them; only the co-processor can say whether it accepts them. That is why this application exists and why it reports the co-processor's own esp_err_t on failure rather than a local verdict – the number in that field is what a fix would be based on.

No network is joined here. Association needs an AP in range and belongs to #492; this stops at "the radio is up and has an address", which is exactly the state an IP driver starts from.

Bench requirements
SW4 1=OFF 2=OFF 3=ON 4=OFF, the C6 harness on J26, and the C6 powered from its own USB. SW4-3 ON is what connects J26-1..J26-4 to the MCU at all; with it wrong the board and the co-processor both look healthy and the link simply does not exist.
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ c6_wifi_expect_t

enum c6_wifi_expect_t : uint32_t

What a passing run must observe from the co-processor.

The chip id is upstream's own enumerator, so a board carrying some other Espressif part fails here by name rather than by silence.

Invariant
k_c6_wifi_expect_chip is the ESP32-C6's firmware chip id.
k_c6_wifi_drain_polls is non-zero, so the post-start drain always clocks at least one transaction.
Example:
if (fw.chip_id != (uint32_t)k_c6_wifi_expect_chip) { fail(); }
See also
c6_wifi_phase_identity
Since
0.1.0
Enumerator
k_c6_wifi_expect_chip 

Firmware chip id the answering co-processor must report.

k_c6_wifi_drain_polls 

Transactions clocked after the station starts, so the Wi-Fi events the co-processor raises on its own are drained and reported rather than left queued behind the next request.

Definition at line 83 of file main.c.

Function Documentation

◆ c6_wifi_heartbeat()

void c6_wifi_heartbeat ( bool passed)
static

Print a liveness line forever, never returning.

Parameters
[in]passedVerdict the run reached, echoed on every beat.
Returns
Never returns.
Precondition
The console is up and ThreadX is scheduling.
The verdict has already been printed once.
Postcondition
A line is emitted every k_c6_wifi_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 console attached after the run still learns the verdict.
Since
0.1.0

Definition at line 398 of file main.c.

References c6_wifi_put_u32(), c6_wifi_puts(), k_c6_wifi_heartbeat_ms, and tx_thread_sleep.

Referenced by c6_wifi_worker_entry().

◆ c6_wifi_on_event()

void c6_wifi_on_event ( void * ctx,
const ra8_c6link_event_t * ev )
static

Narrate one announcement the co-processor volunteered.

Parameters
[in]ctxUnused; this application has one link.
[in]evThe decoded announcement; never null.
Returns
Nothing.
Precondition
The console is up.
ev is valid only for the duration of this call.
Postcondition
One line was emitted and the run's event count advanced.
Nothing was called back into the link.
Note
Runs inside ra8_c6link_poll, on the worker thread, with the transport in use – so it prints and returns and does nothing else.
Since
0.1.0

Definition at line 211 of file main.c.

References c6_wifi_put_i32(), c6_wifi_put_text(), c6_wifi_put_u32(), c6_wifi_puts(), ra8_c6link_event::kind, ra8_c6link_event::reason, s_c6_wifi_events, ra8_c6link_event::ssid, ra8_c6link_event::ssid_len, and ra8_c6link_event::wifi_event_id.

Referenced by c6_wifi_open_link().

◆ c6_wifi_open_link()

ra8_err_t c6_wifi_open_link ( void )
static

Open the link over the port's transport seam.

Returns
ra8_err_t Error code.
Return values
k_ra8_okThe link is open and ready to pump.
k_ra8_err_not_initializedThe port did not come up.
k_ra8_err_null_ptrThe seam came back incomplete.
k_ra8_err_invalid_sizeThe arena is smaller than the facade accepts.
Precondition
ra8_esp_hosted_port_init has succeeded.
The console is up, so a failure is reportable.
Postcondition
On success s_c6_wifi_link is open with both callbacks registered.
On failure the link is untouched.
Note
Split out of the worker so that function stays inside NASA Rule 4.
Since
0.1.0

Definition at line 372 of file main.c.

References ra8_c6link_cfg::arena, ra8_c6link_cfg::arena_bytes, c6_wifi_on_event(), ra8_c6link_cfg::cb_ctx, ra8_c6link_cfg::event_cb, k_ra8_ok, ra8_c6link_open(), ra8_esp_hosted_c6link_bind(), s_c6_wifi_arena, s_c6_wifi_link, and ra8_c6link_cfg::transport.

Referenced by c6_wifi_phase_ready().

◆ c6_wifi_panic_halt()

void c6_wifi_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 157 of file main.c.

Referenced by c6_wifi_setup_or_halt(), and main().

◆ c6_wifi_phase_identity()

bool c6_wifi_phase_identity ( const ra8_c6link_fw_version_t * fw_in)
static

Check the identity the readiness probe already brought back.

Parameters
[in]fw_inIdentity ra8_c6link_await_ready answered with; must be non-null. Copied to a local before use so the printing below reads the same whether the caller's record moves or not.
Returns
true when the version and chip id are the expected ones.
Return values
trueThe host/co-processor version lock holds.
falseA field did not match what this host was built against.
Precondition
The link is ready, so fw was populated by a real answer.
The console is up.
Postcondition
The identity, and any mismatch in it, is on the console.
No link state is modified; this phase clocks no transaction.
Note
The expectation is the vendored host driver's own version, so this is the version lock rather than a literal written twice.
Readiness already cost one identity exchange, so re-asking here would be a second round trip for an answer this host is holding.
Since
0.1.0

Definition at line 273 of file main.c.

References c6_wifi_put_hex(), c6_wifi_put_text(), c6_wifi_put_u32(), c6_wifi_puts(), ra8_c6link_fw_version::chip_id, k_c6_wifi_expect_chip, k_c6_wifi_hex_byte, ra8_c6link_fw_version::major, ra8_c6link_fw_version::minor, ra8_c6link_fw_version::patch, ra8_c6link_fw_version::target, and ra8_c6link_fw_version::target_len.

Referenced by c6_wifi_worker_entry().

◆ c6_wifi_phase_ready()

bool c6_wifi_phase_ready ( ra8_c6link_fw_version_t * out)
static

Open the link and prove the co-processor is answering.

Opening the handle only binds a transport; it clocks nothing and therefore says nothing about the far side. This phase follows it with ra8_c6link_await_ready, which announces this host and then asks the co-processor who it is. Deliberately not a wait for the boot event: that fires once when the CO-PROCESSOR boots, and the C6 has its own supply, so it does not reboot when this board is reset.

Parameters
[out]outReceives the identity the readiness probe answered with; must be non-null.
Returns
true when the link is open and the co-processor answered.
Return values
trueout holds a real answer; every later phase may proceed.
falseThe link would not open, or nothing answered. Fatal: nothing below this can work if the far side is silent.
Precondition
The port is up, so the transport seam can bind.
The console is up, so a failure is reportable.
Postcondition
Each outcome is on the console, with the fault detail on failure.
On success the link is open and usable.
Note
Not thread-safe; it pumps.
Since
0.1.0

Definition at line 431 of file main.c.

References c6_wifi_open_link(), c6_wifi_puts(), c6_wifi_report_fault(), k_ra8_c6link_announce_transfers, k_ra8_ok, ra8_c6link_await_ready(), ra8_err_to_str(), and s_c6_wifi_link.

Referenced by c6_wifi_worker_entry().

◆ c6_wifi_phase_station()

bool c6_wifi_phase_station ( void )
static

Start the station, read its address, then stop it again.

Returns
true when the radio started and reported a non-zero address.
Return values
trueThe co-processor accepted the whole start sequence.
falseA step was refused; the co-processor's own code is on the console.
Precondition
The link is open and the identity phase has passed.
The console is up.
Postcondition
The station was stopped whether or not the run succeeded, so the co-processor is not left with a radio nobody owns.
The address, or the reason there was none, is on the console.
Note
This is the phase no host test can stand in for: the twenty scalars Req_WifiInit carries are validated by the co-processor's own esp_wifi_init(), not by this side.
Since
0.1.0

Definition at line 325 of file main.c.

References c6_wifi_print_stats(), c6_wifi_put_mac(), c6_wifi_puts(), c6_wifi_report_fault(), k_c6_wifi_drain_polls, k_ra8_ok, ra8_c6link_poll(), ra8_c6link_wifi_mac(), ra8_c6link_wifi_start(), ra8_c6link_wifi_stop(), and s_c6_wifi_link.

Referenced by c6_wifi_worker_entry().

◆ c6_wifi_report_fault()

void c6_wifi_report_fault ( const char * what,
ra8_err_t err )
static

Print the co-processor's own error code for the last failed request.

Parameters
[in]whatShort name of the step that failed; must be non-null.
[in]errWhat the facade returned.
Returns
Nothing.
Precondition
The console is up.
A request has just failed on s_c6_wifi_link.
Postcondition
Exactly one line was emitted.
No application state is modified.
Note
The co-processor's esp_err_t is the actionable number here: an ESP_ERR_INVALID_ARG against Req_WifiInit names the transmitted configuration, not the link.
Since
0.1.0

Definition at line 240 of file main.c.

References c6_wifi_put_i32(), c6_wifi_put_u32(), c6_wifi_puts(), ra8_c6link_last_fault(), ra8_err_to_str(), ra8_c6link_fault::resp, ra8_c6link_fault::rpc_id, and s_c6_wifi_link.

Referenced by c6_wifi_phase_ready(), and c6_wifi_phase_station().

◆ c6_wifi_setup_or_halt()

void c6_wifi_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_wifi_cpuclk_hz and s_c6_wifi_pclka_hz are non-zero and the console transmits at k_c6_wifi_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 176 of file main.c.

References c6_wifi_panic_halt(), k_c6_wifi_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_wifi_cpuclk_hz, and s_c6_wifi_pclka_hz.

Referenced by main().

◆ c6_wifi_worker_entry()

void c6_wifi_worker_entry ( ULONG thread_input)
static

Worker thread: open the link, run both phases, judge, heartbeat.

Parameters
[in]thread_inputThreadX entry argument; unused.
Returns
Never returns.
Precondition
tx_application_define has recorded s_c6_wifi_init_err.
The console is up.
Postcondition
On a successful init both phases ran and exactly one verdict line was printed.
On a failed init no transaction was attempted 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 474 of file main.c.

References c6_wifi_heartbeat(), c6_wifi_phase_identity(), c6_wifi_phase_ready(), c6_wifi_phase_station(), c6_wifi_put_u32(), c6_wifi_puts(), k_c6_wifi_boot_wait_ms, k_ra8_ok, ra8_delay_ms(), ra8_err_to_str(), ra8_esp_hosted_mem_dump(), s_c6_wifi_events, and s_c6_wifi_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 was 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 561 of file main.c.

References c6_wifi_panic_halt(), c6_wifi_print_banner(), c6_wifi_puts(), c6_wifi_setup_or_halt(), ra8_isr_globals_enable(), s_c6_wifi_cpuclk_hz, and s_c6_wifi_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_wifi_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 525 of file main.c.

References c6_wifi_puts(), c6_wifi_worker_entry(), k_c6_wifi_edge_poll_ms, k_c6_wifi_sck_hz, k_c6_wifi_worker_prio, k_ra8_board_pmod1_sci_channel, ra8_esp_hosted_port_init(), s_c6_wifi_init_err, s_c6_wifi_pclka_hz, s_c6_wifi_worker, s_c6_wifi_worker_name, s_c6_wifi_worker_stack, TX_AUTO_START, TX_NO_TIME_SLICE, TX_SUCCESS, and tx_thread_create.

Variable Documentation

◆ s_c6_wifi_arena

uint8_t s_c6_wifi_arena[k_c6_wifi_arena_bytes]
static

Decode arena the facade hands to the generated protobuf codec.

Static because this image has no heap; the facade bump-allocates from it and empties it after every message, which is what keeps the whole control plane inside NASA Power of 10 Rule 3.

Note
Written only through the facade, from the worker thread.
Warning
Shrinking it below k_ra8_c6link_arena_min makes ra8_c6link_open refuse rather than fail later.
Since
0.1.0

Definition at line 130 of file main.c.

Referenced by c6_wifi_open_link().

◆ s_c6_wifi_cpuclk_hz

uint32_t s_c6_wifi_cpuclk_hz
static

Cached CPUCLK0 rate, used to programme SysTick.

Definition at line 93 of file main.c.

Referenced by c6_wifi_setup_or_halt(), and main().

◆ s_c6_wifi_events

uint32_t s_c6_wifi_events
static

Count of announcements the co-processor volunteered.

Printed with the verdict. A station that starts and says nothing is a different situation from one that starts and raises WIFI_EVENT_STA_START, and the difference matters to whoever debugs #492.

Note
Written only from the event callback, on the worker thread.
Warning
Not reset between phases; it is a run total.
Since
0.1.0

Definition at line 145 of file main.c.

Referenced by c6_wifi_on_event(), and c6_wifi_worker_entry().

◆ s_c6_wifi_init_err

ra8_err_t s_c6_wifi_init_err = k_ra8_err_not_initialized
static

Exact result of ra8_esp_hosted_port_init.

Definition at line 99 of file main.c.

Referenced by c6_wifi_worker_entry(), and tx_application_define().

◆ s_c6_wifi_link

ra8_c6link_t s_c6_wifi_link
static

The one link this application drives.

Definition at line 133 of file main.c.

Referenced by c6_wifi_open_link(), c6_wifi_phase_ready(), c6_wifi_phase_station(), and c6_wifi_report_fault().

◆ s_c6_wifi_pclka_hz

uint32_t s_c6_wifi_pclka_hz
static

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

Definition at line 96 of file main.c.

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

◆ s_c6_wifi_worker

TX_THREAD s_c6_wifi_worker
static

Control block of the single application thread.

Definition at line 102 of file main.c.

Referenced by tx_application_define().

◆ s_c6_wifi_worker_name

CHAR s_c6_wifi_worker_name[] = "c6_wifi_link"
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 114 of file main.c.

Referenced by tx_application_define().

◆ s_c6_wifi_worker_stack

UCHAR s_c6_wifi_worker_stack[k_c6_wifi_worker_stack]
static

Stack backing s_c6_wifi_worker.

Definition at line 117 of file main.c.

Referenced by tx_application_define().