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 view of the onboard MRAM (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 "usb_msc_mram_steps.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  scsi_wp_sense_t : uint8_t {
  k_scsi_sense_data_protect = 0x07U ,
  k_scsi_asc_write_protected = 0x27U
}
 SCSI sense triple for a write to the protected medium. 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)
static UINT demo_msc_write (VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
 Storage media-write callback: always rejects (write-protected).
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 the read-only MRAM LUN.
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_msc_vendor_id [] = "RA8D2 "
static UCHAR s_msc_product_id [] = "MRAM 1MiB (RO) "
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.
static volatile uint32_t s_dbg_read_calls
 Storage media-read callback: synthesize sectors over MRAM.
static volatile uint32_t s_dbg_read_last_lba
 Most recent starting LBA.
static volatile uint32_t s_dbg_read_last_n
 Most recent block count.

Detailed Description

ThreadX + USBX Mass-Storage view of the onboard MRAM (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 a READ-ONLY synthesized FAT16 volume: the boot sector, FAT, and root directory are generated on the fly, and the data clusters map 1:1 onto the chip's 1 MiB MRAM window at 0x02000000, exposed as a single root file MRAM.BIN. Plug the board into a computer and the onboard flash shows up as a file you can open/copy; comparing it against a debugger dump of the same window proves the bytes travel USB end to end. Writes are rejected with DATA PROTECT sense and the LUN reports write-protected via MODE SENSE, so hosts mount it read-only.

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

◆ 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 114 of file main.c.

◆ scsi_wp_sense_t

enum scsi_wp_sense_t : uint8_t

SCSI sense triple for a write to the protected medium.

Enumerator
k_scsi_sense_data_protect 

Sense key: DATA PROTECT.

k_scsi_asc_write_protected 

ASC: WRITE PROTECTED.

Definition at line 121 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 302 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 the read-only MRAM LUN.

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 the read-only synthesized FAT16 volume.
Note
Not re-entrant.
Since
0.1.0

Definition at line 486 of file main.c.

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

◆ demo_msc_read()

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

◆ 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 429 of file main.c.

◆ 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: always rejects (write-protected).

Parameters
[in,out]storageUSBX storage class instance (unused).
[in]lunLogical unit number (unused).
[in]data_pointerUSBX-owned source buffer (unused).
[in]number_blocksNumber of blocks the host tried (unused).
[in]lbaStarting LBA (unused).
[out]media_statusFilled with DATA PROTECT sense.
Returns
Always UX_ERROR.
Return values
UX_ERRORThe medium is write-protected.
Precondition
media_status is non-NULL (USBX guarantee).
The LUN also reports write-protected via MODE SENSE.
Postcondition
*media_status carries the DATA PROTECT sense triple.
The MRAM window is untouched.
Note
Hosts honouring the MODE SENSE WP bit never call this.
Since
0.1.0

Definition at line 394 of file main.c.

References k_scsi_asc_write_protected, k_scsi_ascq_none, and k_scsi_sense_data_protect.

◆ 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 590 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 610 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 456 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 640 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 82 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 559 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 107 of file main.c.

◆ k_demo_pin_dp

Definition at line 106 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 104 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 105 of file main.c.

◆ s_dbg_read_calls

volatile uint32_t s_dbg_read_calls
static

Storage media-read callback: synthesize sectors over MRAM.

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 produce.
[in]lbaStarting LBA.
[out]media_statusFilled with sense status word.
Returns
UX_SUCCESS if the request fits the volume; 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 synthesized or media_status is non-zero.
Note
Called from the USBX storage class thread.
Since
0.1.0 media_read invocations.

Definition at line 343 of file main.c.

◆ s_dbg_read_last_lba

volatile uint32_t s_dbg_read_last_lba
static

Most recent starting LBA.

Definition at line 344 of file main.c.

Referenced by demo_msc_read().

◆ s_dbg_read_last_n

volatile uint32_t s_dbg_read_last_n
static

Most recent block count.

Definition at line 345 of file main.c.

Referenced by demo_msc_read().

◆ 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 145 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 138 of file main.c.

◆ s_device_framework_fs

UCHAR s_device_framework_fs[]
static

Definition at line 175 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 312 of file main.c.

◆ s_msc_product_id

UCHAR s_msc_product_id[] = "MRAM 1MiB (RO) "
static

Definition at line 158 of file main.c.

◆ s_msc_product_rev

UCHAR s_msc_product_rev[] = "0001"
static

Definition at line 159 of file main.c.

◆ s_msc_vendor_id

UCHAR s_msc_vendor_id[] = "RA8D2 "
static

Definition at line 157 of file main.c.

◆ 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 244 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 154 of file main.c.