ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_selftest_wlun_host.c
Go to the documentation of this file.
1
26
27#include <stdint.h>
28#include <string.h>
29
30#include "ra8_board_ek_ra8d2.h"
31#include "ra8_err.h"
32#include "ra8_usb_hmsc.h"
33#include "tx_api.h"
35
36#ifndef RA8_OFF_TARGET
37
38/* -------------------------------------------------------------------------- */
39/* J-Link probes (host ladder) */
40/* -------------------------------------------------------------------------- */
41
43static volatile uint32_t s_dbg_phase;
45static volatile uint32_t s_dbg_luns_ok;
47static volatile uint32_t s_dbg_max_lun;
49static volatile uint32_t s_dbg_mismatch = (uint32_t)k_wlun_no_mismatch;
51static volatile uint32_t s_dbg_pass_count;
52
53/* -------------------------------------------------------------------------- */
54/* Host side: ra8_usb_hmsc enumerate + WRITE(10) then read-verify */
55/* -------------------------------------------------------------------------- */
56
79[[nodiscard]] static ra8_err_t wlun_write_disk(uint32_t lun)
80{
81 static uint8_t s_wbuf[k_wlun_burst_bytes] = {};
82 for (uint32_t blk = 0U; blk < (uint32_t)k_wlun_sectors; blk += (uint32_t)k_wlun_burst_blocks) {
83 for (uint32_t s = 0U; s < (uint32_t)k_wlun_burst_blocks; s++) {
84 wlun_pattern_fill(lun, blk + s, &s_wbuf[s * (uint32_t)k_wlun_block_size]);
85 }
86 const ra8_err_t err =
87 ra8_usb_hmsc_write10((uint8_t)lun, blk, (uint16_t)k_wlun_burst_blocks, s_wbuf);
88 if (err != k_ra8_ok) {
89 (void)wlun_print_fail("WRITE(10)", err);
90 return err;
91 }
92 }
93 return k_ra8_ok;
94}
95
118[[nodiscard]] static ra8_err_t wlun_verify_one(uint32_t lun)
119{
120 static uint8_t s_burst[k_wlun_burst_bytes] = {};
121 static uint8_t s_expect[k_wlun_block_size] = {};
122
123 uint32_t block_count = 0U;
124 uint32_t block_size = 0U;
125 ra8_err_t err = ra8_usb_hmsc_read_capacity((uint8_t)lun, &block_count, &block_size);
126 if (err != k_ra8_ok) {
127 (void)wlun_print_fail("read_capacity", err);
128 return err;
129 }
130 if (block_count != (uint32_t)k_wlun_sectors) {
131 (void)wlun_print_fail("capacity mismatch", k_ra8_err_invalid_size);
133 }
134 for (uint32_t blk = 0U; blk < (uint32_t)k_wlun_sectors; blk += (uint32_t)k_wlun_burst_blocks) {
135 err = ra8_usb_hmsc_read10((uint8_t)lun, blk, (uint16_t)k_wlun_burst_blocks, s_burst);
136 if (err != k_ra8_ok) {
137 (void)wlun_print_fail("READ(10)", err);
138 return err;
139 }
140 for (uint32_t s = 0U; s < (uint32_t)k_wlun_burst_blocks; s++) {
141 wlun_pattern_fill(lun, blk + s, s_expect);
142 const uint32_t boff = s * (uint32_t)k_wlun_block_size;
143 if (memcmp(&s_burst[boff], s_expect, (size_t)k_wlun_block_size) != 0) {
144 s_dbg_mismatch = (lun << (uint32_t)k_wlun_mismatch_lun_shift) | (blk + s);
145 (void)wlun_print_fail("LUN data mismatch", k_ra8_err_invalid_state);
147 }
148 }
149 }
150 return k_ra8_ok;
151}
152
169[[nodiscard]] static ra8_err_t wlun_print_lun_ok(uint32_t lun)
170{
171 ra8_err_t err = wlun_print("ra8d2 wlun: LUN ");
172 if (err != k_ra8_ok) {
173 return err;
174 }
175 err = wlun_print_dec(lun);
176 if (err != k_ra8_ok) {
177 return err;
178 }
179 return wlun_print(" OK (64 sectors, write+read verified)\r\n");
180}
181
204{
205 s_dbg_phase = (uint32_t)k_wlun_phase_enum;
206 ra8_err_t err = ra8_usb_hmsc_enumerate(device);
207 if (err != k_ra8_ok) {
208 (void)wlun_print_fail("enumerate", err);
209 (void)ra8_usb_hmsc_close();
210 return err;
211 }
212 s_dbg_max_lun = (uint32_t)device->max_lun;
213 err = wlun_print("ra8d2 wlun: enumerated pid=0x");
214 if (err != k_ra8_ok) {
215 return err;
216 }
217 err = wlun_print_hex((uint32_t)device->product_id, (uint8_t)k_wlun_hex_chars_u16);
218 if (err != k_ra8_ok) {
219 return err;
220 }
221 err = wlun_print(", GET_MAX_LUN=");
222 if (err != k_ra8_ok) {
223 return err;
224 }
226 if (err != k_ra8_ok) {
227 return err;
228 }
229 return wlun_print("\r\n");
230}
231
249[[nodiscard]] static ra8_err_t wlun_host_pass(void)
250{
251 s_dbg_phase = (uint32_t)k_wlun_phase_init;
252 ra8_err_t err = wlun_print("ra8d2 wlun: host up on USB-HS, probing the loop...\r\n");
253 if (err != k_ra8_ok) {
254 return err;
255 }
257 if (err != k_ra8_ok) {
258 (void)wlun_print_fail("host init", err);
259 return err;
260 }
261
262 ra8_usb_hmsc_device_t device = {};
263 err = wlun_host_enumerate(&device);
264 if (err != k_ra8_ok) {
265 return err;
266 }
267
269 s_dbg_luns_ok = 0U;
270 for (uint32_t lun = 0U; lun < (uint32_t)k_wlun_count; lun++) {
271 err = wlun_write_disk(lun);
272 if (err != k_ra8_ok) {
273 (void)ra8_usb_hmsc_close();
274 return err;
275 }
276 err = wlun_verify_one(lun);
277 if (err != k_ra8_ok) {
278 (void)ra8_usb_hmsc_close();
279 return err;
280 }
282 err = wlun_print_lun_ok(lun);
283 if (err != k_ra8_ok) {
284 return err;
285 }
286 }
287
288 s_dbg_phase = (uint32_t)k_wlun_phase_pass;
290 err = wlun_print("ra8d2 wlun: USB SELFTEST WRITABLE-LUN PASS\r\n");
291 if (err != k_ra8_ok) {
292 return err;
293 }
295 return k_ra8_ok;
296}
297
299{
300 (void)arg;
301
303 for (;;) {
304 const ra8_err_t err = wlun_host_pass();
305 if (err == k_ra8_ok) {
306 break;
307 }
309 }
310 while (1) {
312 }
313}
314
315#endif /* !RA8_OFF_TARGET */
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_on(ra8_board_led_id_t led)
Drive led HIGH (light it).
@ k_ra8_board_led2
LED2, GREEN, P303 (jumper E26).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
Native USB host-side MSC (Mass Storage Class) class layer.
ra8_err_t ra8_usb_hmsc_read_capacity(uint8_t target_lun, uint32_t *block_count, uint32_t *block_size)
Issue a SCSI READ CAPACITY(10) (opcode 0x25) over BBB.
ra8_err_t ra8_usb_hmsc_read10(uint8_t target_lun, uint32_t lba, uint16_t block_count, uint8_t *out_buf)
Issue a SCSI READ(10) (opcode 0x28) over BBB.
ra8_err_t ra8_usb_hmsc_enumerate(ra8_usb_hmsc_device_t *out_device)
Enumerate the attached MSC device end to end (polled).
ra8_err_t ra8_usb_hmsc_close(void)
Tear down the host-MSC driver and release the controller.
ra8_err_t ra8_usb_hmsc_init(ra8_usb_speed_t speed)
Bring up the host-MSC driver on a chosen USB controller.
ra8_err_t ra8_usb_hmsc_write10(uint8_t target_lun, uint32_t lba, uint16_t block_count, const uint8_t *in_buf)
Issue a SCSI WRITE(10) (opcode 0x2A) over BBB.
#define tx_thread_sleep
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Snapshot of the attached MSC device, passed to the attach callback.
uint8_t max_lun
Get-Max-LUN response (0..15).
uint16_t product_id
idProduct from device descriptor.
static ra8_err_t wlun_host_pass(void)
One full host-side pass: enumerate, WRITE(10) then verify.
static volatile uint32_t s_dbg_phase
Host-ladder phase marker (wlun_phase_t).
static ra8_err_t wlun_host_enumerate(ra8_usb_hmsc_device_t *device)
Enumerate the looped device and print its PID + GET_MAX_LUN.
static volatile uint32_t s_dbg_luns_ok
Sectors that read back correctly after the write pass.
static ra8_err_t wlun_verify_one(uint32_t lun)
Read + verify one LUN's full sector range against its pattern.
static volatile uint32_t s_dbg_pass_count
Completed full passes (sticky success counter).
static ra8_err_t wlun_print_lun_ok(uint32_t lun)
Print "LUN n OK" for the verified writable unit.
static volatile uint32_t s_dbg_mismatch
First mismatching sector, or k_wlun_no_mismatch.
static volatile uint32_t s_dbg_max_lun
Device-reported GET_MAX_LUN value (expect 0, single LUN).
VOID wlun_host_worker(ULONG arg)
Host-side worker: retry the full pass until it succeeds.
static ra8_err_t wlun_write_disk(uint32_t lun)
WRITE(10) the per-LBA pattern across the whole RAM disk.
examples/ek_ra8d2/hil_needs_revalidation/usb_selftest_wlun/inc/usb_selftest_wlun_steps....
void wlun_pattern_fill(uint32_t lun, uint32_t lba, UCHAR *out)
Fill one 512-byte sector with this LUN/LBA's deterministic bytes.
ra8_err_t wlun_print_hex(uint32_t value, uint8_t digits)
Print a value as fixed-width uppercase hex.
@ k_wlun_block_size
SCSI logical block size.
@ k_wlun_burst_blocks
Blocks per READ(10) burst.
@ k_wlun_mismatch_lun_shift
s_dbg_mismatch: LUN in bits 31:24.
@ k_wlun_sectors
512-byte sectors (RAM disk = 32 KiB).
@ k_wlun_no_mismatch
Probe: no mismatch.
@ k_wlun_burst_bytes
8 x 512 B burst buffer.
@ k_wlun_count
Logical units exposed (single writable).
ra8_err_t wlun_print(const char *text)
Print a NUL-terminated ASCII string over the console.
@ k_wlun_hex_chars_u16
16-bit value -> "ABCD".
@ k_wlun_idle_ticks
Parked-loop back-off (ticks).
@ k_wlun_retry_ticks
Pause between ladder retries.
@ k_wlun_boot_wait_ticks
Host start delay (1 ms ticks).
ra8_err_t wlun_print_fail(const char *what, ra8_err_t err)
Print "FAIL <what> err=0xNNNNNNNN" on its own line.
ra8_err_t wlun_print_dec(uint32_t value)
Print a uint32_t as ASCII decimal.
@ k_wlun_phase_enum
Enumerating.
@ k_wlun_phase_init
ra8_usb_hmsc_init issued.
@ k_wlun_phase_pass
All LUNs verified.
@ k_wlun_phase_verify
Reading + checking LUNs.