ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_selftest_host.c
Go to the documentation of this file.
1
17
18#include "usb_selftest_host.h"
19
20#include <stdint.h>
21#include <string.h>
22
23#include "ra8_board_ek_ra8d2.h"
24#include "ra8_err.h"
25#include "ra8_fs.h"
26#include "ra8_io_blockdev.h"
28#include "ra8_time.h"
29#include "ra8_usb_hmsc.h"
30#include "usb_selftest_common.h"
32
33/* -------------------------------------------------------------------------- */
34/* J-Link probes (host side) */
35/* -------------------------------------------------------------------------- */
36
38static volatile uint32_t s_dbg_phase;
40static volatile uint32_t s_dbg_verified_bytes;
42static volatile uint32_t s_dbg_mismatch_off = (uint32_t)k_selftest_no_mismatch;
44static volatile uint32_t s_dbg_verify_ms;
46static volatile uint32_t s_dbg_pass_count;
47
48/* -------------------------------------------------------------------------- */
49/* Host side: ra8_fs mount over the ra8_io USB-MSC block device */
50/* -------------------------------------------------------------------------- */
51
67
81
100static const char* selftest_fs_type_name(ra8_fs_type_t type)
101{
102 switch (type) {
104 return "fat12";
106 return "fat16";
108 return "fat32";
110 return "exfat";
112 default:
113 return "unknown";
114 }
115}
116
138[[nodiscard]] static ra8_err_t selftest_mount_volume(ra8_fs_mount_t** out_mount)
139{
142 (uint8_t)k_selftest_target_lun);
143 if (err != k_ra8_ok) {
144 (void)selftest_print_fail("blockdev", err);
145 return err;
146 }
147 ra8_fs_backend_t backend = {};
149 if (err != k_ra8_ok) {
150 (void)selftest_print_fail("backend", err);
151 return err;
152 }
153 err = ra8_fs_mount(&backend, out_mount);
154 if (err != k_ra8_ok) {
155 (void)selftest_print_fail("mount", err);
156 return err;
157 }
158 err = selftest_print("ra8d2 selftest: mounted fs=");
159 if (err != k_ra8_ok) {
160 return err;
161 }
162 err = selftest_print(selftest_fs_type_name((*out_mount)->type));
163 if (err != k_ra8_ok) {
164 return err;
165 }
166 return selftest_print("\r\n");
167}
168
199[[nodiscard]] static ra8_err_t selftest_verify_mram_raw(void)
200{
201 static uint8_t s_burst[k_selftest_burst_bytes] = {};
202
205 const uint32_t t0 = ra8_time_ms();
206 for (uint32_t blk = 0U; blk < (uint32_t)k_fat_mram_clusters;
207 blk += (uint32_t)k_selftest_burst_blocks) {
208 const uint32_t lba = (uint32_t)k_fat_data_lba + blk;
210 lba,
211 (uint16_t)k_selftest_burst_blocks,
212 s_burst);
213 if (err != k_ra8_ok) {
214 (void)selftest_print_fail("READ(10) burst", err);
215 return err;
216 }
217 const uint32_t offset = blk * (uint32_t)k_selftest_block_size;
218 const uint8_t* mram = (const uint8_t*)(uintptr_t)((uint32_t)k_mram_base_addr + offset);
219 if (memcmp(s_burst, mram, (size_t)k_selftest_burst_bytes) != 0) {
220 s_dbg_mismatch_off = offset;
221 (void)selftest_print_fail("content mismatch at 0x", (ra8_err_t)offset);
223 }
224 s_dbg_verified_bytes = offset + (uint32_t)k_selftest_burst_bytes;
225 }
227 return k_ra8_ok;
228}
229
259[[nodiscard]] static ra8_err_t selftest_write_protect_probe(void)
260{
261 static uint8_t s_wp_buf[k_selftest_block_size] = {};
262
263 ra8_err_t err = selftest_print("ra8d2 selftest: WRITE(10) into RO LUN must be rejected...\r\n");
264 if (err != k_ra8_ok) {
265 return err;
266 }
268 (uint32_t)k_selftest_wp_probe_lba,
269 1U,
270 s_wp_buf);
271 if (wr == k_ra8_ok) {
272 (void)selftest_print_fail("write unexpectedly accepted", k_ra8_err_invalid_state);
274 }
275 err = selftest_print("ra8d2 selftest: write rejected (code 0x");
276 if (err != k_ra8_ok) {
277 return err;
278 }
279 err = selftest_print_hex((uint32_t)wr, (uint8_t)k_selftest_hex_chars_u32);
280 if (err != k_ra8_ok) {
281 return err;
282 }
283 return selftest_print("), MRAM protected\r\n");
284}
285
307{
309 ra8_err_t err = selftest_print("ra8d2 selftest: host up on USB-HS, probing the loop...\r\n");
310 if (err != k_ra8_ok) {
311 return err;
312 }
314 if (err != k_ra8_ok) {
315 (void)selftest_print_fail("host init", err);
316 return err;
317 }
319 err = ra8_usb_hmsc_enumerate(out_device);
320 if (err != k_ra8_ok) {
321 (void)selftest_print_fail("enumerate", err);
322 (void)ra8_usb_hmsc_close();
323 return err;
324 }
325 err = selftest_print("ra8d2 selftest: enumerated vid=0x");
326 if (err != k_ra8_ok) {
327 return err;
328 }
329 err = selftest_print_hex((uint32_t)out_device->vendor_id, (uint8_t)k_selftest_hex_chars_u16);
330 if (err != k_ra8_ok) {
331 return err;
332 }
333 err = selftest_print(" pid=0x");
334 if (err != k_ra8_ok) {
335 return err;
336 }
337 err = selftest_print_hex((uint32_t)out_device->product_id, (uint8_t)k_selftest_hex_chars_u16);
338 if (err != k_ra8_ok) {
339 return err;
340 }
341 return selftest_print(" over the loop cable\r\n");
342}
343
362[[nodiscard]] static ra8_err_t selftest_print_soak_verdict(uint64_t total_bytes, uint64_t total_ms)
363{
364 uint64_t ms = total_ms;
365 if (ms == 0U) {
366 ms = 1U;
367 }
368 const uint32_t kib_per_s = (uint32_t)((total_bytes * (uint64_t)k_selftest_ms_per_sec) /
369 (ms * (uint64_t)k_selftest_bytes_per_kib));
370 ra8_err_t err = selftest_print("ra8d2 soak: ");
371 if (err == k_ra8_ok) {
373 }
374 if (err == k_ra8_ok) {
375 err = selftest_print(" iters, ");
376 }
377 if (err == k_ra8_ok) {
378 err = selftest_print_dec((uint32_t)(total_bytes / (uint64_t)k_selftest_bytes_per_mib));
379 }
380 if (err == k_ra8_ok) {
381 err = selftest_print(" MiB verified in ");
382 }
383 if (err == k_ra8_ok) {
384 err = selftest_print_dec((uint32_t)total_ms);
385 }
386 if (err == k_ra8_ok) {
387 err = selftest_print(" ms (");
388 }
389 if (err == k_ra8_ok) {
390 err = selftest_print_dec(kib_per_s);
391 }
392 if (err == k_ra8_ok) {
393 err = selftest_print(" KiB/s), 0 errors\r\n");
394 }
395 return err;
396}
397
419[[nodiscard]] ra8_err_t selftest_host_pass(void)
420{
421 ra8_usb_hmsc_device_t device = {};
422 ra8_err_t err = selftest_host_enumerate(&device);
423 if (err != k_ra8_ok) {
424 return err;
425 }
427 ra8_fs_mount_t* mount = nullptr;
428 err = selftest_mount_volume(&mount);
429 if (err != k_ra8_ok) {
430 (void)ra8_usb_hmsc_close();
431 return err;
432 }
433 (void)ra8_fs_unmount(mount);
434
436 uint64_t total_bytes = 0U;
437 uint64_t total_ms = 0U;
438 for (uint32_t it = 0U; it < (uint32_t)k_selftest_soak_iters; it++) {
440 if (err != k_ra8_ok) {
441 (void)ra8_usb_hmsc_close();
442 return err;
443 }
444 total_bytes += (uint64_t)s_dbg_verified_bytes;
445 total_ms += (uint64_t)s_dbg_verify_ms;
446 s_dbg_pass_count = it + 1U;
447 }
448
451 if (err == k_ra8_ok) {
452 err = selftest_print_soak_verdict(total_bytes, total_ms);
453 }
454 if (err != k_ra8_ok) {
455 (void)ra8_usb_hmsc_close();
456 return err;
457 }
459 err = selftest_print("ra8d2 soak: USB SELFTEST SOAK PASS\r\n");
460 if (err != k_ra8_ok) {
461 return err;
462 }
464 return k_ra8_ok;
465}
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
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.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_mount(const ra8_fs_backend_t *backend, ra8_fs_mount_t **out_handle)
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
ra8_err_t ra8_fs_unmount(ra8_fs_mount_t *handle)
Unmount a previously mounted volume and release its slot.
ra8_fs_type_t
FAT variant detected from the BPB cluster-count rule.
@ k_ra8_fs_type_fat12
count_of_clusters < 4085.
@ k_ra8_fs_type_fat32
count_of_clusters >= 65525.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_type_fat16
4085 <= count_of_clusters < 65525.
@ k_ra8_fs_type_unknown
Not yet detected / mount failed.
ra8_io block-device fabric – one LBA vtable across every storage medium.
ra8_err_t ra8_io_blockdev_as_fs_backend(const ra8_io_blockdev_t *bd, ra8_fs_backend_t *out)
Expose a bound block device as an ra8_fs_backend_t for ra8_fs.
ra8_io block-device backend over a hosted USB mass-storage device.
ra8_err_t ra8_io_blockdev_usbmsc_init(ra8_io_blockdev_t *bd, ra8_io_blockdev_usbmsc_state_t *state, uint8_t lun)
Bind a hosted USB mass-storage backend into a caller-owned handle.
SysTick-based tick counter, delay and timestamp helpers.
uint32_t ra8_time_ms(void)
Get the current 1 kHz tick count.
Definition ra8_time.c:108
@ 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_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.
Block-device interface that ra8_fs runs on top of.
Cached parse of one mounted FAT volume.
Caller-allocated block-device handle binding a backend to its context.
Caller-owned private state for a USB mass-storage block device.
Snapshot of the attached MSC device, passed to the attach callback.
uint16_t vendor_id
idVendor from device descriptor.
uint16_t product_id
idProduct from device descriptor.
@ k_selftest_hex_chars_u16
16-bit value -> "ABCD".
@ k_selftest_hex_chars_u32
32-bit value -> "ABCDEF01".
static ra8_err_t selftest_print_dec(uint32_t value)
Print a uint32_t as ASCII decimal.
static ra8_io_blockdev_usbmsc_state_t s_selftest_usb_state
Caller-owned backend state for s_selftest_usb_dev.
@ k_selftest_phase_wp
Write-protect rejection test.
@ k_selftest_phase_mount
Mounting the FAT16 volume.
@ k_selftest_phase_enum
Enumerating the FS device.
@ k_selftest_phase_pass
Full config A pass.
@ k_selftest_phase_host_init
ra8_usb_hmsc_init issued.
@ k_selftest_phase_verify
Streaming + comparing MRAM.BIN.
static ra8_err_t selftest_print_hex(uint32_t value, uint8_t digits)
Print a value as fixed-width uppercase hex.
static ra8_io_blockdev_t s_selftest_usb_dev
Block device fronting the hosted MSC volume for this ladder.
@ k_selftest_wp_probe_lba
Data-region LBA for WP test.
@ k_selftest_ms_per_sec
Milliseconds per second.
@ k_selftest_target_lun
Single-LUN device.
@ k_selftest_burst_bytes
8 x 512 B burst buffer size.
@ k_selftest_burst_blocks
Blocks per READ(10) burst.
@ k_selftest_no_mismatch
Probe: no mismatch found.
@ k_selftest_bytes_per_kib
Bytes per KiB (rate math).
static ra8_err_t selftest_print(const char *text)
Print a NUL-terminated ASCII string over the console.
static volatile uint32_t s_dbg_verified_bytes
Bytes content-verified so far this pass.
static ra8_err_t selftest_print_fail(const char *what, ra8_err_t err)
Print "FAIL <what> err=0xNNNNNNNN" on its own line.
static volatile uint32_t s_dbg_mismatch_off
First mismatching MRAM offset (k_selftest_no_mismatch = none).
static volatile uint32_t s_dbg_verify_ms
Milliseconds the 1 MiB verify streamed for.
@ k_fat_data_lba
First data sector (cluster 2).
@ k_fat_mram_clusters
Clusters backed by MRAM (1 MiB).
@ k_mram_base_addr
MRAM code window base address.
@ k_selftest_block_size
SCSI logical block size (bytes).
Shared constants for the usb_selftest_soak translation units.
@ k_selftest_soak_iters
Soak: 1 MiB verify repeats.
@ k_selftest_bytes_per_mib
Bytes per MiB (aggregate).
Shared SCI8 console + text formatters for the soak self-test.
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_host_enumerate(ra8_usb_hmsc_device_t *out_device)
Bring the host controller up and enumerate the loop device.
ra8_err_t selftest_host_pass(void)
Soak pass: enumerate + mount once, then repeat the 1 MiB verify.
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_print_soak_verdict(uint64_t total_bytes, uint64_t total_ms)
Print the soak aggregate line (iterations + volume + rate).
static ra8_err_t selftest_write_protect_probe(void)
WRITE(10) into the read-only LUN must be rejected.
static ra8_err_t selftest_mount_volume(ra8_fs_mount_t **out_mount)
Mount the loop device's volume through the USB-MSC backend.
Host-side entry point of the soak self-test.
static volatile uint32_t s_dbg_phase
Host-ladder phase marker (wlun_phase_t).
static volatile uint32_t s_dbg_pass_count
Completed full passes (sticky success counter).