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

Device side of the soak self-test: USBX MSC over a FAT16 MRAM volume. More...

#include "usb_selftest_device.h"
#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_err.h"
#include "ra8_usb.h"
#include "usb_selftest_common.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 usb_selftest_device.c:

Go to the source code of this file.

Enumerations

enum  usb_langid_byte_t : uint8_t {
  k_usb_langid_en_us_lo = 0x09U ,
  k_usb_langid_en_us_hi = 0x04U
}

Functions

static void selftest_put16 (UCHAR *dst, uint16_t value)
 Write a 16-bit value little-endian into a byte buffer.
static void selftest_put32 (UCHAR *dst, uint32_t value)
 Write a 32-bit value little-endian into a byte buffer.
static void selftest_fat_fill_boot (UCHAR *out)
 Synthesize the FAT16 boot sector (MS FAT spec 1.03 sec 3.1).
static void selftest_fat_fill_fat (uint32_t fat_sector, UCHAR *out)
 Synthesize one FAT16 sector of the cluster chain.
static void selftest_fat_fill_root (uint32_t root_sector, UCHAR *out)
 Synthesize one root-directory sector.
static void selftest_fat_fill_sector (uint32_t lba, UCHAR *out)
 Synthesize one 512-byte sector of the read-only volume.
static UINT selftest_msc_read (VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
 Storage media-read callback: synthesize sectors over MRAM.
static UINT selftest_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 selftest_msc_status (VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
 Storage media-status callback.
static UINT selftest_usbx_stack_up (void)
 Brings USBX system + FS device stack up.
static UINT selftest_msc_class_register (void)
 Registers the Mass-Storage class with the read-only MRAM LUN.
VOID selftest_device_worker (ULONG arg)
 Device-side worker: bring the FS device stack up, then park.

Variables

static UCHAR s_usbx_pool [k_selftest_usbx_pool_bytes]
static UCHAR s_msc_vendor_id [] = "RA8D2 "
static UCHAR s_msc_product_id [] = "SELFTEST MRAM RO"
static UCHAR s_msc_product_rev [] = "0001"
static const UCHAR s_fat_oem_name [8] = {'R', 'A', '8', 'D', '2', 'F', 'W', ' '}
 Boot-sector OEM name (8 bytes, space padded).
static const UCHAR s_fat_volume_label [11] = {'R', 'A', '8', 'D', '2', ' ', 'M', 'R', 'A', 'M', ' '}
 Volume label, 11 bytes space padded (also the root entry).
static const UCHAR s_fat_fs_type [8] = {'F', 'A', 'T', '1', '6', ' ', ' ', ' '}
 Filesystem-type tag, 8 bytes space padded.
static const UCHAR s_fat_file_name [11] = {'M', 'R', 'A', 'M', ' ', ' ', ' ', ' ', 'B', 'I', 'N'}
 8.3 directory name of the exposed file: "MRAM.BIN".
static volatile uint32_t s_dbg_read_calls
 Device-side media_read invocations.
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

Device side of the soak self-test: USBX MSC over a FAT16 MRAM volume.

The USBFS device half of the self-loop: a USBX Mass-Storage class exposing the 1 MiB MRAM window at 0x02000000 as a read-only synthesized FAT16 volume (MRAM.BIN). Owns the USB framework descriptors, the FAT16 sector synthesis, the MSC media callbacks, the USBX device-stack bring-up, and the device worker thread entry (selftest_device_worker, spawned by tx_application_define in main.c). Split out of main.c (see usb_selftest_common.h).

Since
0.1.0

Definition in file usb_selftest_device.c.

Enumeration Type Documentation

◆ 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 196 of file usb_selftest_device.c.

Function Documentation

◆ selftest_device_worker()

VOID selftest_device_worker ( ULONG arg)

Device-side worker: bring the FS device stack up, then park.

Device-side worker: bring the FS device MSC stack up, then park.

Device-side worker: bring the HS device stack up, then park.

USBX system + device stack + MSC class + DCD bridge on the USBFS controller, then DPRPU attach. USBX runs the SCSI/BBB state machine on its own class threads after this.

Parameters
[in]argThreadX entry argument (unused).
Precondition
tx_application_define created this thread.
USB-FS pins + 48 MHz clock are up (main did both).
Postcondition
The FS device is attached and serviceable.
On any bring-up failure the thread exits (probes show where).
Note
Runs once; loops forever on success.
Since
0.1.0

Definition at line 650 of file usb_selftest_device.c.

References k_ra8_ok, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, k_selftest_idle_ticks, ra8_usb_device_attach(), s_dbg_dev_state, s_dbg_framework, s_dbg_fw_fs_addr, s_dbg_fw_hs_addr, s_dbg_fw_len, s_dbg_state3_seen, s_dbg_thr_runs, s_dbg_thr_state, s_dbg_ux_speed, s_device_framework_fs, s_device_framework_hs, selftest_msc_class_register(), selftest_msc_class_register(), selftest_usbx_stack_up(), selftest_usbx_stack_up(), tx_thread_sleep, and ux_dcd_ra8_usb_initialize().

◆ selftest_fat_fill_boot()

void selftest_fat_fill_boot ( UCHAR * out)
static

Synthesize the FAT16 boot sector (MS FAT spec 1.03 sec 3.1).

BPB for the padded 4146-sector volume plus the 0x55AA signature; geometry constants in selftest_fat_geom_t.

Parameters
[out]outZeroed 512-byte sector buffer.
Precondition
out is zeroed.
Geometry constants describe a valid FAT16 volume.
Postcondition
out holds the BPB + 0x55AA signature.
No other state changes.
Note
Pure function.
Since
0.1.0

Definition at line 272 of file usb_selftest_device.c.

References k_boot_drive_num, k_boot_ext_sig, k_boot_jmp0, k_boot_jmp1, k_boot_jmp2, k_boot_media, k_boot_num_heads, k_boot_sec_per_trk, k_boot_sig_hi, k_boot_sig_hi_off, k_boot_sig_lo, k_boot_sig_lo_off, k_boot_volume_id, k_bpb_off_bootsig, k_bpb_off_bps, k_bpb_off_drvnum, k_bpb_off_fatsz16, k_bpb_off_fstype, k_bpb_off_heads, k_bpb_off_jmp, k_bpb_off_label, k_bpb_off_media, k_bpb_off_nfats, k_bpb_off_oem, k_bpb_off_rootent, k_bpb_off_rsvd, k_bpb_off_spc, k_bpb_off_spt, k_bpb_off_totsec16, k_bpb_off_volid, k_fat_fat_sectors, k_fat_num_fats, k_fat_reserved_sectors, k_fat_root_entries, k_fat_total_sectors, k_selftest_block_size, memcpy(), s_fat_fs_type, s_fat_oem_name, s_fat_volume_label, selftest_put16(), and selftest_put32().

Referenced by selftest_fat_fill_sector().

◆ selftest_fat_fill_fat()

void selftest_fat_fill_fat ( uint32_t fat_sector,
UCHAR * out )
static

Synthesize one FAT16 sector of the cluster chain.

MRAM.BIN occupies clusters 2..2049 as one sequential chain (entry c -> c + 1, last entry -> end-of-chain). Entries 0/1 carry the media descriptor per the FAT spec; everything past the chain reads as free (0x0000).

Parameters
[in]fat_sectorIndex of the FAT sector (0-based).
[out]outZeroed 512-byte sector buffer.
Precondition
out is zeroed.
fat_sector is below k_fat_fat_sectors.
Postcondition
out holds 256 little-endian FAT16 entries.
No other state changes.
Note
Pure function.
Since
0.1.0

Definition at line 316 of file usb_selftest_device.c.

References k_fat_entries_per_sec, k_fat_entry0, k_fat_eoc, k_fat_last_mram_clus, and selftest_put16().

Referenced by selftest_fat_fill_sector().

◆ selftest_fat_fill_root()

void selftest_fat_fill_root ( uint32_t root_sector,
UCHAR * out )
static

Synthesize one root-directory sector.

Sector 0 of the root carries two entries: the volume label and the read-only MRAM.BIN file (start cluster 2, size 1 MiB). Every other root sector is empty.

Parameters
[in]root_sectorIndex of the root sector (0-based).
[out]outZeroed 512-byte sector buffer.
Precondition
out is zeroed.
root_sector is below k_fat_root_sectors.
Postcondition
out holds the directory entries for that sector.
No other state changes.
Note
Pure function.
Since
0.1.0

Definition at line 355 of file usb_selftest_device.c.

References k_dir_attr_read_only, k_dir_attr_volume, k_dir_entry_bytes, k_dir_name_bytes, k_dir_off_attr, k_dir_off_cluster_lo, k_dir_off_size, k_fat_first_cluster, k_mram_bytes, memcpy(), s_fat_file_name, s_fat_volume_label, selftest_put16(), and selftest_put32().

Referenced by selftest_fat_fill_sector().

◆ selftest_fat_fill_sector()

void selftest_fat_fill_sector ( uint32_t lba,
UCHAR * out )
static

Synthesize one 512-byte sector of the read-only volume.

Dispatches on the LBA: boot sector, FAT, root directory, or data region. Data sectors inside the MRAM.BIN chain are copied straight out of the 1 MiB MRAM window; padding clusters past the chain read as zeros.

Parameters
[in]lbaLogical block address inside the volume.
[out]out512-byte destination buffer.
Precondition
lba is below k_fat_total_sectors (caller-checked).
out has 512 writable bytes.
Postcondition
out holds the synthesized sector content.
No other state changes.
Note
Reads chip MRAM directly; no caching.
Since
0.1.0

Definition at line 390 of file usb_selftest_device.c.

References k_fat_data_lba, k_fat_fat_lba, k_fat_first_cluster, k_fat_last_mram_clus, k_fat_root_lba, k_mram_base_addr, k_selftest_block_size, memcpy(), memset(), selftest_fat_fill_boot(), selftest_fat_fill_fat(), and selftest_fat_fill_root().

Referenced by selftest_msc_read().

◆ selftest_msc_class_register()

UINT selftest_msc_class_register ( void )
static

Registers the Mass-Storage class with the read-only MRAM LUN.

Single LUN, write-protected, FAT16 geometry from selftest_fat_geom_t, media callbacks above.

Returns
UINT UX_SUCCESS on success.
Return values
UX_SUCCESSClass registered.
Precondition
selftest_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 598 of file usb_selftest_device.c.

References k_fat_total_sectors, k_selftest_block_size, memset(), s_msc_product_id, s_msc_product_rev, s_msc_vendor_id, selftest_msc_read(), selftest_msc_status(), and selftest_msc_write().

Referenced by selftest_device_worker().

◆ selftest_msc_read()

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

Storage media-read callback: synthesize sectors over MRAM.

Bound checks the request against the volume, then fills each block via selftest_fat_fill_sector. LED1 toggles per call so the self-loop traffic is visible on the board.

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.
s_dbg_read_calls advanced.
Note
Called from the USBX storage class thread.
Since
0.1.0

Definition at line 447 of file usb_selftest_device.c.

References k_fat_total_sectors, k_ra8_board_led1, k_scsi_asc_lba_out_of_range, k_scsi_ascq_none, k_scsi_sense_illegal_request, k_selftest_block_size, ra8_board_led_toggle(), s_dbg_read_calls, and selftest_fat_fill_sector().

◆ selftest_msc_status()

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

Storage media-status callback.

Always reports media-present.

The synthesized volume cannot go away; status is constant 0.

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).
The class instance is live.
Postcondition
*media_status is 0.
No other state changes.
Note
Synthesized volume; never reports media-not-present.
Since
0.1.0

Definition at line 535 of file usb_selftest_device.c.

◆ selftest_msc_write()

UINT selftest_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).

The host side of this very app probes exactly this rejection (WRITE(10) must fail with DATA PROTECT and the transport must keep working afterwards).

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 496 of file usb_selftest_device.c.

References k_scsi_asc_write_protected, k_scsi_ascq_none, and k_scsi_sense_data_protect.

◆ selftest_put16()

void selftest_put16 ( UCHAR * dst,
uint16_t value )
static

Write a 16-bit value little-endian into a byte buffer.

Low byte first, high byte second, per the FAT on-disk layout.

Parameters
[out]dstDestination (2 bytes).
[in]valueValue to store.
Precondition
dst has 2 writable bytes.
None beyond the buffer contract.
Postcondition
dst[0] holds the low byte, dst[1] the high byte.
No other state changes.
Note
Pure function.
Since
0.1.0

Definition at line 228 of file usb_selftest_device.c.

References k_byte_mask, and k_byte_shift.

Referenced by selftest_fat_fill_boot(), selftest_fat_fill_fat(), selftest_fat_fill_root(), and selftest_put32().

◆ selftest_put32()

void selftest_put32 ( UCHAR * dst,
uint32_t value )
static

Write a 32-bit value little-endian into a byte buffer.

Two selftest_put16 halves, low half-word first.

Parameters
[out]dstDestination (4 bytes).
[in]valueValue to store.
Precondition
dst has 4 writable bytes.
None beyond the buffer contract.
Postcondition
dst holds the four little-endian bytes of value.
No other state changes.
Note
Pure function.
Since
0.1.0

Definition at line 250 of file usb_selftest_device.c.

References k_word_mask, k_word_shift, and selftest_put16().

Referenced by selftest_fat_fill_boot(), and selftest_fat_fill_root().

◆ selftest_usbx_stack_up()

UINT selftest_usbx_stack_up ( void )
static

Brings USBX system + FS device stack up.

One-shot USBX pool + device-stack initialization for the FS-only framework.

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 565 of file usb_selftest_device.c.

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

Referenced by selftest_device_worker().

Variable Documentation

◆ s_dbg_read_calls

volatile uint32_t s_dbg_read_calls
static

Device-side media_read invocations.

Definition at line 63 of file usb_selftest_device.c.

◆ s_device_framework_fs

UCHAR s_device_framework_fs[]
static

Definition at line 72 of file usb_selftest_device.c.

◆ s_fat_file_name

const UCHAR s_fat_file_name[11] = {'M', 'R', 'A', 'M', ' ', ' ', ' ', ' ', 'B', 'I', 'N'}
static

8.3 directory name of the exposed file: "MRAM.BIN".

Definition at line 56 of file usb_selftest_device.c.

◆ s_fat_fs_type

const UCHAR s_fat_fs_type[8] = {'F', 'A', 'T', '1', '6', ' ', ' ', ' '}
static

Filesystem-type tag, 8 bytes space padded.

Definition at line 53 of file usb_selftest_device.c.

◆ s_fat_oem_name

const UCHAR s_fat_oem_name[8] = {'R', 'A', '8', 'D', '2', 'F', 'W', ' '}
static

Boot-sector OEM name (8 bytes, space padded).

Definition at line 47 of file usb_selftest_device.c.

◆ s_fat_volume_label

const UCHAR s_fat_volume_label[11] = {'R', 'A', '8', 'D', '2', ' ', 'M', 'R', 'A', 'M', ' '}
static

Volume label, 11 bytes space padded (also the root entry).

Definition at line 50 of file usb_selftest_device.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 206 of file usb_selftest_device.c.

◆ s_msc_product_id

UCHAR s_msc_product_id[] = "SELFTEST MRAM RO"
static

Definition at line 43 of file usb_selftest_device.c.

◆ s_msc_product_rev

UCHAR s_msc_product_rev[] = "0001"
static

Definition at line 44 of file usb_selftest_device.c.

◆ s_msc_vendor_id

UCHAR s_msc_vendor_id[] = "RA8D2 "
static

Definition at line 42 of file usb_selftest_device.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 137 of file usb_selftest_device.c.

◆ s_usbx_pool

UCHAR s_usbx_pool[k_selftest_usbx_pool_bytes]
static

Definition at line 39 of file usb_selftest_device.c.