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

ThreadX + USBX Mass-Storage RAM-disk for EK-RA8D2 (USB-FS). 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_gpio_constants.h"
#include "ra8_isr.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_time.h"
#include "ra8_usb.h"
#include "tx_api.h"
#include "ux_api.h"
#include "ux_dcd_ra8_usb.h"
#include "ux_device_class_storage.h"
#include "ux_device_stack.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  scsi_sense_code_t : uint8_t {
  k_scsi_sense_illegal_request = 0x05U ,
  k_scsi_asc_lba_out_of_range = 0x21U ,
  k_scsi_ascq_none = 0x00U
}
 SCSI sense triple for an unsupported / out-of-range request. More...
enum  demo_config_t : uint32_t {
  k_demo_thread_stack = 4096U ,
  k_demo_usbx_pool_bytes = 32768U ,
  k_demo_block_size = 512U ,
  k_demo_block_count = 1024U ,
  k_demo_idle_ticks = 50U
}
 Compile-time settings for the worker thread + USBX pool + RAM-disk geometry. More...
enum  usb_langid_byte_t : uint8_t {
  k_usb_langid_en_us_lo = 0x09U ,
  k_usb_langid_en_us_hi = 0x04U
}

Functions

void _tx_timer_interrupt (void)
void SysTick_Handler (void)
 Service the SysTick exception selected by the linked application.
static UINT demo_msc_read (VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
 Storage media-read callback.
static UINT demo_msc_write (VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
 Storage media-write callback.
static UINT demo_msc_status (VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
 Storage media-status callback.
static UINT demo_usbx_stack_up (void)
 Brings USBX system + FS device stack up.
static UINT demo_msc_class_register (void)
 Registers the Mass-Storage class with one LUN backed by s_ramdisk.
static VOID demo_worker (ULONG arg)
VOID tx_application_define (VOID *first_unused_memory)
 ThreadX application-define hook.
static void demo_panic_halt (void)
 Halt forever in WFI – panic stop on init failure.
static ra8_err_t demo_pins_init (void)
 Route the four USB-FS pins to the USBFS controller.
void main (void)
 Application entry.

Variables

static const ra8_port_pin_t k_demo_pin_vbus = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbus
 USB-FS pin identifiers, packed ra8_port_pin_t (port << 8 | pin).
static const ra8_port_pin_t k_demo_pin_vbusen = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbusen
static const ra8_port_pin_t k_demo_pin_dp = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dp
static const ra8_port_pin_t k_demo_pin_dm = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dm
static TX_THREAD s_demo_thread
 ThreadX TCB for the USBX worker thread.
static UCHAR s_demo_stack [k_demo_thread_stack]
 Stack backing storage for s_demo_thread.
static UCHAR s_usbx_pool [k_demo_usbx_pool_bytes]
 USBX memory pool (USBX uses tx_byte_pool internally).
static UCHAR s_ramdisk [k_demo_block_count *k_demo_block_size]
 RAM-disk backing store (4 KiB = 8 x 512-byte sectors).
static UCHAR s_msc_vendor_id [] = "RA8D2 "
static UCHAR s_msc_product_id [] = "USBX RAM Disk "
static UCHAR s_msc_product_rev [] = "0001"
static UCHAR s_device_framework_fs []
static UCHAR s_string_framework []
 USBX string descriptor table (vendor / product / serial).
static UCHAR s_language_id_framework [] = {k_usb_langid_en_us_lo, k_usb_langid_en_us_hi}
 USBX language-id table – US English.

Detailed Description

ThreadX + USBX Mass-Storage RAM-disk for EK-RA8D2 (USB-FS).

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

Brings the chip up via ra8_cgc_init() (XTAL -> PLL1 -> CPUCLK0 = 1 GHz, PCLKA = 125 MHz), routes the four USB-FS pins per the EK-RA8D2 v1 User's Manual to the on-board USB-FS receptacle, hands control to ThreadX, and brings the Mass-Storage device class up via Eclipse USBX (_ux_device_class_storage_initialize). The class sits on top of the project's port/usbx/ux_dcd_ra8_usb bridge to the hand-written ra8_usb register-level driver (HUM Ch. 36 USBFS, sec. 36.2.x for SYSCFG / DCPCFG / DCPMAXP / PIPECFG / CFIFO). The host actually enumerates the device because USBX's chapter-9 + SCSI/BBB state machines answer SETUP and BOT packets through the DCD bridge.

The single LUN is backed by an 8-sector x 512-byte (4 KiB) RAM buffer in DTCM/SRAM. There is no filesystem on it – the goal is proof-of-enumeration only. The host sees an unformatted removable drive of 4 KiB; macOS will offer to initialize the disk, which is the expected behaviour for this demo.

Pinout (USB-FS, FSP-aligned, mirrors usb_cdc_echo)

P4_07 = VBUS, P5_00 = VBUSEN, P8_14 = D+, P8_15 = D-, all PSEL = k_ra8_psel_usb_fs.

Verification (macOS)

After flashing, the EK-RA8D2's USB-FS receptacle (J11) enumerates as a USB Mass-Storage device. system_profiler SPUSBDataType lists it under "USB Bus" with class Mass Storage; Disk Utility shows an unformatted 4 KiB volume.

Author
Brighton Sikarskie
Date
2026-05-02
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ demo_config_t

enum demo_config_t : uint32_t

Compile-time settings for the worker thread + USBX pool + RAM-disk geometry.

Enumerator
k_demo_thread_stack 

Worker thread stack (bytes).

k_demo_usbx_pool_bytes 

USBX memory pool (bytes).

k_demo_block_size 

SCSI logical block size (bytes).

k_demo_block_count 

Blocks (1024 * 512 = 512 KiB) – big enough for a host mkfs.vfat / mount.

k_demo_idle_ticks 

Heartbeat back-off (ThreadX ticks).

Definition at line 120 of file main.c.

◆ scsi_sense_code_t

enum scsi_sense_code_t : uint8_t

SCSI sense triple for an unsupported / out-of-range request.

Enumerator
k_scsi_sense_illegal_request 

Sense key: ILLEGAL REQUEST.

k_scsi_asc_lba_out_of_range 

ASC: LBA out of range.

k_scsi_ascq_none 

ASCQ: none.

Definition at line 109 of file main.c.

◆ usb_langid_byte_t

enum usb_langid_byte_t : uint8_t
Enumerator
k_usb_langid_en_us_lo 

LANGID 0x0409 low byte.

k_usb_langid_en_us_hi 

LANGID 0x0409 high byte.

Definition at line 319 of file main.c.

Function Documentation

◆ _tx_timer_interrupt()

void _tx_timer_interrupt ( void )
extern

◆ demo_msc_class_register()

UINT demo_msc_class_register ( void )
static

Registers the Mass-Storage class with one LUN backed by s_ramdisk.

Returns
UINT UX_SUCCESS on success.
Return values
UX_SUCCESSClass registered.
Precondition
demo_usbx_stack_up has succeeded.
Media read/write/status callbacks are defined.
Postcondition
MSC class bound to configuration 1, interface 0.
LUN0 advertises k_demo_block_count removable FAT blocks.
Note
Not re-entrant.
Since
0.1.0

Definition at line 509 of file main.c.

References demo_msc_read(), demo_msc_status(), demo_msc_write(), k_demo_block_count, k_demo_block_size, memset(), s_msc_product_id, s_msc_product_rev, and s_msc_vendor_id.

Referenced by demo_worker().

◆ demo_msc_read()

UINT demo_msc_read ( VOID * storage,
ULONG lun,
UCHAR * data_pointer,
ULONG number_blocks,
ULONG lba,
ULONG * media_status )
static

Storage media-read callback.

Splats from RAM-disk into USBX.

Parameters
[in,out]storageUSBX storage class instance (unused).
[in]lunLogical unit number (must be 0).
[out]data_pointerUSBX-owned destination buffer.
[in]number_blocksNumber of 512-byte blocks to copy.
[in]lbaStarting LBA.
[out]media_statusFilled with sense status word.
Returns
UX_SUCCESS if the request fits the RAM-disk; otherwise UX_ERROR with media_status set to ILLEGAL REQUEST.
Return values
UX_SUCCESSRead completed.
UX_ERROROut-of-range LBA / count.
Precondition
data_pointer and media_status are non-NULL (USBX guarantee).
lun is 0 (single-LUN device).
Postcondition
Either number_blocks * 512 bytes were copied or media_status is non-zero.
Note
Called from the USBX storage class thread; no other context touches s_ramdisk.
Since
0.1.0

Definition at line 361 of file main.c.

References k_demo_block_count, k_demo_block_size, k_ra8_board_led1, k_scsi_asc_lba_out_of_range, k_scsi_ascq_none, k_scsi_sense_illegal_request, memcpy(), ra8_board_led_toggle(), and s_ramdisk.

Referenced by demo_msc_class_register().

◆ demo_msc_status()

UINT demo_msc_status ( VOID * storage,
ULONG lun,
ULONG media_id,
ULONG * media_status )
static

Storage media-status callback.

Always reports media-present.

Parameters
[in,out]storageUSBX storage class instance (unused).
[in]lunLogical unit number (unused).
[in]media_idMedia id (unused).
[out]media_statusFilled with 0 (no fault).
Returns
Always UX_SUCCESS.
Return values
UX_SUCCESSMedia is present and ready.
Precondition
media_status is non-NULL (USBX guarantee).
Postcondition
*media_status is 0.
Note
RAM-disk is always present; never reports media-not-present.
Since
0.1.0

Definition at line 452 of file main.c.

Referenced by demo_msc_class_register().

◆ demo_msc_write()

UINT demo_msc_write ( VOID * storage,
ULONG lun,
UCHAR * data_pointer,
ULONG number_blocks,
ULONG lba,
ULONG * media_status )
static

Storage media-write callback.

Splats from USBX into RAM-disk.

Parameters
[in,out]storageUSBX storage class instance (unused).
[in]lunLogical unit number (must be 0).
[in]data_pointerUSBX-owned source buffer.
[in]number_blocksNumber of 512-byte blocks to copy.
[in]lbaStarting LBA.
[out]media_statusFilled with sense status word.
Returns
UX_SUCCESS if the request fits the RAM-disk; otherwise UX_ERROR.
Return values
UX_SUCCESSWrite completed.
UX_ERROROut-of-range LBA / count.
Precondition
data_pointer and media_status are non-NULL.
lun is 0.
Postcondition
Either number_blocks * 512 bytes were copied or media_status is non-zero.
Note
Called from the USBX storage class thread.
Since
0.1.0

Definition at line 411 of file main.c.

References k_demo_block_count, k_demo_block_size, k_ra8_board_led1, k_scsi_asc_lba_out_of_range, k_scsi_ascq_none, k_scsi_sense_illegal_request, memcpy(), ra8_board_led_toggle(), and s_ramdisk.

Referenced by demo_msc_class_register().

◆ demo_panic_halt()

void demo_panic_halt ( void )
static

Halt forever in WFI – panic stop on init failure.

Precondition
Called only after a fatal error in boot.
Postcondition
CPU is parked.
Note
Not reachable post-boot.
Since
0.1.0

Definition at line 613 of file main.c.

◆ demo_pins_init()

ra8_err_t demo_pins_init ( void )
staticnodiscard

Route the four USB-FS pins to the USBFS controller.

Returns
Error from the first failing route call, or k_ra8_ok.
Return values
k_ra8_okAll four pins routed.
Precondition
IOPORT module is reachable.
Single-threaded init context.
Postcondition
On success the four USB-FS pins are in USB peripheral mode.
Note
Not thread-safe.
Since
0.1.0

Definition at line 633 of file main.c.

References k_demo_pin_dm, k_demo_pin_dp, k_demo_pin_vbus, k_demo_pin_vbusen, k_ra8_level_low, k_ra8_ok, k_ra8_psel_usb_fs, ra8_gpio_output_init(), and ra8_pfs_route_peripheral().

◆ demo_usbx_stack_up()

UINT demo_usbx_stack_up ( void )
static

Brings USBX system + FS device stack up.

Returns
UINT UX_SUCCESS on success.
Return values
UX_SUCCESSStack ready.
Precondition
File-scope pool reserved.
Thread context.
Postcondition
Device stack accepts class registrations.
On failure, USBX state is undefined.
Note
Single-call; not idempotent.
Since
0.1.0

Definition at line 479 of file main.c.

References k_demo_usbx_pool_bytes, s_device_framework_fs, s_language_id_framework, s_string_framework, and s_usbx_pool.

◆ demo_worker()

◆ main()

void main ( void )

Application entry.

The application entry point Reset_Handler hands control to.

Brings up CGC + USB-FS pins + LED1 + ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

Definition at line 663 of file main.c.

References demo_panic_halt(), demo_pins_init(), k_ra8_board_led1, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_board_led_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_cgc_usbfs_clock_enable(), ra8_isr_globals_enable(), and ra8_time_init().

◆ SysTick_Handler()

void SysTick_Handler ( void )

Service the SysTick exception selected by the linked application.

Service one SysTick event for the core timebase.

Service one SysTick event for the core timebase.

Resolves to the weak core timebase handler unless a strong RTOS or application handler overrides it. The vector table references the selected implementation without owning its subsystem policy.

Precondition
Entered for a SysTick exception with a valid exception frame.
The selected handler's timebase or scheduler state is initialised.
Postcondition
The selected implementation has processed one SysTick event.
The vector table itself remains unchanged.
Note
Runs in handler mode; thread-safety follows the selected implementation.
Since
0.1.0

The weak firmware implementation advances the millisecond counter, then services linked ThreadX and USB hooks when their weak symbols and readiness state permit. The host-test implementation advances only the counter. An application may replace either weak definition with a strong handler.

Precondition
The handler is entered for one SysTick event or a host-test equivalent.
On target, ra8_time_init() configured the SysTick period.
Postcondition
s_tick_ms has advanced by exactly one.
Optional subsystem hooks run only when linked and ready.
Note
IRQ-safe; the weak symbol may be overridden by an application handler.
Since
0.1.0

Service the SysTick exception selected by the linked application.

The weak firmware implementation advances the millisecond counter, then services linked ThreadX and USB hooks when their weak symbols and readiness state permit. The host-test implementation advances only the counter. An application may replace either weak definition with a strong handler.

Precondition
The handler is entered for one SysTick event or a host-test equivalent.
On target, ra8_time_init() configured the SysTick period.
Postcondition
s_tick_ms has advanced by exactly one.
Optional subsystem hooks run only when linked and ready.
Note
IRQ-safe; the weak symbol may be overridden by an application handler.
Since
0.1.0

Service the SysTick exception selected by the linked application.

Precondition
Called from exception context (IPSR == 15).
_tx_initialize_low_level has programmed SysTick.
Postcondition
One ThreadX tick elapsed; PendSV may be pending.

Definition at line 77 of file main.c.

References _tx_timer_interrupt(), ra8_time_on_tick(), and ux_dcd_ra8_usb_irq_reenable().

◆ tx_application_define()

VOID tx_application_define ( VOID * first_unused_memory)

ThreadX application-define hook.

Spawns the demo worker.

Parameters
[in]first_unused_memorySentinel (unused; static stacks).
Precondition
Called from tx_kernel_enter after scheduler init.
Postcondition
One auto-start worker thread is queued.
Note
Called once at boot; not thread-safe.
Since
0.1.0

Definition at line 582 of file main.c.

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

Variable Documentation

◆ k_demo_pin_dm

Definition at line 102 of file main.c.

◆ k_demo_pin_dp

Definition at line 101 of file main.c.

◆ k_demo_pin_vbus

const ra8_port_pin_t k_demo_pin_vbus = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbus
static

USB-FS pin identifiers, packed ra8_port_pin_t (port << 8 | pin).

Built as a runtime cast so clang-tidy's enum-range check is happy with the otherwise out-of-enum value.

Since
0.1.0

Definition at line 99 of file main.c.

◆ k_demo_pin_vbusen

const ra8_port_pin_t k_demo_pin_vbusen = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbusen
static

Definition at line 100 of file main.c.

◆ s_demo_stack

UCHAR s_demo_stack[k_demo_thread_stack]
static

Stack backing storage for s_demo_thread.

Since
0.1.0

Definition at line 148 of file main.c.

◆ s_demo_thread

TX_THREAD s_demo_thread
static

ThreadX TCB for the USBX worker thread.

Note
Single-writer (worker only).
Since
0.1.0

Definition at line 141 of file main.c.

◆ s_device_framework_fs

UCHAR s_device_framework_fs[]
static

Definition at line 188 of file main.c.

◆ s_language_id_framework

UCHAR s_language_id_framework[] = {k_usb_langid_en_us_lo, k_usb_langid_en_us_hi}
static

USBX language-id table – US English.

Since
0.1.0

Definition at line 329 of file main.c.

◆ s_msc_product_id

UCHAR s_msc_product_id[] = "USBX RAM Disk "
static

Definition at line 171 of file main.c.

◆ s_msc_product_rev

UCHAR s_msc_product_rev[] = "0001"
static

Definition at line 172 of file main.c.

◆ s_msc_vendor_id

UCHAR s_msc_vendor_id[] = "RA8D2 "
static

Definition at line 170 of file main.c.

◆ s_ramdisk

UCHAR s_ramdisk[k_demo_block_count *k_demo_block_size]
static

RAM-disk backing store (4 KiB = 8 x 512-byte sectors).

Zero-initialized at boot. There is no filesystem on it; macOS will offer to initialize the volume.

Note
Single-instance; not thread-safe (USBX serializes class IO).
Since
0.1.0

Definition at line 167 of file main.c.

Referenced by demo_msc_read(), and demo_msc_write().

◆ s_string_framework

UCHAR s_string_framework[]
static

USBX string descriptor table (vendor / product / serial).

Each entry: 2 bytes lang-id, 1 byte string index, 1 byte length, then ASCII bytes.

Since
0.1.0

Definition at line 257 of file main.c.

◆ s_usbx_pool

UCHAR s_usbx_pool[k_demo_usbx_pool_bytes]
static

USBX memory pool (USBX uses tx_byte_pool internally).

Sized larger than CDC/HID because the storage class allocates 2 x bulk endpoint buffers (~64 KiB-shaped reads).

Since
0.1.0

Definition at line 157 of file main.c.