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

Non-Secure main entry point: launches ThreadX and the e-reader UI. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_err.h"
#include "ra8_nsc.h"
#include "ra8_wdt_supervisor.h"
#include "tx_api.h"
Include dependency graph for ns_main.c:

Go to the source code of this file.

Typedefs

typedef void(* ns_exc_handler_t) (void)

Enumerations

enum  ns_scb_addr_t : uintptr_t { k_ns_scb_vtor_addr = 0xE000ED08U }
 Address of NS VTOR register. More...
enum  ns_thread_stack_t : uint32_t {
  k_ns_ui_thread_stack_size = 4096U ,
  k_ns_sys_thread_stack_size = 2048U
}
 Stack sizes for Non-Secure ThreadX threads. More...
enum  ns_log_cadence_t : uint32_t {
  k_ns_ui_heartbeat_frames = 60U ,
  k_ns_sys_heartbeat_iters = 10U
}
 Heartbeat-log cadence per thread (iterations between log lines). More...
enum  ns_thread_sleep_t : uint32_t {
  k_ns_ui_frame_ticks = 16U ,
  k_ns_sys_poll_ticks = 100U
}
 Per-thread loop sleep period, in ThreadX ticks. More...
enum  ns_thread_prio_t : uint32_t {
  k_ns_ui_priority = 10U ,
  k_ns_sys_priority = 15U
}
 ThreadX priority + preemption threshold for each Non-Secure thread. More...
enum  ns_wdt_param_t : uint32_t {
  k_ns_wdt_sup_stack_size = 1024U ,
  k_ns_wdt_ui_deadline_ms = 500U ,
  k_ns_wdt_sys_deadline_ms = 1000U ,
  k_ns_wdt_refresh_ms = 50U
}
 Watchdog-supervisor sizing and timing parameters. More...
enum  ns_wdt_prio_t : uint32_t { k_ns_wdt_sup_priority = 14U }
 ThreadX priority for the watchdog supervisor thread. More...

Functions

void PendSV_Handler (void)
 Perform the ThreadX Non-Secure context switch requested by PendSV.
void _tx_timer_interrupt (void)
 Advance the ThreadX kernel timer by one hardware tick.
static void internal_systick_handler (void)
 SysTick exception handler for the Non-Secure ThreadX OS.
static void internal_panic_halt (void)
 Park the CPU in an idle loop if a fatal startup error occurs.
static void internal_ui_thread_entry (ULONG thread_input)
 UI thread entry: runs the e-reader UI frame loop.
static void internal_sys_thread_entry (ULONG thread_input)
 System supervisor and storage background thread.
static void internal_wdt_setup (void)
 Arm the watchdog and start the ThreadX check-in supervisor.
void tx_application_define (void *first_unused_memory)
 Setup ThreadX threads and resources.
void ns_reset_handler (void)
 Non-Secure Reset handler: entered via Secure-to-NS transition.
static void internal_nmi_halt (void)
 Default Non-Secure fault/NMI handler: park the CPU in a wfi halt.

Variables

uint32_t g_ra8_ls_ns_bss_start
uint32_t g_ra8_ls_ns_bss_end
uint32_t g_ra8_ls_ns_stack_top
uint32_t g_ra8_ls_ns_run_start
static TX_THREAD s_ui_thread
static TX_THREAD s_sys_thread
static uint8_t s_ui_thread_stack [k_ns_ui_thread_stack_size]
static uint8_t s_sys_thread_stack [k_ns_sys_thread_stack_size]
static uint8_t s_sup_stack [k_ns_wdt_sup_stack_size]
 Supervisor thread stack (caller-owned, 8-byte aligned for ThreadX).
static uint8_t s_ui_wdt_handle = (uint8_t)k_ra8_wdt_sup_handle_invalid
 Supervisor check-in handle for the UI thread.
static uint8_t s_sys_wdt_handle = (uint8_t)k_ra8_wdt_sup_handle_invalid
 Supervisor check-in handle for the system thread.
volatile uint32_t g_ns_ui_frames = 0U
 HIL liveness probe: UI-thread iteration count.
volatile uint32_t g_ns_sys_ticks = 0U
 HIL liveness probe: system-thread iteration count.
volatile uint32_t g_ra8_threadx_systick_ready
 0 until _tx_initialize_low_level has armed ThreadX's SysTick + timer state; 1 afterwards.
const ns_exc_handler_t g_ra8_ns_vector_table [16]

Detailed Description

Non-Secure main entry point: launches ThreadX and the e-reader UI.

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

This file is executed after the Secure world bootloader configures the SAU and jumps to ns_reset_handler. It operates entirely in Non-Secure state, leveraging ThreadX for multitasking and calling Secure services via NSC veneers.

A ThreadX watchdog supervisor guards the workers: at start-up it arms the Secure-owned WDT through the ra8_nsc_wdt_start veneer, then refreshes it (through ra8_nsc_wdt_refresh) only while every worker thread keeps checking in within its deadline. If any thread wedges the supervisor stops kicking the WDT and it underflows. Expiry is routed to NMI in this build, so a wedge halts the system deterministically (context preserved for a debugger) instead of hanging silently; routing expiry to an internal reset for automatic reboot is a separate product decision.

Since
0.1.0

Definition in file ns_main.c.

Typedef Documentation

◆ ns_exc_handler_t

typedef void(* ns_exc_handler_t) (void)

Definition at line 475 of file ns_main.c.

Enumeration Type Documentation

◆ ns_log_cadence_t

enum ns_log_cadence_t : uint32_t

Heartbeat-log cadence per thread (iterations between log lines).

Each thread logs a startup line once, then a periodic heartbeat so the serial / SWO log shows the system is alive without flooding it. The UI thread sleeps ~16 ms (~60 FPS) and the system thread ~100 ticks, so both cadences land near a one-second heartbeat.

Since
0.1.0
Enumerator
k_ns_ui_heartbeat_frames 

UI heartbeat every ~60 frames (~1 s).

k_ns_sys_heartbeat_iters 

System heartbeat every ~10 loops (~1 s).

Definition at line 81 of file ns_main.c.

◆ ns_scb_addr_t

enum ns_scb_addr_t : uintptr_t

Address of NS VTOR register.

Enumerator
k_ns_scb_vtor_addr 

Ns scb vtor address.

Definition at line 52 of file ns_main.c.

◆ ns_thread_prio_t

enum ns_thread_prio_t : uint32_t

ThreadX priority + preemption threshold for each Non-Secure thread.

Lower numbers are higher priority. The UI thread runs ahead of the system thread so input/rendering stays responsive; each thread uses the same value for its priority and its preemption threshold.

Since
0.1.0
Enumerator
k_ns_ui_priority 

UI thread priority + preemption threshold.

k_ns_sys_priority 

System thread priority + preemption threshold.

Definition at line 107 of file ns_main.c.

◆ ns_thread_sleep_t

enum ns_thread_sleep_t : uint32_t

Per-thread loop sleep period, in ThreadX ticks.

The UI thread sleeps ~16 ticks (~16 ms at a 1 kHz tick, ~60 FPS); the system thread sleeps ~100 ticks (~100 ms) since it only supervises. Every loop must sleep so the other threads get to run.

Since
0.1.0
Enumerator
k_ns_ui_frame_ticks 

UI loop sleep (~16 ms, ~60 FPS).

k_ns_sys_poll_ticks 

System loop sleep (~100 ms cadence).

Definition at line 94 of file ns_main.c.

◆ ns_thread_stack_t

enum ns_thread_stack_t : uint32_t

Stack sizes for Non-Secure ThreadX threads.

Since
0.1.0
Enumerator
k_ns_ui_thread_stack_size 

Stack size for UI thread.

k_ns_sys_thread_stack_size 

Stack size for System thread.

Definition at line 61 of file ns_main.c.

◆ ns_wdt_param_t

enum ns_wdt_param_t : uint32_t

Watchdog-supervisor sizing and timing parameters.

The supervisor refreshes the WDT every k_ns_wdt_refresh_ms only if both workers have checked in within their deadlines. The deadlines are generous multiples of each worker's loop period (UI ~16 ms, SYS ~100 ms) so ordinary slow work (a book load, an SD read) never false -trips the reset, while a genuine wedge is caught within the deadline.

Invariant
Each deadline exceeds its worker's loop period by a wide margin.
Since
0.1.0
Enumerator
k_ns_wdt_sup_stack_size 

Supervisor thread stack size (bytes).

k_ns_wdt_ui_deadline_ms 

UI worker check-in deadline (ms).

k_ns_wdt_sys_deadline_ms 

System worker check-in deadline (ms).

k_ns_wdt_refresh_ms 

Supervisor refresh / poll cadence (ms).

Definition at line 123 of file ns_main.c.

◆ ns_wdt_prio_t

enum ns_wdt_prio_t : uint32_t

ThreadX priority for the watchdog supervisor thread.

Sits between the UI (k_ns_ui_priority) and system (k_ns_sys_priority) workers: high enough to preempt the background system thread and refresh on time, low enough not to starve the UI.

Since
0.1.0
Enumerator
k_ns_wdt_sup_priority 

Supervisor thread priority.

Definition at line 138 of file ns_main.c.

Function Documentation

◆ _tx_timer_interrupt()

void _tx_timer_interrupt ( void )
extern

Advance the ThreadX kernel timer by one hardware tick.

The ThreadX Cortex-M port supplies this timer ISR worker. The local SysTick handler calls it only after the kernel readiness flag is set, allowing ThreadX delays, timers, and timed waits to advance.

Precondition
ThreadX low-level initialisation has completed.
Called once for the SysTick event being serviced.
Postcondition
The ThreadX system clock has advanced by one tick.
Any timeout made ready by that tick is visible to the scheduler.
Note
Runs in Non-Secure handler mode and is not re-entrant.
Since
0.1.0

References g_ra8_threadx_systick_ready.

Referenced by internal_systick_handler(), and ns_systick_handler().

◆ internal_nmi_halt()

void internal_nmi_halt ( void )
static

Default Non-Secure fault/NMI handler: park the CPU in a wfi halt.

Installed on the NMI, HardFault, and the other unhandled Non-Secure exception vectors. There is no recovery path, so it spins in a wfi loop and leaves the faulting context intact for a debugger.

Returns
Nothing (noreturn; control never leaves the halt loop).
Note
This function does not return.
Precondition
Reached only via a Non-Secure exception vector.
Recovery, if any, is the debugger's or watchdog's responsibility.
Postcondition
The CPU is parked in a wfi loop and runs no further NS code.
The faulting context is left unmodified for inspection.
Note
Runs in NS exception context.
Since
0.1.0

Definition at line 491 of file ns_main.c.

References RA8_INTERNAL.

◆ internal_panic_halt()

void internal_panic_halt ( void )
static

Park the CPU in an idle loop if a fatal startup error occurs.

Spins forever issuing wfi so a Non-Secure bring-up failure halts deterministically (low power) instead of executing undefined state. Recovery requires an external reset.

Returns
Does not return (noreturn).
Note
The function never returns to its caller.
Precondition
Called only on an unrecoverable NS startup error.
Interrupts that could resume normal flow are not relied upon.
Postcondition
The core remains parked in a low-power wait loop until reset.
No further application code executes.
Note
Not thread-safe; terminal error path only.
Since
0.1.0

Definition at line 239 of file ns_main.c.

References RA8_INTERNAL.

Referenced by internal_wdt_setup(), ns_reset_handler(), and tx_application_define().

◆ internal_sys_thread_entry()

void internal_sys_thread_entry ( ULONG thread_input)
static

System supervisor and storage background thread.

Lower-priority background worker for long-running, non-UI duties – SD card / filesystem setup, input polling, battery status, and OTA state. It runs an infinite supervisor loop, emitting a periodic heartbeat and sleeping each iteration so the UI thread stays responsive. It never returns.

Parameters
[in]thread_inputThreadX entry argument (unused; reserved by the API).
Returns
Nothing (runs for the lifetime of the system).
Precondition
Registered as the system thread's entry in tx_application_define.
ThreadX is running (the scheduler invoked this entry).
Postcondition
The supervisor loop runs continuously, yielding each iteration.
Heartbeat log lines are emitted on the configured cadence.
Note
Runs on the NS system thread; not thread-safe across threads.
Since
0.1.0

Definition at line 296 of file ns_main.c.

References g_ns_sys_ticks, k_ns_sys_heartbeat_iters, k_ns_sys_poll_ticks, RA8_INTERNAL, ra8_nsc_log_emit(), ra8_wdt_supervisor_checkin(), s_sys_wdt_handle, and tx_thread_sleep.

Referenced by tx_application_define().

◆ internal_systick_handler()

void internal_systick_handler ( void )
static

SysTick exception handler for the Non-Secure ThreadX OS.

Drives the ThreadX timer: once the kernel is up (g_ra8_threadx_systick_ready set), each SysTick forwards into _tx_timer_interrupt to service timeouts and the time-slice. Before the kernel is ready the tick is ignored so an early SysTick cannot enter the scheduler.

Returns
Nothing.
Precondition
Installed as the SysTick vector in the NS vector table.
g_ra8_threadx_systick_ready is set only after tx_kernel_enter.
Postcondition
When the kernel is ready, one ThreadX timer tick has been serviced.
When the kernel is not ready, no scheduler state is touched.
Note
Runs in NS handler mode; not callable from thread context.
Since
0.1.0

Definition at line 218 of file ns_main.c.

References _tx_timer_interrupt(), g_ra8_threadx_systick_ready, and RA8_INTERNAL.

◆ internal_ui_thread_entry()

void internal_ui_thread_entry ( ULONG thread_input)
static

UI thread entry: runs the e-reader UI frame loop.

The Non-Secure UI thread. By the time ThreadX schedules it the Secure substrate, the TrustZone boundary, and logging (SCI8) are all up, so it drives the frame loop for the lifetime of the system: each iteration advances the frame counter, emits a heartbeat on the configured cadence, and yields so the other threads run. Never returns.

Parameters
[in]thread_inputThreadX entry argument (unused; reserved by the API).
Returns
Nothing (runs for the lifetime of the system).
Precondition
Registered as the UI thread's entry in tx_application_define.
ra8_nsc_periph_init has completed (Secure services available).
Postcondition
The UI loop runs continuously, yielding each iteration.
Heartbeat log lines are emitted on the configured cadence.
Note
Runs on the NS UI thread; not thread-safe across threads.
Since
0.1.0

Definition at line 262 of file ns_main.c.

References g_ns_ui_frames, k_ns_ui_frame_ticks, k_ns_ui_heartbeat_frames, RA8_INTERNAL, ra8_nsc_log_emit(), ra8_wdt_supervisor_checkin(), s_ui_wdt_handle, and tx_thread_sleep.

Referenced by tx_application_define().

◆ internal_wdt_setup()

void internal_wdt_setup ( void )
static

Arm the watchdog and start the ThreadX check-in supervisor.

Runs once from tx_application_define, before the workers are created, and in this exact order: arm the Secure WDT via the ra8_nsc_wdt_start veneer; initialise the supervisor with a caller-owned stack; redirect its refresh hook to the ra8_nsc_wdt_refresh veneer (the library default would call the WDT directly, which faults in NS); register the UI and system workers with their deadlines; then start the supervisor thread. Any failure is unrecoverable this early, so it parks in internal_panic_halt.

Returns
Nothing.
Note
Returns only on full success; otherwise never returns (halts).
Precondition
ra8_nsc_periph_init has completed (Secure clocks + substrate up).
Called in single-threaded boot context before any worker is created.
Postcondition
The WDT is armed and the supervisor thread is running.
s_ui_wdt_handle and s_sys_wdt_handle hold valid registry handles.
Note
Not thread-safe; boot-time only.
Since
0.1.0

Definition at line 333 of file ns_main.c.

References internal_panic_halt(), k_ns_wdt_refresh_ms, k_ns_wdt_sup_priority, k_ns_wdt_sup_stack_size, k_ns_wdt_sys_deadline_ms, k_ns_wdt_ui_deadline_ms, k_ra8_ok, RA8_INTERNAL, ra8_nsc_wdt_refresh(), ra8_nsc_wdt_start(), ra8_wdt_supervisor_init(), ra8_wdt_supervisor_register_thread(), ra8_wdt_supervisor_set_refresh_hook(), ra8_wdt_supervisor_start(), s_sup_stack, s_sys_wdt_handle, and s_ui_wdt_handle.

Referenced by tx_application_define().

◆ ns_reset_handler()

void ns_reset_handler ( void )

Non-Secure Reset handler: entered via Secure-to-NS transition.

Slot 1 of the NS vector table and the NS image's linker entry symbol; the Secure boot BLXNS-es here. No header declares it because the only callers are the hardware vector fetch and the linker – the prototype below satisfies -Wmissing-prototypes for this externally-linked boot symbol.

Precondition
The Secure boot copied/armed the NS image and programmed VTOR_NS.
Executes in NS Thread mode with MSP_NS from vector slot 0.
Postcondition
.bss (and, under XIP, .data) is initialised; ThreadX never returns.
Interrupt state is whatever tx_kernel_enter establishes.
Note
Not thread-safe; single-threaded NS boot only.
Since
0.1.0

Definition at line 431 of file ns_main.c.

References g_ra8_ls_ns_bss_end, g_ra8_ls_ns_bss_start, g_ra8_ls_ns_run_start, internal_panic_halt(), k_ns_scb_vtor_addr, k_ra8_ok, ra8_nsc_log_emit(), and ra8_nsc_periph_init().

◆ PendSV_Handler()

void PendSV_Handler ( void )
extern

Perform the ThreadX Non-Secure context switch requested by PendSV.

The ThreadX Cortex-M port supplies this exception entry point. The Non-Secure vector table references it directly so a pending context switch saves the outgoing thread and restores the scheduler-selected thread before exception return.

Precondition
PendSV was entered in Non-Secure handler mode.
ThreadX has initialised the scheduler and thread contexts.
Postcondition
The pending context-switch request has been serviced.
The scheduler-selected thread context is active for exception return.
Note
Exception-context entry point supplied by ThreadX; not thread-callable.
Since
0.1.0

◆ tx_application_define()

Variable Documentation

◆ g_ns_sys_ticks

volatile uint32_t g_ns_sys_ticks = 0U

HIL liveness probe: system-thread iteration count.

Bumped once per system-thread poll; see g_ns_ui_frames. A frozen value means the system thread wedged. Diagnostic only.

Note
Written by the system thread; read externally by the bench.
Since
0.1.0

Definition at line 169 of file ns_main.c.

Referenced by internal_sys_thread_entry().

◆ g_ns_ui_frames

volatile uint32_t g_ns_ui_frames = 0U

HIL liveness probe: UI-thread iteration count.

Bumped once per UI frame. Read via J-Link (NS SRAM survives a connect) to confirm the NS world is alive and the watchdog supervisor is being fed – a frozen value means the UI thread wedged (and the WDT would then stop being refreshed). Diagnostic only.

Note
Written by the UI thread; read externally by the bench.
Since
0.1.0

Definition at line 160 of file ns_main.c.

Referenced by internal_ui_thread_entry().

◆ g_ra8_ls_ns_bss_end

uint32_t g_ra8_ls_ns_bss_end
extern

◆ g_ra8_ls_ns_bss_start

uint32_t g_ra8_ls_ns_bss_start
extern

◆ g_ra8_ls_ns_run_start

uint32_t g_ra8_ls_ns_run_start
extern

◆ g_ra8_ls_ns_stack_top

uint32_t g_ra8_ls_ns_stack_top
extern

◆ g_ra8_ns_vector_table

const ns_exc_handler_t g_ra8_ns_vector_table[16]
Initial value:
= {
0,
0,
0,
0,
}
static void internal_nmi_halt(void)
Default Non-Secure fault/NMI handler: park the CPU in a wfi halt.
Definition ns_main.c:491
static void internal_systick_handler(void)
SysTick exception handler for the Non-Secure ThreadX OS.
Definition ns_main.c:218
uint32_t g_ra8_ls_ns_stack_top
void ns_reset_handler(void)
Definition ns_main.c:384
void(* ns_exc_handler_t)(void)
Function-pointer type for entries in the NS vector table.
Definition ns_main.c:337
void PendSV_Handler(void)

Definition at line 498 of file ns_main.c.

◆ g_ra8_threadx_systick_ready

volatile uint32_t g_ra8_threadx_systick_ready
extern

0 until _tx_initialize_low_level has armed ThreadX's SysTick + timer state; 1 afterwards.

Set by the kernel once tx_initialize_low_level has run.

Read by the shared SysTick handler in libs/ra8_core/src/ra8_time.c.

Note
Single-writer (assembly, once); multi-reader (every SysTick).
Since
0.1.0

Definition at line 58 of file tx_systick_ready.c.

◆ s_sup_stack

uint8_t s_sup_stack[k_ns_wdt_sup_stack_size]
static

Supervisor thread stack (caller-owned, 8-byte aligned for ThreadX).

Definition at line 143 of file ns_main.c.

◆ s_sys_thread

TX_THREAD s_sys_thread
static

Definition at line 67 of file ns_main.c.

Referenced by tx_application_define().

◆ s_sys_thread_stack

uint8_t s_sys_thread_stack[k_ns_sys_thread_stack_size]
static

Definition at line 70 of file ns_main.c.

Referenced by tx_application_define().

◆ s_sys_wdt_handle

uint8_t s_sys_wdt_handle = (uint8_t)k_ra8_wdt_sup_handle_invalid
static

Supervisor check-in handle for the system thread.

Definition at line 148 of file ns_main.c.

Referenced by internal_sys_thread_entry(), and internal_wdt_setup().

◆ s_ui_thread

TX_THREAD s_ui_thread
static

Definition at line 66 of file ns_main.c.

◆ s_ui_thread_stack

uint8_t s_ui_thread_stack[k_ns_ui_thread_stack_size]
static

Definition at line 69 of file ns_main.c.

◆ s_ui_wdt_handle

uint8_t s_ui_wdt_handle = (uint8_t)k_ra8_wdt_sup_handle_invalid
static

Supervisor check-in handle for the UI thread.

Definition at line 146 of file ns_main.c.

Referenced by internal_ui_thread_entry(), and internal_wdt_setup().