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

Pattern + SCI8 console + host-side enumerate/verify for usb_selftest_mlun. More...

#include "usb_selftest_mlun_steps.h"
#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_err.h"
#include "ra8_usb_hmsc.h"
#include "tx_api.h"
#include "ux_api.h"
#include "ux_device_class_storage.h"
Include dependency graph for usb_selftest_mlun_steps.c:

Go to the source code of this file.

Functions

void mlun_pattern_fill (uint32_t lun, uint32_t lba, UCHAR *out)
 Fill one 512-byte sector with this LUN/LBA's deterministic bytes.
static uint8_t mlun_nibble_to_hex (uint32_t nibble)
 Format one nibble (0..15) into an uppercase hex character.
static uint32_t mlun_str_len (const char *text)
 Bounded ASCII string length (cap k_mlun_print_cap).
static ra8_err_t mlun_sci_write (const uint8_t *data, uint32_t len)
 Push a literal block over SCI8 polled.
static ra8_err_t mlun_print (const char *text)
 Print a NUL-terminated ASCII string over the console.
static ra8_err_t mlun_print_dec (uint32_t value)
 Print a uint32_t as ASCII decimal.
static ra8_err_t mlun_print_hex (uint32_t value, uint8_t digits)
 Print a value as fixed-width uppercase hex.
static ra8_err_t mlun_print_fail (const char *what, ra8_err_t err)
 Print "FAIL <what> err=0xNNNNNNNN" on its own line.
static ra8_err_t mlun_verify_one (uint32_t lun)
 Read + verify one LUN's full sector range against its pattern.
static ra8_err_t mlun_print_lun_ok (uint32_t lun)
 Print "LUN n OK (256 sectors)" for a verified logical unit.
static ra8_err_t mlun_host_enumerate (ra8_usb_hmsc_device_t *device)
 Enumerate the looped device and print its PID + GET_MAX_LUN.
static ra8_err_t mlun_host_pass (void)
 One full host-side pass: enumerate, verify both LUNs.
VOID mlun_host_worker (ULONG arg)
 Host-side worker: retry the full pass until it succeeds.

Variables

static volatile uint32_t s_dbg_phase
 Host-ladder phase marker (mlun_phase_t).
static volatile uint32_t s_dbg_luns_ok
 LUNs that fully verified this pass (target 2).
static volatile uint32_t s_dbg_max_lun
 Device-reported GET_MAX_LUN value (expect 1).
static volatile uint32_t s_dbg_mismatch = (uint32_t)k_mlun_no_mismatch
 First mismatching (lun<<24 | sector), or k_mlun_no_mismatch.
static volatile uint32_t s_dbg_pass_count
 Completed full passes (sticky success counter).

Detailed Description

Pattern + SCI8 console + host-side enumerate/verify for usb_selftest_mlun.

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

Split out of the multi-LUN USB self-loop main.c to keep each translation unit under the per-file line cap. This TU owns:

  • the shared per-(LUN,LBA) deterministic pattern (mlun_pattern_fill), which the device media-read in main.c and the host verifier here both compute identically;
  • the SCI8 -> J-Link OB CDC console plus the heap-free decimal / hex / fail-line text formatters;
  • the host-side ladder: enumerate the looped device, READ_CAPACITY + READ(10) sweep + byte-check each LUN, and the retry worker thread.

The host-ladder J-Link probes (s_dbg_phase / s_dbg_luns_ok / s_dbg_max_lun / s_dbg_mismatch / s_dbg_pass_count) live here because only this TU writes them; the device-side probes stay in main.c.

Author
Brighton Sikarskie
Date
2026-06-13
Since
0.1.0

Definition in file usb_selftest_mlun_steps.c.

Function Documentation

◆ mlun_host_enumerate()

ra8_err_t mlun_host_enumerate ( ra8_usb_hmsc_device_t * device)
staticnodiscard

Enumerate the looped device and print its PID + GET_MAX_LUN.

Sets the enum phase, runs ra8_usb_hmsc_enumerate, records the reported max-LUN in s_dbg_max_lun, and streams the enumerated pid=... GET_MAX_LUN=... banner. On enumerate failure the host controller is closed so the next retry re-attaches clean.

Parameters
[out]deviceReceives the enumerated descriptor snapshot.
Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okDevice enumerated and the banner printed.
Precondition
device is non-null.
ra8_usb_hmsc_init has succeeded on this pass.
Postcondition
s_dbg_max_lun mirrors the device's GET_MAX_LUN.
On failure the host controller is deinitialized.
Note
Blocking; runs on the low-priority host thread.
Since
0.1.0

Definition at line 407 of file usb_selftest_mlun_steps.c.

References k_mlun_hex_chars_u16, k_mlun_phase_enum, k_ra8_ok, ra8_usb_hmsc_device_t::max_lun, mlun_print(), mlun_print_dec(), mlun_print_fail(), mlun_print_hex(), ra8_usb_hmsc_device_t::product_id, ra8_usb_hmsc_close(), ra8_usb_hmsc_enumerate(), s_dbg_max_lun, and s_dbg_phase.

Referenced by mlun_host_pass().

◆ mlun_host_pass()

ra8_err_t mlun_host_pass ( void )
staticnodiscard

One full host-side pass: enumerate, verify both LUNs.

Phases mirror mlun_phase_t. On any failure the host controller is closed so the next retry starts from a clean attach.

Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okThe pass printed MULTI-LUN PASS.
Precondition
Device-side class is registered and attached (other thread).
The self-loop cable connects J7 to J11.
Postcondition
On success s_dbg_pass_count advanced and LED2 is on.
On failure the host controller is deinitialized again.
Note
Blocking; runs on the low-priority host thread.
Since
0.1.0

Definition at line 453 of file usb_selftest_mlun_steps.c.

References k_mlun_count, k_mlun_phase_init, k_mlun_phase_pass, k_mlun_phase_verify, k_ra8_board_led2, k_ra8_ok, k_ra8_usb_speed_hs, mlun_host_enumerate(), mlun_print(), mlun_print_fail(), mlun_print_lun_ok(), mlun_verify_one(), ra8_board_led_on(), ra8_usb_hmsc_close(), ra8_usb_hmsc_init(), s_dbg_luns_ok, s_dbg_pass_count, and s_dbg_phase.

Referenced by mlun_host_worker().

◆ mlun_host_worker()

VOID mlun_host_worker ( ULONG arg)

Host-side worker: retry the full pass until it succeeds.

Waits for the device side to attach, then loops the full enumerate + per-LUN verify pass with a retry pause until both LUNs verify; afterwards parks so the verdict stays on the wire.

Parameters
[in]argThreadX entry argument (unused).
Precondition
tx_application_define created this thread.
The HS host pins, expander switch, and PLL are up (main).
Postcondition
On success the pass counter and LED2 are latched.
Retries forever otherwise; each failure prints its step.
Note
Blocking calls; ms timeouts via ra8_time. Defined in usb_selftest_mlun_steps.c; tx_application_define spawns it.
Since
0.1.0

Definition at line 497 of file usb_selftest_mlun_steps.c.

References k_mlun_boot_wait_ticks, k_mlun_idle_ticks, k_mlun_retry_ticks, k_ra8_ok, mlun_host_pass(), and tx_thread_sleep.

Referenced by tx_application_define().

◆ mlun_nibble_to_hex()

uint8_t mlun_nibble_to_hex ( uint32_t nibble)
static

Format one nibble (0..15) into an uppercase hex character.

Standard '0'-'9' then 'A'-'F' mapping.

Parameters
[in]nibble4-bit value.
Returns
ASCII '0'..'9' or 'A'..'F'.
Return values
'0'For a zero nibble.
Precondition
Caller has masked the value to 4 bits.
None beyond the mask contract.
Postcondition
Returned byte is printable hex.
No state changes.
Note
Pure function.
Since
0.1.0

Definition at line 96 of file usb_selftest_mlun_steps.c.

References k_mlun_hex_digit_split.

Referenced by mlun_print_hex().

◆ mlun_pattern_fill()

void mlun_pattern_fill ( uint32_t lun,
uint32_t lba,
UCHAR * out )

Fill one 512-byte sector with this LUN/LBA's deterministic bytes.

Byte i = (lun*97 + lba*7 + i + 0x5A) & 0xFF. Distinct per LUN and per LBA so the host can prove it addressed the right logical unit and sector. The device media-read and the host verifier compute it identically.

Parameters
[in]lunThe logical unit (0..1).
[in]lbaThe logical block address within the LUN.
[out]out512-byte destination buffer.
Precondition
out has k_mlun_block_size writable bytes.
lun and lba are within the exposed geometry.
Postcondition
out holds the sector's pattern bytes.
No global state changes.
Note
Pure function. Defined in usb_selftest_mlun_steps.c; the device media-read in main.c shares it with the host verifier.
Since
0.1.0

Definition at line 65 of file usb_selftest_mlun_steps.c.

References k_mlun_block_size, k_mlun_byte_mask, k_mlun_pat_bias, k_mlun_pat_lba_mul, and k_mlun_pat_lun_mul.

Referenced by mlun_msc_read(), and mlun_verify_one().

◆ mlun_print()

ra8_err_t mlun_print ( const char * text)
staticnodiscard

Print a NUL-terminated ASCII string over the console.

Length-bounded by mlun_str_len.

Parameters
[in]textString to print (CR/LF included by the caller).
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran; text is non-NULL.
text is NUL-terminated within k_mlun_print_cap bytes.
Postcondition
The string bytes are in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 176 of file usb_selftest_mlun_steps.c.

References mlun_sci_write(), and mlun_str_len().

Referenced by mlun_host_enumerate(), mlun_host_pass(), mlun_print_fail(), and mlun_print_lun_ok().

◆ mlun_print_dec()

ra8_err_t mlun_print_dec ( uint32_t value)
staticnodiscard

Print a uint32_t as ASCII decimal.

Digit-reversal into a bounded scratch buffer.

Parameters
[in]valueValue to print.
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran.
None beyond console readiness.
Postcondition
One ASCII decimal token is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 199 of file usb_selftest_mlun_steps.c.

References k_mlun_dec_chars_u32, k_mlun_dec_radix, and mlun_sci_write().

Referenced by mlun_host_enumerate(), and mlun_print_lun_ok().

◆ mlun_print_fail()

ra8_err_t mlun_print_fail ( const char * what,
ra8_err_t err )
staticnodiscard

Print "FAIL <what> err=0xNNNNNNNN" on its own line.

One-line diagnostic; first failing chunk's code returned.

Parameters
[in]whatShort description of the failed step.
[in]errError code returned by the step.
Returns
ra8_err_t propagated from the SCI helpers.
Return values
k_ra8_okThe diagnostic line is queued.
Precondition
SCI8 init already ran.
what is NUL-terminated within the print cap.
Postcondition
One diagnostic line is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 275 of file usb_selftest_mlun_steps.c.

References k_mlun_hex_chars_u32, k_ra8_ok, mlun_print(), and mlun_print_hex().

Referenced by mlun_host_enumerate(), mlun_host_pass(), and mlun_verify_one().

◆ mlun_print_hex()

ra8_err_t mlun_print_hex ( uint32_t value,
uint8_t digits )
staticnodiscard

Print a value as fixed-width uppercase hex.

Width is clamped to 8 hex digits.

Parameters
[in]valueValue to print.
[in]digitsHex digit count (4 for u16, 8 for u32).
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran.
digits is at most k_mlun_hex_chars_u32.
Postcondition
One fixed-width hex token is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 242 of file usb_selftest_mlun_steps.c.

References k_mlun_hex_chars_u32, k_mlun_nibble_bits, k_mlun_nibble_mask, mlun_nibble_to_hex(), and mlun_sci_write().

Referenced by mlun_host_enumerate(), and mlun_print_fail().

◆ mlun_print_lun_ok()

ra8_err_t mlun_print_lun_ok ( uint32_t lun)
staticnodiscard

Print "LUN n OK (256 sectors)" for a verified logical unit.

Parameters
[in]lunThe LUN that just verified.
Returns
ra8_err_t propagated from the SCI helpers.
Return values
k_ra8_okThe line is queued.
Precondition
mlun_verify_one returned k_ra8_ok for lun.
SCI8 init already ran.
Postcondition
One ASCII line is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 373 of file usb_selftest_mlun_steps.c.

References k_ra8_ok, mlun_print(), and mlun_print_dec().

Referenced by mlun_host_pass().

◆ mlun_sci_write()

ra8_err_t mlun_sci_write ( const uint8_t * data,
uint32_t len )
staticnodiscard

Push a literal block over SCI8 polled.

Thin wrapper fixing the console channel.

Parameters
[in]dataBuffer to send.
[in]lenByte count.
Returns
ra8_err_t passthrough from ra8_board_uart_console_write.
Return values
k_ra8_okAll bytes queued.
Precondition
data is non-NULL; SCI8 init already ran.
len excludes any NUL terminator.
Postcondition
Bytes are in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 153 of file usb_selftest_mlun_steps.c.

References ra8_board_uart_console_write().

Referenced by mlun_print(), mlun_print_dec(), and mlun_print_hex().

◆ mlun_str_len()

uint32_t mlun_str_len ( const char * text)
static

Bounded ASCII string length (cap k_mlun_print_cap).

Linear scan with a hard upper bound.

Parameters
[in]textNUL-terminated string.
Returns
Number of bytes before the NUL, capped.
Return values
0For an empty string.
Precondition
text is non-NULL.
text points to readable storage of at least the length.
Postcondition
No state changes.
Return value never exceeds k_mlun_print_cap.
Note
Bounded scan.
Since
0.1.0

Definition at line 122 of file usb_selftest_mlun_steps.c.

References k_mlun_print_cap.

Referenced by mlun_print().

◆ mlun_verify_one()

ra8_err_t mlun_verify_one ( uint32_t lun)
staticnodiscard

Read + verify one LUN's full sector range against its pattern.

READ_CAPACITY (must report k_mlun_sectors), then a raw multi-block READ(10) sweep in 8-block bursts, checking each sector against mlun_pattern_fill for this lun.

Parameters
[in]lunLogical unit to verify (0..1).
Returns
ra8_err_t verdict.
Return values
k_ra8_okThe whole LUN matched its pattern.
k_ra8_err_invalid_sizeREAD_CAPACITY reported wrong geometry.
k_ra8_err_invalid_stateA byte differed from the pattern.
Precondition
The host has enumerated the device.
lun is below k_mlun_count.
Postcondition
s_dbg_mismatch records (lun<<24 | sector) on mismatch.
Nothing is retained between LUNs.
Note
Blocking; 32 four-KiB READ(10) bursts over the self-loop.
Since
0.1.0

Definition at line 322 of file usb_selftest_mlun_steps.c.

References k_mlun_block_size, k_mlun_burst_blocks, k_mlun_burst_bytes, k_mlun_mismatch_lun_shift, k_mlun_sectors, k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_ok, memcmp(), mlun_pattern_fill(), mlun_print_fail(), ra8_usb_hmsc_read10(), ra8_usb_hmsc_read_capacity(), and s_dbg_mismatch.

Referenced by mlun_host_pass().

Variable Documentation

◆ s_dbg_luns_ok

volatile uint32_t s_dbg_luns_ok
static

LUNs that fully verified this pass (target 2).

Definition at line 53 of file usb_selftest_mlun_steps.c.

◆ s_dbg_max_lun

volatile uint32_t s_dbg_max_lun
static

Device-reported GET_MAX_LUN value (expect 1).

Definition at line 55 of file usb_selftest_mlun_steps.c.

◆ s_dbg_mismatch

volatile uint32_t s_dbg_mismatch = (uint32_t)k_mlun_no_mismatch
static

First mismatching (lun<<24 | sector), or k_mlun_no_mismatch.

Definition at line 57 of file usb_selftest_mlun_steps.c.

◆ s_dbg_pass_count

volatile uint32_t s_dbg_pass_count
static

Completed full passes (sticky success counter).

Definition at line 59 of file usb_selftest_mlun_steps.c.

◆ s_dbg_phase

volatile uint32_t s_dbg_phase
static

Host-ladder phase marker (mlun_phase_t).

Definition at line 51 of file usb_selftest_mlun_steps.c.