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

ThreadX + LevelX wear-levelling demo for EK-RA8D2 OSPI flash. More...

#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_isr.h"
#include "ra8_time.h"
#include "lx_api.h"
#include "lx_nor_driver_ra8_xspi.h"
#include "tx_api.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  lx_log_pace_t : uint32_t { k_lx_log_every_n = 100U }
 Compile-time settings for the LevelX wear-levelling demo. More...
enum  demo_config_t : uint32_t {
  k_demo_baud = 115200U ,
  k_demo_thread_stack = 4096U ,
  k_demo_sector_index = 0U ,
  k_demo_burnin_writes = 10000U ,
  k_demo_tick_ms = 1000U ,
  k_demo_sector_bytes = 512U ,
  k_demo_radix_dec = 10U ,
  k_demo_u32_buf_size = 12U
}

Functions

static void demo_panic_halt (void)
 Halt forever in WFI, after draining the J-Link OB VCOM TX FIFO.
static void demo_setup_or_halt (void)
 Bring CGC + the J-Link OB VCOM console up.
static void demo_print (const char *s)
 Convenience wrapper to write a NUL-terminated string to the console.
static void demo_print_u32 (uint32_t value)
 Print an unsigned 32-bit integer in decimal to SCI8.
static void demo_print_stat (const char *label, ULONG value)
 Print one labelled ULONG LevelX statistic line over SCI8.
static void demo_lx_format_or_panic (void)
 Format + open the LevelX partition.
static UINT demo_heartbeat (uint32_t counter)
 Run one heartbeat: program counter into sector 0 + read back.
static void demo_print_wear_stats (void)
 Dump LevelX's wear-levelling statistics to SCI8.
static void demo_report_rw_once (uint32_t counter, uint32_t readback)
 Emit a one-shot HIL success banner after the first verified heartbeat.
static void demo_thread_entry (ULONG thread_input)
 ThreadX worker entry: format LevelX, run the heartbeat loop, dump stats.
void tx_application_define (void *first_unused_memory)
 ThreadX system-define hook: build the worker thread + LevelX core.
void main (void)
 Application entry.

Variables

static LX_NOR_FLASH s_nor_flash
static ULONG s_demo_sector_io [k_demo_sector_bytes/sizeof(ULONG)]
static TX_THREAD s_demo_thread
static UCHAR s_demo_stack [k_demo_thread_stack]

Detailed Description

ThreadX + LevelX wear-levelling demo for EK-RA8D2 OSPI flash.

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

Brings the chip up the same way uart_hello does (CGC -> SCI8 @ 115200 8N1), then hands control to ThreadX. tx_application_define spawns one worker thread that:

  1. Initialises ra8_xspi against the on-board EK-RA8D2 ISSI IS25LX512M octal-SPI flash chip.
  2. Calls lx_nor_flash_format once to lay down a fresh LevelX partition (small, 64 blocks * 4 KiB = 256 KiB) and immediately lx_nor_flash_open to mount it.
  3. Enters a continuous heartbeat loop:
    • Increments an in-RAM counter once per second.
    • Writes the counter into LevelX logical sector 0 with lx_nor_flash_sector_write.
    • Reads it back with lx_nor_flash_sector_read and prints the value over SCI8.
  4. Once k_demo_burnin_writes (10000) heartbeats have run, the thread prints LevelX's wear-levelling statistics (lx_nor_flash_write_requests, lx_nor_flash_read_requests, lx_nor_flash_extended_cache_hits/misses, lx_nor_flash_minimum_erase_count / lx_nor_flash_maximum_erase_count) so a human can see the wear distribution across blocks.

Recipe (see also the README.md alongside this main.c):

  • Connect a USB cable to the J-Link OB CDC port on the EK-RA8D2.
  • Open a 115200 8N1 terminal.
  • Flash this firmware (just apps::hardware::flash threadx_levelx_demo).
  • Watch the heartbeat counter and final wear-levelling stats stream out over the terminal.
Author
Brighton Sikarskie
Date
2026-04-29
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ demo_config_t

enum demo_config_t : uint32_t
Enumerator
k_demo_baud 

Console baud (matches uart_hello / threadx_fs_demo).

k_demo_thread_stack 

Worker-thread stack size in bytes.

k_demo_sector_index 

LevelX logical sector the heartbeat counter is stored in.

k_demo_burnin_writes 

Number of heartbeats before printing wear-levelling stats.

k_demo_tick_ms 

Heartbeat tick in milliseconds.

k_demo_sector_bytes 

LevelX bytes per logical sector (= 512).

k_demo_radix_dec 

Decimal radix used by demo_print_u32.

k_demo_u32_buf_size 

Buffer size for demo_print_u32 (10 digits + sign + NUL).

Definition at line 76 of file main.c.

◆ lx_log_pace_t

enum lx_log_pace_t : uint32_t

Compile-time settings for the LevelX wear-levelling demo.

Enumerator
k_lx_log_every_n 

Log once every N loop iterations.

Definition at line 72 of file main.c.

Function Documentation

◆ demo_heartbeat()

UINT demo_heartbeat ( uint32_t counter)
static

Run one heartbeat: program counter into sector 0 + read back.

Parameters
[in]counterHeartbeat sequence number.
Returns
LX_SUCCESS on success, otherwise the LevelX error code from the underlying read or write call.
Precondition
LevelX flash control block s_nor_flash is open.
Postcondition
On success the read-back word equals counter.
Since
0.1.0

Definition at line 273 of file main.c.

References k_demo_sector_index, s_demo_sector_io, and s_nor_flash.

Referenced by demo_thread_entry().

◆ demo_lx_format_or_panic()

void demo_lx_format_or_panic ( void )
static

Format + open the LevelX partition.

Panics on any failure.

Precondition
ra8_xspi_init succeeded for instance 0.
Postcondition
On success s_nor_flash is open and ready for sector I/O.
Since
0.1.0

Definition at line 242 of file main.c.

References demo_panic_halt(), demo_print(), lx_nor_driver_ra8_xspi_initialize(), and s_nor_flash.

Referenced by demo_thread_entry().

◆ demo_panic_halt()

void demo_panic_halt ( void )
static

Halt forever in WFI, after draining the J-Link OB VCOM TX FIFO.

Calls ra8_board_uart_console_flush so any panic message previously queued via ra8_board_uart_console_write finishes clocking onto the wire before WFI gates the SCI clock. Without the flush, only the first 1-3 bytes of the failure log reach the host because WFI silences the peripheral mid-frame. Return code is intentionally discarded – if the flush times out we still want to halt rather than spin.

Precondition
Called only after a fatal error.
Postcondition
Pending console TX has drained (or the flush budget expired) and the CPU is parked.
Since
0.1.0

Definition at line 133 of file main.c.

References ra8_board_uart_console_flush().

◆ demo_print()

void demo_print ( const char * s)
static

Convenience wrapper to write a NUL-terminated string to the console.

Parameters
[in]sNUL-terminated ASCII string. Must not be NULL.
Precondition
s != NULL.
Postcondition
On success the bytes are queued in the BSP console TX FIFO.
Since
0.1.0

Definition at line 177 of file main.c.

References ra8_board_uart_console_write(), and strlen().

◆ demo_print_stat()

void demo_print_stat ( const char * label,
ULONG value )
static

Print one labelled ULONG LevelX statistic line over SCI8.

Parameters
[in]labelNUL-terminated stat name. Must not be NULL.
[in]valueStat value.
Precondition
label != NULL.
Postcondition
One " <label>: <value>\\r\\n" line is queued to SCI8.
Since
0.1.0

Definition at line 225 of file main.c.

References demo_print(), and demo_print_u32().

Referenced by demo_print_wear_stats().

◆ demo_print_u32()

void demo_print_u32 ( uint32_t value)
static

Print an unsigned 32-bit integer in decimal to SCI8.

Parameters
[in]valueInteger to print.
Precondition
None.
Postcondition
Decimal representation of value is queued to SCI8.
Since
0.1.0

Definition at line 196 of file main.c.

References demo_print(), k_demo_radix_dec, and k_demo_u32_buf_size.

Referenced by demo_print_stat(), demo_report_rw_once(), and demo_thread_entry().

◆ demo_print_wear_stats()

void demo_print_wear_stats ( void )
static

Dump LevelX's wear-levelling statistics to SCI8.

Precondition
s_nor_flash is open.
Postcondition
Statistics are queued to SCI8.
Since
0.1.0

Definition at line 297 of file main.c.

References demo_print(), demo_print_stat(), and s_nor_flash.

Referenced by demo_thread_entry().

◆ demo_report_rw_once()

void demo_report_rw_once ( uint32_t counter,
uint32_t readback )
static

Emit a one-shot HIL success banner after the first verified heartbeat.

On the first heartbeat (counter == 1) the worker has written the counter into LevelX logical sector 0 and read it back. A matching read-back proves the whole stack (LevelX format + open + sector write/read over the xSPI NOR) round-tripped real data – not just that the chip booted. Emits a distinct success-only banner the HIL uart_scrape gate keys on, or a MISMATCH banner its negative regex catches. Does nothing on later heartbeats.

Parameters
[in]counterCurrent heartbeat sequence number.
[in]readbackValue read back from LevelX logical sector 0.
Precondition
Called once per heartbeat from the worker loop.
Postcondition
On counter == 1 exactly one banner line is queued to SCI8.
Since
0.1.0

Definition at line 336 of file main.c.

References demo_print(), and demo_print_u32().

Referenced by demo_thread_entry().

◆ demo_setup_or_halt()

void demo_setup_or_halt ( void )
static

Bring CGC + the J-Link OB VCOM console up.

Panic-halts on any failure.

Precondition
Reset_Handler / SystemInit complete.
Postcondition
On success the BSP console is sending at 115200 8N1.
Since
0.1.0

Definition at line 149 of file main.c.

References demo_panic_halt(), k_demo_baud, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), and ra8_time_init().

◆ demo_thread_entry()

void demo_thread_entry ( ULONG thread_input)
static

ThreadX worker entry: format LevelX, run the heartbeat loop, dump stats.

Parameters
[in]thread_inputUnused.
Precondition
tx_application_define has scheduled this thread.
Postcondition
The heartbeat loop has run k_demo_burnin_writes cycles and wear-levelling statistics have been printed.
Since
0.1.0

Definition at line 361 of file main.c.

References demo_heartbeat(), demo_lx_format_or_panic(), demo_print(), demo_print_u32(), demo_print_wear_stats(), demo_report_rw_once(), k_demo_burnin_writes, k_demo_tick_ms, k_lx_log_every_n, s_demo_sector_io, s_nor_flash, and tx_thread_sleep.

◆ main()

void main ( void )

Application entry.

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.
Postcondition
On clean entry the kernel runs the worker thread once.
Since
0.1.0

Definition at line 451 of file main.c.

References demo_panic_halt(), demo_print(), demo_setup_or_halt(), and ra8_isr_globals_enable().

◆ tx_application_define()

void tx_application_define ( void * first_unused_memory)

ThreadX system-define hook: build the worker thread + LevelX core.

Parameters
[in]first_unused_memoryPointer to the start of free RAM provided by the ThreadX port; unused – we statically allocate.
Precondition
tx_kernel_enter() has been called.
Postcondition
One worker thread is created and LevelX has been initialized.
Since
0.1.0

Definition at line 422 of file main.c.

References demo_thread_entry(), s_demo_stack, s_demo_thread, s_thread_name, TX_AUTO_START, TX_NO_TIME_SLICE, and tx_thread_create.

Variable Documentation

◆ s_demo_sector_io

ULONG s_demo_sector_io[k_demo_sector_bytes/sizeof(ULONG)]
static

Definition at line 108 of file main.c.

Referenced by demo_heartbeat(), and demo_thread_entry().

◆ s_demo_stack

UCHAR s_demo_stack[k_demo_thread_stack]
static

Definition at line 112 of file main.c.

◆ s_demo_thread

TX_THREAD s_demo_thread
static

Definition at line 111 of file main.c.

◆ s_nor_flash

LX_NOR_FLASH s_nor_flash
static

Definition at line 105 of file main.c.