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

Host-side step routines + console formatters for the writable-OSPI self-loop. More...

#include "usb_selftest_ospi_rw_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 dependency graph for usb_selftest_ospi_rw_steps.c:

Go to the source code of this file.

Functions

static void ospirw_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 ospirw_nibble_to_hex (uint32_t nibble)
 Format one nibble (0..15) into an uppercase hex character.
static uint32_t ospirw_str_len (const char *text)
 Bounded ASCII string length (cap k_ospirw_print_cap).
static ra8_err_t ospirw_sci_write (const uint8_t *data, uint32_t len)
 Push a literal block over the BSP UART console (SCI8) polled.
static ra8_err_t ospirw_print (const char *text)
 Print a NUL-terminated ASCII string over the console.
static ra8_err_t ospirw_print_dec (uint32_t value)
 Print a uint32_t as ASCII decimal.
static ra8_err_t ospirw_print_hex (uint32_t value, uint8_t digits)
 Print a value as fixed-width uppercase hex.
static ra8_err_t ospirw_print_fail (const char *what, ra8_err_t err)
 Print "FAIL <what> err=0xNNNNNNNN" on its own line.
static ra8_err_t ospirw_write_disk (uint32_t lun)
 WRITE(10) the per-LBA pattern across the whole OSPI window.
static ra8_err_t ospirw_verify_one (uint32_t lun)
 Read + verify one LUN's full sector range against its pattern.
static ra8_err_t ospirw_print_lun_ok (uint32_t lun)
 Print "LUN n OK" for the verified writable unit.
static ra8_err_t ospirw_host_enumerate (ra8_usb_hmsc_device_t *device)
 Enumerate the looped device and print its PID + GET_MAX_LUN.
static ra8_err_t ospirw_host_pass (void)
 One full host-side pass: enumerate, WRITE(10) then verify.
VOID ospirw_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 (ospirw_phase_t).
static volatile uint32_t s_dbg_luns_ok
 Sectors that read back correctly after the write pass.
static volatile uint32_t s_dbg_max_lun
 Device-reported GET_MAX_LUN value (expect 0, single LUN).
static volatile uint32_t s_dbg_mismatch = (uint32_t)k_ospirw_no_mismatch
 First mismatching sector, or k_ospirw_no_mismatch.
static volatile uint32_t s_dbg_pass_count
 Completed full passes (sticky success counter).

Detailed Description

Host-side step routines + console formatters for the writable-OSPI self-loop.

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

The host-side half of the usb_selftest_ospi_rw application, split out of main.c so each translation unit stays below the 1000-line file-size cap. It carries:

  • the SCI8 (J-Link OB CDC) console formatters: nibble/hex/decimal text conversion and the line-printers used to stream verdicts;
  • the deterministic per-(LUN,LBA) sector pattern generator that both the WRITE(10) producer and the READ(10) verifier compute identically;
  • the first-party polled host MSC ladder (enumerate, WRITE(10) the whole OSPI window, then READ(10) it back and byte-check every sector); and
  • the host ThreadX worker (ospirw_host_worker) that retries the full pass until the writable LUN verifies, then parks.

Only ospirw_host_worker is externally visible; tx_application_define in main.c spawns it. Everything else here is file-private. The J-Link debug probes touched solely by this side (s_dbg_phase ... s_dbg_pass_count) live here too; the device-side probes stay in main.c.

Author
Brighton Sikarskie
Date
2026-06-13
Since
0.1.0

Definition in file usb_selftest_ospi_rw_steps.c.

Function Documentation

◆ ospirw_host_enumerate()

ra8_err_t ospirw_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 470 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_hex_chars_u16, k_ospirw_phase_enum, k_ra8_ok, ra8_usb_hmsc_device_t::max_lun, ospirw_print(), ospirw_print_dec(), ospirw_print_fail(), ospirw_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 ospirw_host_pass().

◆ ospirw_host_pass()

ra8_err_t ospirw_host_pass ( void )
staticnodiscard

One full host-side pass: enumerate, WRITE(10) then verify.

Phases mirror ospirw_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 WRITABLE-OSPI 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 516 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_count, k_ospirw_phase_init, k_ospirw_phase_pass, k_ospirw_phase_verify, k_ra8_board_led2, k_ra8_ok, k_ra8_usb_speed_hs, ospirw_host_enumerate(), ospirw_print(), ospirw_print_fail(), ospirw_print_lun_ok(), ospirw_verify_one(), ospirw_write_disk(), 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 ospirw_host_worker().

◆ ospirw_host_worker()

VOID ospirw_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 host pass (enumerate + WRITE(10) + read-verify) with a retry pause until the writable LUN verifies; afterwards parks so the verdict stays on the wire. Spawned by tx_application_define in main.c; the body and all of its helpers live in usb_selftest_ospi_rw_steps.c.

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.
Since
0.1.0

Definition at line 565 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_boot_wait_ticks, k_ospirw_idle_ticks, k_ospirw_retry_ticks, k_ra8_ok, ospirw_host_pass(), and tx_thread_sleep.

Referenced by tx_application_define().

◆ ospirw_nibble_to_hex()

uint8_t ospirw_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 118 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_hex_digit_split.

Referenced by ospirw_print_hex().

◆ ospirw_pattern_fill()

void ospirw_pattern_fill ( uint32_t lun,
uint32_t lba,
UCHAR * out )
static

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_ospirw_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.
Since
0.1.0

Definition at line 87 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_block_size, k_ospirw_byte_mask, k_ospirw_pat_bias, k_ospirw_pat_lba_mul, and k_ospirw_pat_lun_mul.

Referenced by ospirw_verify_one(), and ospirw_write_disk().

◆ ospirw_print()

ra8_err_t ospirw_print ( const char * text)
staticnodiscard

Print a NUL-terminated ASCII string over the console.

Length-bounded by ospirw_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_ospirw_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 198 of file usb_selftest_ospi_rw_steps.c.

References ospirw_sci_write(), and ospirw_str_len().

Referenced by ospirw_host_enumerate(), ospirw_host_pass(), ospirw_print_fail(), and ospirw_print_lun_ok().

◆ ospirw_print_dec()

ra8_err_t ospirw_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 221 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_dec_chars_u32, k_ospirw_dec_radix, and ospirw_sci_write().

Referenced by ospirw_host_enumerate(), and ospirw_print_lun_ok().

◆ ospirw_print_fail()

ra8_err_t ospirw_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 297 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_hex_chars_u32, k_ra8_ok, ospirw_print(), and ospirw_print_hex().

Referenced by ospirw_host_enumerate(), ospirw_host_pass(), ospirw_verify_one(), and ospirw_write_disk().

◆ ospirw_print_hex()

ra8_err_t ospirw_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_ospirw_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 264 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_hex_chars_u32, k_ospirw_nibble_bits, k_ospirw_nibble_mask, ospirw_nibble_to_hex(), and ospirw_sci_write().

Referenced by ospirw_host_enumerate(), and ospirw_print_fail().

◆ ospirw_print_lun_ok()

ra8_err_t ospirw_print_lun_ok ( uint32_t lun)
staticnodiscard

Print "LUN n OK" for the verified writable 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
ospirw_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 436 of file usb_selftest_ospi_rw_steps.c.

References k_ra8_ok, ospirw_print(), and ospirw_print_dec().

Referenced by ospirw_host_pass().

◆ ospirw_sci_write()

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

Push a literal block over the BSP UART console (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; the BSP console 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 175 of file usb_selftest_ospi_rw_steps.c.

References ra8_board_uart_console_write().

Referenced by ospirw_print(), ospirw_print_dec(), and ospirw_print_hex().

◆ ospirw_str_len()

uint32_t ospirw_str_len ( const char * text)
static

Bounded ASCII string length (cap k_ospirw_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_ospirw_print_cap.
Note
Bounded scan.
Since
0.1.0

Definition at line 144 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_print_cap.

Referenced by ospirw_print().

◆ ospirw_verify_one()

ra8_err_t ospirw_verify_one ( uint32_t lun)
staticnodiscard

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

READ_CAPACITY (must report k_ospirw_sectors), then a raw multi-block READ(10) sweep in 8-block bursts, checking each sector against ospirw_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_ospirw_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 384 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_block_size, k_ospirw_burst_blocks, k_ospirw_burst_bytes, k_ospirw_mismatch_lun_shift, k_ospirw_sectors, k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_ok, memcmp(), ospirw_pattern_fill(), ospirw_print_fail(), ra8_usb_hmsc_read10(), ra8_usb_hmsc_read_capacity(), and s_dbg_mismatch.

Referenced by ospirw_host_pass().

◆ ospirw_write_disk()

ra8_err_t ospirw_write_disk ( uint32_t lun)
staticnodiscard

WRITE(10) the per-LBA pattern across the whole OSPI window.

Fills an 8-block burst from ospirw_pattern_fill and pushes it with raw ra8_usb_hmsc_write10 until every sector is written. This is the host data-OUT phase that drives the device bulk-OUT receive path (the gating mechanism for every writable / repeated-bulk matrix item).

Parameters
[in]lunLogical unit to write (0).
Returns
ra8_err_t verdict.
Return values
k_ra8_okThe whole window was written.
k_ra8_err_hw_timeoutA WRITE(10) data-OUT phase did not complete.
Precondition
The host has enumerated the device.
The LUN is writable (read_only_flag = UX_FALSE).
Postcondition
The device OSPI window holds the pattern on success.
On failure the offending step printed its error.
Note
Blocking; 8 four-KiB WRITE(10) bursts over the self-loop.
Since
0.1.0

Definition at line 344 of file usb_selftest_ospi_rw_steps.c.

References k_ospirw_block_size, k_ospirw_burst_blocks, k_ospirw_burst_bytes, k_ospirw_sectors, k_ra8_ok, ospirw_pattern_fill(), ospirw_print_fail(), and ra8_usb_hmsc_write10().

Referenced by ospirw_host_pass().

Variable Documentation

◆ s_dbg_luns_ok

volatile uint32_t s_dbg_luns_ok
static

Sectors that read back correctly after the write pass.

Definition at line 55 of file usb_selftest_ospi_rw_steps.c.

◆ s_dbg_max_lun

volatile uint32_t s_dbg_max_lun
static

Device-reported GET_MAX_LUN value (expect 0, single LUN).

Definition at line 57 of file usb_selftest_ospi_rw_steps.c.

◆ s_dbg_mismatch

volatile uint32_t s_dbg_mismatch = (uint32_t)k_ospirw_no_mismatch
static

First mismatching sector, or k_ospirw_no_mismatch.

Definition at line 59 of file usb_selftest_ospi_rw_steps.c.

◆ s_dbg_pass_count

volatile uint32_t s_dbg_pass_count
static

Completed full passes (sticky success counter).

Definition at line 61 of file usb_selftest_ospi_rw_steps.c.

◆ s_dbg_phase

volatile uint32_t s_dbg_phase
static

Host-ladder phase marker (ospirw_phase_t).

Definition at line 53 of file usb_selftest_ospi_rw_steps.c.