ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_selftest_microsd_steps.c
Go to the documentation of this file.
1
26
28
29#include <stdint.h>
30#include <string.h>
31
32#include "ra8_board_ek_ra8d2.h"
33#include "ra8_err.h"
34#include "ra8_usb.h"
35#include "ra8_usb_hmsc.h"
36
37#ifndef RA8_OFF_TARGET
38#include "tx_api.h"
39#include "ux_api.h"
40#include "ux_dcd_ra8_usb.h"
41#include "ux_device_class_storage.h"
42#include "ux_device_stack.h"
43
44/* -------------------------------------------------------------------------- */
45/* ThreadX device worker + USBX pool storage */
46/* -------------------------------------------------------------------------- */
47
54
55/* SCSI INQUIRY strings -- 8 / 16 / 4 byte fields per SBC-3. */
56static UCHAR s_msc_vendor_id[] = "RA8D2 ";
57static UCHAR s_msc_product_id[] = "MICROSD CARD RO ";
58static UCHAR s_msc_product_rev[] = "0001";
59
60/* -------------------------------------------------------------------------- */
61/* J-Link probes (device + host owned) */
62/* -------------------------------------------------------------------------- */
63
65static volatile uint32_t s_dbg_phase;
67static volatile uint32_t s_dbg_luns_ok;
69static volatile uint32_t s_dbg_max_lun;
71static volatile uint32_t s_dbg_mismatch = (uint32_t)k_microsd_no_mismatch;
73static volatile uint32_t s_dbg_pass_count;
75static volatile uint32_t s_dbg_read_calls;
77static volatile uint32_t s_dbg_dev_step;
79static volatile uint32_t s_dbg_dev_err;
80
81/* -------------------------------------------------------------------------- */
82/* USB descriptors (single-interface MSC; multi-LUN is a BOT-level concept) */
83/* -------------------------------------------------------------------------- */
84
85/* MSC config: bulk-only transport, SCSI command set, EP1 IN + EP2 OUT,
86 * 64-byte MPS. The number of LUNs is a class-registration parameter, not
87 * a descriptor field, so this framework is the standard single-interface
88 * MSC blob. PID 0x0015 marks the microSD self-test identity. */
89static UCHAR s_device_framework_fs[] = {
90 /* Device descriptor (USB 2.0 sec 9.6.1) -- 18 bytes. */
91 0x12U,
92 0x01U,
93 0x00U,
94 0x02U,
95 0x00U,
96 0x00U,
97 0x00U,
98 0x40U,
99 0x09U,
100 0x12U,
101 0x15U, /* PID = 0x0015 (pid.codes test). */
102 0x00U,
103 0x00U,
104 0x01U,
105 0x01U,
106 0x02U,
107 0x03U,
108 0x01U,
109 /* Configuration descriptor (32 bytes total). */
110 0x09U,
111 0x02U,
112 0x20U,
113 0x00U,
114 0x01U,
115 0x01U,
116 0x00U,
117 0x80U,
118 0x32U,
119 /* Interface descriptor -- MSC, SCSI, BBB. */
120 0x09U,
121 0x04U,
122 0x00U,
123 0x00U,
124 0x02U,
125 0x08U,
126 0x06U,
127 0x50U,
128 0x00U,
129 /* Bulk-IN endpoint (EP1 IN, 64-byte MPS). */
130 0x07U,
131 0x05U,
132 0x81U,
133 0x02U,
134 0x40U,
135 0x00U,
136 0x00U,
137 /* Bulk-OUT endpoint (EP2 OUT, 64-byte MPS). */
138 0x07U,
139 0x05U,
140 0x02U,
141 0x02U,
142 0x40U,
143 0x00U,
144 0x00U,
145};
146
154static UCHAR s_string_framework[] = {
155 /* idx 1: "Brighton Sikarskie". */
156 0x09U,
157 0x04U,
158 0x01U,
159 0x12U,
160 'B',
161 'r',
162 'i',
163 'g',
164 'h',
165 't',
166 'o',
167 'n',
168 ' ',
169 'S',
170 'i',
171 'k',
172 'a',
173 'r',
174 's',
175 'k',
176 'i',
177 'e',
178 /* idx 2: "RA8D2 MULTILUN". */
179 0x09U,
180 0x04U,
181 0x02U,
182 0x0EU,
183 'R',
184 'A',
185 '8',
186 'D',
187 '2',
188 ' ',
189 'M',
190 'U',
191 'L',
192 'T',
193 'I',
194 'L',
195 'U',
196 'N',
197 /* idx 3: serial. */
198 0x09U,
199 0x04U,
200 0x03U,
201 0x08U,
202 '0',
203 '0',
204 '0',
205 '0',
206 '0',
207 '0',
208 '1',
209 '3',
210};
211
218
219/* -------------------------------------------------------------------------- */
220/* Storage class media callbacks (single read-only microSD LUN) */
221/* -------------------------------------------------------------------------- */
222
251static UINT microsd_msc_read(VOID* storage,
252 ULONG lun,
253 UCHAR* data_pointer,
254 ULONG number_blocks,
255 ULONG lba,
256 ULONG* media_status)
257{
258 (void)storage;
259 (void)lun;
261 if ((lba + number_blocks) > (ULONG)k_microsd_sectors) {
262 *media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(k_scsi_sense_illegal_request,
265 return UX_ERROR;
266 }
267 (void)memcpy(data_pointer,
269 (size_t)(number_blocks * (ULONG)k_microsd_block_size));
270 *media_status = 0UL;
272 return UX_SUCCESS;
273}
274
300static UINT microsd_msc_write(VOID* storage,
301 ULONG lun,
302 UCHAR* data_pointer,
303 ULONG number_blocks,
304 ULONG lba,
305 ULONG* media_status)
306{
307 (void)storage;
308 (void)lun;
309 (void)data_pointer;
310 (void)number_blocks;
311 (void)lba;
312 *media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(k_scsi_sense_data_protect,
315 return UX_ERROR;
316}
317
339static UINT microsd_msc_status(VOID* storage, ULONG lun, ULONG media_id, ULONG* media_status)
340{
341 (void)storage;
342 (void)lun;
343 (void)media_id;
344 *media_status = 0UL;
345 return UX_SUCCESS;
346}
347
348/* -------------------------------------------------------------------------- */
349/* Device side: USBX MSC with one read-only microSD LUN */
350/* -------------------------------------------------------------------------- */
351
369{
370 if (_ux_system_initialize(s_usbx_pool, k_microsd_usbx_pool_bytes, UX_NULL, 0) != UX_SUCCESS) {
371 return UX_ERROR;
372 }
373 return _ux_device_stack_initialize((UCHAR*)UX_NULL,
374 0,
376 sizeof(s_device_framework_fs),
378 sizeof(s_string_framework),
381 UX_NULL);
382}
383
402static void microsd_fill_lun(UX_SLAVE_CLASS_STORAGE_PARAMETER* p, uint32_t idx)
403{
404 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_last_lba =
406 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_block_length =
408 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_type =
409 UX_SLAVE_CLASS_STORAGE_MEDIA_FAT_DISK;
410 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_removable_flag =
411 UX_SLAVE_CLASS_STORAGE_MEDIA_IS_REMOVABLE;
412 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_read_only_flag =
413 UX_TRUE;
414 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_read = microsd_msc_read;
415 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_write =
417 p->ux_slave_class_storage_parameter_lun[idx].ux_slave_class_storage_media_status =
419}
420
440{
441 UX_SLAVE_CLASS_STORAGE_PARAMETER msc_params;
442 (void)memset(&msc_params, 0, sizeof(msc_params));
443 msc_params.ux_slave_class_storage_parameter_number_lun = (ULONG)k_microsd_count;
444 msc_params.ux_slave_class_storage_parameter_vendor_id = s_msc_vendor_id;
445 msc_params.ux_slave_class_storage_parameter_product_id = s_msc_product_id;
446 msc_params.ux_slave_class_storage_parameter_product_rev = s_msc_product_rev;
447 for (uint32_t idx = 0U; idx < (uint32_t)k_microsd_count; idx++) {
448 microsd_fill_lun(&msc_params, idx);
449 }
450 static UCHAR s_class_name[] = "ux_slave_class_storage";
451
452 return _ux_device_stack_class_register(s_class_name,
453 _ux_device_class_storage_entry,
454 1,
455 0,
456 &msc_params);
457}
458
460{
461 (void)arg;
462
464 if (ux != UX_SUCCESS) {
465 s_dbg_dev_err = (uint32_t)ux;
466 return;
467 }
470 if (ux != UX_SUCCESS) {
471 s_dbg_dev_err = (uint32_t)ux;
472 return;
473 }
476 if (e != k_ra8_ok) {
477 s_dbg_dev_err = (uint32_t)e;
478 return;
479 }
482 if (e != k_ra8_ok) {
483 s_dbg_dev_err = (uint32_t)e;
484 return;
485 }
487
488 while (1) {
491 }
492}
493
494/* -------------------------------------------------------------------------- */
495/* Host side: ra8_usb_hmsc enumerate + per-LUN read/verify */
496/* -------------------------------------------------------------------------- */
497
521[[nodiscard]] static ra8_err_t microsd_verify_one(uint32_t lun)
522{
523 static uint8_t s_burst[k_microsd_burst_bytes] = {};
524
525 uint32_t block_count = 0U;
526 uint32_t block_size = 0U;
527 ra8_err_t err = ra8_usb_hmsc_read_capacity((uint8_t)lun, &block_count, &block_size);
528 if (err != k_ra8_ok) {
529 (void)microsd_print_fail("read_capacity", err);
530 return err;
531 }
532 if (block_count != (uint32_t)k_microsd_sectors) {
533 (void)microsd_print_fail("capacity mismatch", k_ra8_err_invalid_size);
535 }
537 (void)microsd_print_fail("no 0x55AA boot sig on SD LBA0", k_ra8_err_invalid_state);
539 }
540 for (uint32_t blk = 0U; blk < (uint32_t)k_microsd_sectors;
541 blk += (uint32_t)k_microsd_burst_blocks) {
542 err = ra8_usb_hmsc_read10((uint8_t)lun, blk, (uint16_t)k_microsd_burst_blocks, s_burst);
543 if (err != k_ra8_ok) {
544 (void)microsd_print_fail("READ(10)", err);
545 return err;
546 }
547 const uint32_t off = blk * (uint32_t)k_microsd_block_size;
549 0) {
550 s_dbg_mismatch = blk;
551 (void)microsd_print_fail("SD data mismatch vs snapshot", k_ra8_err_invalid_state);
553 }
554 }
555 return k_ra8_ok;
556}
557
574[[nodiscard]] static ra8_err_t microsd_print_lun_ok(uint32_t lun)
575{
576 ra8_err_t err = microsd_print("ra8d2 microsd: LUN ");
577 if (err != k_ra8_ok) {
578 return err;
579 }
580 err = microsd_print_dec(lun);
581 if (err != k_ra8_ok) {
582 return err;
583 }
584 return microsd_print(" OK (64 sectors, SD vs snapshot)\r\n");
585}
586
609{
611 ra8_err_t err = ra8_usb_hmsc_enumerate(device);
612 if (err != k_ra8_ok) {
613 (void)microsd_print_fail("enumerate", err);
614 (void)ra8_usb_hmsc_close();
615 return err;
616 }
617 s_dbg_max_lun = (uint32_t)device->max_lun;
618 err = microsd_print("ra8d2 microsd: enumerated pid=0x");
619 if (err != k_ra8_ok) {
620 return err;
621 }
622 err = microsd_print_hex((uint32_t)device->product_id, (uint8_t)k_microsd_hex_chars_u16);
623 if (err != k_ra8_ok) {
624 return err;
625 }
626 err = microsd_print(", GET_MAX_LUN=");
627 if (err != k_ra8_ok) {
628 return err;
629 }
631 if (err != k_ra8_ok) {
632 return err;
633 }
634 return microsd_print("\r\n");
635}
636
654[[nodiscard]] static ra8_err_t microsd_host_pass(void)
655{
657 ra8_err_t err = microsd_print("ra8d2 microsd: host up on USB-HS, probing the loop...\r\n");
658 if (err != k_ra8_ok) {
659 return err;
660 }
662 if (err != k_ra8_ok) {
663 (void)microsd_print_fail("host init", err);
664 return err;
665 }
666
667 ra8_usb_hmsc_device_t device = {};
668 err = microsd_host_enumerate(&device);
669 if (err != k_ra8_ok) {
670 return err;
671 }
672
674 s_dbg_luns_ok = 0U;
675 for (uint32_t lun = 0U; lun < (uint32_t)k_microsd_count; lun++) {
676 err = microsd_verify_one(lun);
677 if (err != k_ra8_ok) {
678 (void)ra8_usb_hmsc_close();
679 return err;
680 }
682 err = microsd_print_lun_ok(lun);
683 if (err != k_ra8_ok) {
684 return err;
685 }
686 }
687
690 err = microsd_print("ra8d2 microsd: USB SELFTEST MICROSD PASS\r\n");
691 if (err != k_ra8_ok) {
692 return err;
693 }
695 return k_ra8_ok;
696}
697
699{
700 (void)arg;
701
703 for (;;) {
704 const ra8_err_t err = microsd_host_pass();
705 if (err == k_ra8_ok) {
706 break;
707 }
709 }
710 while (1) {
712 }
713}
714
715#endif /* !RA8_OFF_TARGET */
static UCHAR s_msc_product_id[]
Definition main.c:197
static UCHAR s_string_framework[]
USBX string descriptor table (vendor / product / serial).
Definition main.c:299
@ k_scsi_ascq_none
ASCQ: none.
Definition main.c:147
@ k_scsi_asc_write_protected
ASC: WRITE PROTECTED.
Definition main.c:149
@ k_scsi_sense_illegal_request
Sense key: ILLEGAL REQUEST.
Definition main.c:145
@ k_scsi_sense_data_protect
Sense key: DATA PROTECT.
Definition main.c:148
@ k_scsi_asc_lba_out_of_range
ASC: LBA out of range.
Definition main.c:146
static UCHAR s_usbx_pool[k_wlun_usbx_pool_bytes]
USBX memory pool (USBX uses tx_byte_pool internally).
Definition main.c:193
@ k_usb_langid_en_us_lo
LANGID 0x0409 low byte.
Definition main.c:359
@ k_usb_langid_en_us_hi
LANGID 0x0409 high byte.
Definition main.c:360
static UCHAR s_device_framework_fs[]
Definition main.c:234
static UCHAR s_msc_product_rev[]
Definition main.c:198
static UCHAR s_language_id_framework[]
USBX language-id table – US English.
Definition main.c:368
static volatile uint32_t s_dbg_read_calls
Device-side media_read invocations.
Definition main.c:213
static volatile uint32_t s_dbg_dev_step
Device worker progress: 1 stack, 2 class, 3 dcd, 4 attach, 5 parked.
Definition main.c:219
static volatile uint32_t s_dbg_dev_err
Device worker first failing return code (0 = none).
Definition main.c:221
static UCHAR s_msc_vendor_id[]
Definition main.c:196
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
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).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
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
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Native USB controller driver public API (device + host modes).
ra8_err_t ra8_usb_device_attach(ra8_usb_speed_t speed, bool attached)
Raise / drop the D+ pull-up to advertise the device to the host.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
@ k_ra8_usb_speed_fs
Full-Speed controller (USBFS @ 0x40250000).
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.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
#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 microsd_verify_one(uint32_t lun)
Read + verify the LUN's sectors against the SD snapshot.
static UINT microsd_msc_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
Storage media-status callback.
static UINT microsd_usbx_stack_up(void)
Bring USBX system + device stack up with the MSC framework.
static ra8_err_t microsd_host_enumerate(ra8_usb_hmsc_device_t *device)
Enumerate the looped device and print its PID + GET_MAX_LUN.
static ra8_err_t microsd_host_pass(void)
One full host-side pass: enumerate, verify the SD snapshot.
static UINT microsd_class_register(void)
Register the Mass-Storage class with one read-only LUN.
static UINT microsd_msc_read(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-read callback: serve the boot-time SD snapshot.
VOID microsd_host_worker(ULONG arg)
Host-side worker: retry the full pass until it succeeds.
static void microsd_fill_lun(UX_SLAVE_CLASS_STORAGE_PARAMETER *p, uint32_t idx)
Populate the LUN parameter slot with geometry + callbacks.
static UINT microsd_msc_write(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-write callback: reject (all LUNs are read-only).
static ra8_err_t microsd_print_lun_ok(uint32_t lun)
Print "LUN n OK (256 sectors)" for a verified logical unit.
VOID microsd_device_worker(ULONG arg)
Device-side worker: bring the read-only SD FS device up, then park.
examples/ek_ra8d2/hw_validated/hil/usb_selftest_microsd/inc/usb_selftest_microsd_steps....
ra8_err_t microsd_print_fail(const char *what, ra8_err_t err)
Print "FAIL <what> err=0xNNNNNNNN" on its own console line.
ra8_err_t microsd_print_dec(uint32_t value)
Print a uint32_t as ASCII decimal over the SCI8 console.
@ k_microsd_hex_chars_u16
16-bit value -> "ABCD".
ra8_err_t microsd_print(const char *text)
Print a NUL-terminated ASCII string over the SCI8 console.
unsigned char s_usb_selftest_microsd_sd_snapshot[(uint32_t) k_microsd_snap_bytes]
Read-only RAM snapshot of SD LBA 0..63, taken once at boot.
Definition main.c:215
@ k_microsd_boot_wait_ticks
Host start delay (1 ms ticks).
@ k_microsd_idle_ticks
Parked-loop back-off (ticks).
@ k_microsd_usbx_pool_bytes
USBX memory pool (bytes).
@ k_microsd_retry_ticks
Pause between ladder retries.
@ k_microsd_phase_pass
All LUNs verified.
@ k_microsd_phase_init
ra8_usb_hmsc_init issued.
@ k_microsd_phase_verify
Reading + checking LUNs.
@ k_microsd_phase_enum
Enumerating.
@ k_microsd_block_size
SCSI logical block size.
@ k_microsd_no_mismatch
Probe: no mismatch.
@ k_microsd_burst_blocks
Blocks per READ(10) burst.
@ k_microsd_sectors
Exposed sectors (LBA 0..63).
@ k_microsd_count
Single read-only logical unit.
@ k_microsd_burst_bytes
8 x 512 B burst buffer.
@ k_microsd_dev_step_stack
USBX system + device stack up.
@ k_microsd_dev_step_attach
Device attached (DPRPU).
@ k_microsd_dev_step_class
MSC class registered.
@ k_microsd_dev_step_dcd
DCD bridge initialized.
@ k_microsd_dev_step_parked
Bring-up done; worker parked.
ra8_err_t microsd_print_hex(uint32_t value, uint8_t digits)
Print a value as fixed-width uppercase hex over the SCI8 console.
volatile uint32_t s_usb_selftest_microsd_dbg_bootsig
1 = LBA0 carries the 0x55AA FAT/exFAT boot signature.
Definition main.c:201
static volatile uint32_t s_dbg_phase
Host-ladder phase marker (wlun_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_pass_count
Completed full passes (sticky success counter).
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).
USBX device-controller-driver (DCD) bridge to ra8_usb.
ra8_err_t ux_dcd_ra8_usb_initialize(ra8_usb_speed_t speed)
Register the ra8_usb bridge as the active USBX DCD.