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

Host side of the soak self-test: enumerate, mount, verify, soak. More...

#include "usb_selftest_host.h"
#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_err.h"
#include "ra8_fs.h"
#include "ra8_io_blockdev.h"
#include "ra8_io_blockdev_usbmsc.h"
#include "ra8_time.h"
#include "ra8_usb_hmsc.h"
#include "usb_selftest_common.h"
#include "usb_selftest_console.h"
Include dependency graph for usb_selftest_host.c:

Go to the source code of this file.

Functions

static const char * selftest_fs_type_name (ra8_fs_type_t type)
 Map a detected filesystem type to a printable name.
static ra8_err_t selftest_mount_volume (ra8_fs_mount_t **out_mount)
 Mount the loop device's volume through the USB-MSC backend.
static ra8_err_t selftest_verify_mram_raw (void)
 Raw multi-block READ(10) of the MRAM data region vs MRAM.
static ra8_err_t selftest_write_protect_probe (void)
 WRITE(10) into the read-only LUN must be rejected.
static ra8_err_t selftest_host_enumerate (ra8_usb_hmsc_device_t *out_device)
 Bring the host controller up and enumerate the loop device.
static ra8_err_t selftest_print_soak_verdict (uint64_t total_bytes, uint64_t total_ms)
 Print the soak aggregate line (iterations + volume + rate).
ra8_err_t selftest_host_pass (void)
 Soak pass: enumerate + mount once, then repeat the 1 MiB verify.

Variables

static volatile uint32_t s_dbg_phase
 Host-ladder phase marker (selftest_phase_t).
static volatile uint32_t s_dbg_verified_bytes
 Bytes content-verified so far this pass.
static volatile uint32_t s_dbg_mismatch_off = (uint32_t)k_selftest_no_mismatch
 First mismatching MRAM offset (k_selftest_no_mismatch = none).
static volatile uint32_t s_dbg_verify_ms
 Milliseconds the 1 MiB verify streamed for.
static volatile uint32_t s_dbg_pass_count
 Completed full passes (sticky success counter).
static ra8_io_blockdev_t s_selftest_usb_dev
 Block device fronting the hosted MSC volume for this ladder.
static ra8_io_blockdev_usbmsc_state_t s_selftest_usb_state
 Caller-owned backend state for s_selftest_usb_dev.

Detailed Description

Host side of the soak self-test: enumerate, mount, verify, soak.

The polled first-party host MSC stack (ra8_usb_hmsc + ra8_fs) over the loop cable: enumerate the device, mount its FAT16 volume, then repeat the raw 1 MiB READ(10) integrity sweep k_selftest_soak_iters times (memcmp vs MRAM), confirm the RO write rejection, and print the aggregate throughput. selftest_host_pass is the one entry the host worker (main.c) drives; the J-Link probe vars live here too. Split out of main.c (see usb_selftest_common.h).

Since
0.1.0

Definition in file usb_selftest_host.c.

Function Documentation

◆ selftest_fs_type_name()

const char * selftest_fs_type_name ( ra8_fs_type_t type)
static

Map a detected filesystem type to a printable name.

Total over the enum; unknown maps to "unknown".

Parameters
[in]typeMount-time detection result.
Returns
Static NUL-terminated name string.
Return values
fat16For k_ra8_fs_type_fat16 (the expected verdict).
Precondition
None – total over the enum.
type came from a populated mount struct.
Postcondition
No state changes.
Returned pointer references static storage.
Note
Pure function.
Since
0.1.0

Definition at line 100 of file usb_selftest_host.c.

References k_ra8_fs_type_exfat, k_ra8_fs_type_fat12, k_ra8_fs_type_fat16, k_ra8_fs_type_fat32, and k_ra8_fs_type_unknown.

Referenced by selftest_mount_volume().

◆ selftest_host_enumerate()

ra8_err_t selftest_host_enumerate ( ra8_usb_hmsc_device_t * out_device)
staticnodiscard

Bring the host controller up and enumerate the loop device.

Initializes the USBHS host, enumerates the downstream FS device over the cable, and prints its VID/PID. On any failure the host controller is closed so the caller's retry starts clean.

Parameters
[out]out_deviceReceives the enumerated device snapshot.
Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okHost up and device enumerated; identity printed.
Precondition
Device-side class is registered and attached (other thread).
out_device is non-NULL.
Postcondition
On k_ra8_ok the host controller is live and out_device filled.
On failure the host controller has been closed again.
Note
Blocking; runs on the low-priority host thread.
Since
0.1.0

Definition at line 306 of file usb_selftest_host.c.

References k_ra8_ok, k_ra8_usb_speed_hs, k_selftest_hex_chars_u16, k_selftest_phase_enum, k_selftest_phase_host_init, ra8_usb_hmsc_device_t::product_id, ra8_usb_hmsc_close(), ra8_usb_hmsc_enumerate(), ra8_usb_hmsc_init(), s_dbg_phase, selftest_print(), selftest_print_fail(), selftest_print_hex(), and ra8_usb_hmsc_device_t::vendor_id.

Referenced by selftest_host_pass().

◆ selftest_host_pass()

ra8_err_t selftest_host_pass ( void )
nodiscard

Soak pass: enumerate + mount once, then repeat the 1 MiB verify.

Run one full soak pass and print the verdict.

One full host-side pass: enumerate, mount, verify, WP.

One full host-side pass: enumerate, mount, browse, verify, WP.

Enumerates and mounts to prove FAT parse, then runs selftest_verify_mram_raw k_selftest_soak_iters times back to back – every burst is still memcmp'd vs MRAM, so a single corrupted transfer anywhere in the soak fails the run. Aggregates volume + time for a stable throughput benchmark, then confirms the RO write rejection once. s_dbg_pass_count mirrors the completed-iteration count for J-Link.

Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okAll iterations matched; SOAK PASS printed.
Precondition
Device-side class is registered and attached (other thread).
The self-loop cable connects J7 to J11.
Postcondition
On success LED2 is on and the aggregate + PASS lines are queued.
On failure the host controller is closed for a clean retry.
Note
Blocking; ~k_selftest_soak_iters MiB over the loop.
Since
0.1.0

Definition at line 419 of file usb_selftest_host.c.

References k_ra8_board_led2, k_ra8_ok, k_selftest_phase_mount, k_selftest_phase_pass, k_selftest_phase_verify, k_selftest_phase_wp, k_selftest_soak_iters, ra8_board_led_on(), ra8_fs_unmount(), ra8_usb_hmsc_close(), s_dbg_pass_count, s_dbg_phase, s_dbg_verified_bytes, s_dbg_verify_ms, selftest_browse_root(), selftest_host_enumerate(), selftest_host_enumerate(), selftest_mount_volume(), selftest_mount_volume(), selftest_print(), selftest_print_soak_verdict(), selftest_print_verify_verdict(), selftest_verify_mram_raw(), selftest_verify_mram_raw(), selftest_write_protect_probe(), and selftest_write_protect_probe().

Referenced by selftest_host_worker().

◆ selftest_mount_volume()

ra8_err_t selftest_mount_volume ( ra8_fs_mount_t ** out_mount)
staticnodiscard

Mount the loop device's volume through the USB-MSC backend.

Binds the ra8_io USB-MSC block device over the polled host class, bridges it to an ra8_fs backend, and prints the detected filesystem type (must be fat16 for this device).

Parameters
[out]out_mountReceives the mount handle on success.
Returns
ra8_err_t from the block-device bind, the ra8_fs bridge, or ra8_fs_mount.
Return values
k_ra8_okVolume mounted; the type line was printed.
Precondition
ra8_usb_hmsc_enumerate completed on the loop device.
out_mount is non-NULL.
Postcondition
On k_ra8_ok the mount handle is live and must be unmounted later.
The "mounted fs=" line is queued on success.
Note
Reads the BPB chain over the self-loop cable.
Since
0.1.0

Definition at line 138 of file usb_selftest_host.c.

References k_ra8_ok, k_selftest_target_lun, ra8_fs_mount(), ra8_io_blockdev_as_fs_backend(), ra8_io_blockdev_usbmsc_init(), s_selftest_usb_dev, s_selftest_usb_state, selftest_fs_type_name(), selftest_print(), and selftest_print_fail().

Referenced by selftest_host_pass().

◆ selftest_print_soak_verdict()

ra8_err_t selftest_print_soak_verdict ( uint64_t total_bytes,
uint64_t total_ms )
staticnodiscard

Print the soak aggregate line (iterations + volume + rate).

"soak: N iters, M MiB verified in T ms (R KiB/s), 0 errors".

Parameters
[in]total_bytesSum of all bytes verified across the soak.
[in]total_msSum of all per-iteration verify durations (ms).
Returns
ra8_err_t propagated from the SCI helpers.
Return values
k_ra8_okThe aggregate line is queued.
Precondition
The soak loop completed every iteration with k_ra8_ok.
SCI8 init already ran.
Postcondition
One aggregate line is in the SCI8 TX FIFO.
Note
Rate math guards the divide against a zero duration.
Since
0.1.0

Definition at line 362 of file usb_selftest_host.c.

References k_ra8_ok, k_selftest_bytes_per_kib, k_selftest_bytes_per_mib, k_selftest_ms_per_sec, k_selftest_soak_iters, selftest_print(), and selftest_print_dec().

Referenced by selftest_host_pass().

◆ selftest_verify_mram_raw()

ra8_err_t selftest_verify_mram_raw ( void )
staticnodiscard

Raw multi-block READ(10) of the MRAM data region vs MRAM.

Streams the 1 MiB data region straight through the SCSI READ(10) entry point in 8-block (4 KiB) bursts – one CBW per burst, not per sector – and memcmp's each burst against the same offset of the real MRAM window at 0x02000000. This deliberately bypasses ra8_fs: the filesystem walk re-reads FAT/metadata sectors per cluster (a ~250x device-read amplification that throttled the loop to under 1 sector/s), whereas the raw path is the direct integrity proof – "the SCSI transport returns the chip's flash byte for byte" – and runs at the cable's real rate. The mount step (separate phase) already proved the host can PARSE the FAT16 volume over the loop.

Data region: FAT16 LBA k_fat_data_lba is cluster 2 = MRAM offset 0, so LBA (data_lba + b) holds MRAM[b * 512].

Returns
ra8_err_t verdict.
Return values
k_ra8_okAll 1 MiB matched byte for byte.
k_ra8_err_invalid_stateA byte differed from MRAM.
Precondition
ra8_usb_hmsc_enumerate completed on the loop device.
The device side exposes the synthesized MRAM volume.
Postcondition
s_dbg_verified_bytes / s_dbg_verify_ms / s_dbg_mismatch_off reflect the outcome.
No filesystem handle is held (raw SCSI path).
Note
Blocking; 256 four-KiB READ(10) bursts over the self-loop.
Since
0.1.0

Definition at line 199 of file usb_selftest_host.c.

References k_fat_data_lba, k_fat_mram_clusters, k_mram_base_addr, k_ra8_err_invalid_state, k_ra8_ok, k_selftest_block_size, k_selftest_burst_blocks, k_selftest_burst_bytes, k_selftest_no_mismatch, k_selftest_target_lun, memcmp(), ra8_time_ms(), ra8_usb_hmsc_read10(), s_dbg_mismatch_off, s_dbg_verified_bytes, s_dbg_verify_ms, and selftest_print_fail().

Referenced by selftest_host_pass().

◆ selftest_write_protect_probe()

ra8_err_t selftest_write_protect_probe ( void )
staticnodiscard

WRITE(10) into the read-only LUN must be rejected.

Issues a 1-block WRITE(10) into the data region. The device LUN is write-protected (MODE SENSE WP bit + media_write returns DATA PROTECT), so the host's write entry point must surface an error rather than k_ra8_ok – the MRAM is never modified. This is the write-protection proof.

It deliberately stops there: terminating a data-out phase against a write-protected device STALLs the bulk-OUT endpoint, and recovering the BOT transport afterwards (Bulk-Only Mass Storage Reset + Clear Feature ENDPOINT_HALT on both bulk pipes) is not yet implemented in the host class. That STALL/ClearFeature recovery path is tracked as GitHub issue #92's robustness sweep; this pass parks on success, so the post-STALL desync does not affect the verdict.

Returns
ra8_err_t verdict.
Return values
k_ra8_okThe write was rejected (protection works).
k_ra8_err_invalid_stateThe write was unexpectedly accepted.
Precondition
ra8_usb_hmsc_enumerate completed on the loop device.
The device LUN reports write-protected.
Postcondition
The device volume is untouched (the write never lands).
One verdict line is queued on the console.
Note
Leaves the bulk-OUT pipe halted (see details); pass parks next.
Since
0.1.0

Definition at line 259 of file usb_selftest_host.c.

References k_ra8_err_invalid_state, k_ra8_ok, k_selftest_block_size, k_selftest_hex_chars_u32, k_selftest_target_lun, k_selftest_wp_probe_lba, ra8_usb_hmsc_write10(), selftest_print(), selftest_print_fail(), and selftest_print_hex().

Referenced by selftest_host_pass().

Variable Documentation

◆ s_dbg_mismatch_off

volatile uint32_t s_dbg_mismatch_off = (uint32_t)k_selftest_no_mismatch
static

First mismatching MRAM offset (k_selftest_no_mismatch = none).

Definition at line 42 of file usb_selftest_host.c.

◆ s_dbg_pass_count

volatile uint32_t s_dbg_pass_count
static

Completed full passes (sticky success counter).

Definition at line 46 of file usb_selftest_host.c.

◆ s_dbg_phase

volatile uint32_t s_dbg_phase
static

Host-ladder phase marker (selftest_phase_t).

Definition at line 38 of file usb_selftest_host.c.

◆ s_dbg_verified_bytes

volatile uint32_t s_dbg_verified_bytes
static

Bytes content-verified so far this pass.

Definition at line 40 of file usb_selftest_host.c.

◆ s_dbg_verify_ms

volatile uint32_t s_dbg_verify_ms
static

Milliseconds the 1 MiB verify streamed for.

Definition at line 44 of file usb_selftest_host.c.

◆ s_selftest_usb_dev

ra8_io_blockdev_t s_selftest_usb_dev
static

Block device fronting the hosted MSC volume for this ladder.

Bound once in selftest_mount_volume by ra8_io_blockdev_usbmsc_init, which wires the ra8_io USB-MSC backend over the polled host-MSC class. File scope because ra8_io_blockdev_as_fs_backend keeps a pointer to this handle for the whole life of the mount.

Note
Single-threaded ladder; no locking.
Warning
Do not rebind while a mount is live.
Since
0.1.0

Definition at line 66 of file usb_selftest_host.c.

◆ s_selftest_usb_state

ra8_io_blockdev_usbmsc_state_t s_selftest_usb_state
static

Caller-owned backend state for s_selftest_usb_dev.

Records the logical unit the backend addresses. Private to the ra8_io USB-MSC backend and must out-live every call made through the device.

Note
Single-threaded ladder; no locking.
Warning
Treat the contents as private to ra8_io.
Since
0.1.0

Definition at line 80 of file usb_selftest_host.c.