ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_selftest_hid_host.c
Go to the documentation of this file.
1
27
28#include <stdint.h>
29#include <string.h>
30
31#include "ra8_board_ek_ra8d2.h"
32#include "ra8_err.h"
33#include "ra8_time.h"
34#include "ra8_usb.h"
36
37#ifndef RA8_OFF_TARGET
38
39#include "tx_api.h"
40
52
53/* -------------------------------------------------------------------------- */
54/* J-Link probes (host side) */
55/* -------------------------------------------------------------------------- */
56
58static volatile uint32_t s_dbg_phase;
60static volatile uint32_t s_dbg_rounds_ok;
62static volatile uint32_t s_dbg_pid;
64static volatile uint32_t s_dbg_mismatch = (uint32_t)k_hid_no_mismatch;
66static volatile uint32_t s_dbg_pass_count;
68static volatile uint32_t s_dbg_last_seq;
69
70/* -------------------------------------------------------------------------- */
71/* Host side: self-contained polled enumerate + HID interrupt-IN read */
72/* -------------------------------------------------------------------------- */
73
90
105
123[[nodiscard]] static ra8_err_t hid_ctrl_get_dev_desc(uint8_t* desc)
124{
125 const ra8_usb_setup_t setup = {
126 .bm_request_type = (uint8_t)k_hid_bm_std_dev_in,
127 .b_request = (uint8_t)k_hid_breq_get_desc,
128 .w_value = (uint16_t)((uint16_t)k_hid_desc_device << (uint16_t)k_hid_byte_bits),
129 .w_index = 0U,
130 .w_length = (uint16_t)k_hid_dev_desc_len,
131 };
132 uint16_t rx = 0U;
133 const ra8_err_t err =
135 if (err != k_ra8_ok) {
136 return err;
137 }
138 if (rx != (uint16_t)k_hid_dev_desc_len) {
139 return k_ra8_err_hw_error;
140 }
141 return k_ra8_ok;
142}
143
166[[nodiscard]] static ra8_err_t hid_enum_hunt(uint8_t* desc)
167{
169 const uint32_t t0 = ra8_time_ms();
170 for (uint32_t spin = 0U; spin < (uint32_t)k_hid_attach_spin; spin++) {
172 break;
173 }
174 if ((ra8_time_ms() - t0) > (uint32_t)k_hid_attach_to_ms) {
175 break;
176 }
177 }
180 for (uint8_t attempt = 0U; attempt < (uint8_t)k_hid_enum_tries; attempt++) {
187 err = hid_ctrl_get_dev_desc(desc);
188 if (err == k_ra8_ok) {
189 return k_ra8_ok;
190 }
191 }
192 return err;
193}
194
209[[nodiscard]] static ra8_err_t hid_enum_set_address(void)
210{
211 const ra8_usb_setup_t setup = {
212 .bm_request_type = (uint8_t)k_hid_bm_std_dev_out,
213 .b_request = (uint8_t)k_hid_breq_set_addr,
214 .w_value = (uint16_t)k_hid_dev_addr,
215 .w_index = 0U,
216 .w_length = 0U,
217 };
218 ra8_err_t err = ra8_usb_host_control_xfer(k_ra8_usb_speed_hs, &setup, nullptr, 0U, nullptr);
219 if (err != k_ra8_ok) {
220 return err;
221 }
224}
225
240[[nodiscard]] static ra8_err_t hid_enum_set_config(void)
241{
242 const ra8_usb_setup_t setup = {
243 .bm_request_type = (uint8_t)k_hid_bm_std_dev_out,
244 .b_request = (uint8_t)k_hid_breq_set_config,
245 .w_value = (uint16_t)k_hid_config_value,
246 .w_index = 0U,
247 .w_length = 0U,
248 };
249 return ra8_usb_host_control_xfer(k_ra8_usb_speed_hs, &setup, nullptr, 0U, nullptr);
250}
251
271[[nodiscard]] static ra8_err_t hid_open_pipes(void)
272{
274 (uint8_t)k_hid_pipe_in,
275 (uint8_t)k_hid_dev_addr,
276 (uint8_t)k_hid_ep_in_num,
277 true,
278 (uint16_t)k_hid_mps);
279}
280
301[[nodiscard]] static ra8_err_t hid_enumerate(uint32_t* out_pid)
302{
303 uint8_t desc[k_hid_dev_desc_len] = {};
304 ra8_err_t err = hid_enum_hunt(desc);
305 if (err != k_ra8_ok) {
306 (void)hid_print_fail("enumerate", err);
307 return err;
308 }
309 *out_pid = (uint32_t)desc[k_hid_off_dev_pid] |
310 ((uint32_t)desc[(uint32_t)k_hid_off_dev_pid + 1U] << (uint32_t)k_hid_byte_bits);
311 err = hid_enum_set_address();
312 if (err != k_ra8_ok) {
313 (void)hid_print_fail("set_address", err);
314 return err;
315 }
316 err = hid_enum_set_config();
317 if (err != k_ra8_ok) {
318 (void)hid_print_fail("set_config", err);
319 return err;
320 }
321 err = hid_open_pipes();
322 if (err != k_ra8_ok) {
323 (void)hid_print_fail("open_pipes", err);
324 }
325 return err;
326}
327
344[[nodiscard]] static ra8_err_t hid_print_enum(uint32_t pid)
345{
346 ra8_err_t err = hid_print("ra8d2 hid: enumerated pid=0x");
347 if (err != k_ra8_ok) {
348 return err;
349 }
350 err = hid_print_hex(pid, (uint8_t)k_hid_hex_chars_u16);
351 if (err != k_ra8_ok) {
352 return err;
353 }
354 return hid_print("\r\n");
355}
356
371[[nodiscard]] static ra8_err_t hid_print_pass(void)
372{
373 ra8_err_t err = hid_print("ra8d2 hid: ");
374 if (err != k_ra8_ok) {
375 return err;
376 }
377 err = hid_print_dec((uint32_t)k_hid_rounds);
378 if (err != k_ra8_ok) {
379 return err;
380 }
381 return hid_print(" reports verified -- USB SELFTEST HID PASS\r\n");
382}
383
408[[nodiscard]] static ra8_err_t hid_read_round(uint32_t round)
409{
410 static uint8_t s_expect[k_hid_read_buf] = {};
411 static uint8_t s_rx[k_hid_read_buf] = {};
412 hid_fill_report_body(s_expect, (uint32_t)k_hid_report_len);
413 uint16_t rx = 0U;
415 (uint8_t)k_hid_pipe_in,
416 s_rx,
417 (uint16_t)k_hid_read_buf,
418 &rx);
419 if (err != k_ra8_ok) {
420 (void)hid_print_fail("report read", err);
421 return err;
422 }
423 if (rx != (uint16_t)k_hid_report_len) {
424 s_dbg_mismatch = round;
425 (void)hid_print_fail("report length", k_ra8_err_invalid_size);
427 }
428 const size_t body = (size_t)((uint32_t)k_hid_report_len - (uint32_t)k_hid_body_idx);
429 if (memcmp(&s_rx[k_hid_body_idx], &s_expect[k_hid_body_idx], body) != 0) {
430 s_dbg_mismatch = round;
431 (void)hid_print_fail("report pattern mismatch", k_ra8_err_invalid_state);
433 }
434 s_dbg_last_seq = (uint32_t)s_rx[k_hid_seq_idx];
435 return k_ra8_ok;
436}
437
455[[nodiscard]] static ra8_err_t hid_host_pass(void)
456{
457 s_dbg_phase = (uint32_t)k_hid_phase_init;
458 ra8_err_t err = hid_print("ra8d2 hid: host up on USB-HS, probing the loop...\r\n");
459 if (err != k_ra8_ok) {
460 return err;
461 }
463 if (err != k_ra8_ok) {
464 (void)hid_print_fail("host init", err);
465 return err;
466 }
467
468 s_dbg_phase = (uint32_t)k_hid_phase_enum;
469 uint32_t pid = 0U;
470 err = hid_enumerate(&pid);
471 if (err != k_ra8_ok) {
473 return err;
474 }
475 s_dbg_pid = pid;
476 err = hid_print_enum(pid);
477 if (err != k_ra8_ok) {
478 return err;
479 }
480
482 s_dbg_rounds_ok = 0U;
483 for (uint32_t r = 0U; r < (uint32_t)k_hid_rounds; r++) {
484 err = hid_read_round(r);
485 if (err != k_ra8_ok) {
487 return err;
488 }
490 }
491
492 s_dbg_phase = (uint32_t)k_hid_phase_pass;
494 err = hid_print_pass();
495 if (err != k_ra8_ok) {
496 return err;
497 }
499 return k_ra8_ok;
500}
501
503{
504 (void)arg;
505
507 for (;;) {
508 const ra8_err_t err = hid_host_pass();
509 if (err == k_ra8_ok) {
510 break;
511 }
513 }
514 while (1) {
516 }
517}
518
519#endif /* !RA8_OFF_TARGET */
static volatile uint32_t s_dbg_pid
Device-reported product id captured at enumeration.
Definition main.c:208
hid_phase_t
J-Link probe values marking host-ladder progress.
Definition main.c:124
@ k_hid_phase_enum
Enumerating.
Definition main.c:127
@ k_hid_phase_boot
Host thread not started.
Definition main.c:125
@ k_hid_phase_pass
All reports verified.
Definition main.c:129
@ k_hid_phase_verify
Reading + checking reports.
Definition main.c:128
@ k_hid_phase_init
Host controller init.
Definition main.c:126
static volatile uint32_t s_dbg_last_seq
Seq byte of the most recent report the host read back.
Definition main.c:180
hid_usb_req_t
Standard chapter-9 request / descriptor constants for the host.
Definition main.c:216
@ k_hid_desc_device
DEVICE descriptor type.
Definition main.c:222
@ k_hid_dev_desc_len
DEVICE descriptor length.
Definition main.c:223
@ k_hid_bm_std_dev_out
bmRequestType: Std | Device | Out.
Definition main.c:218
@ k_hid_config_value
bConfigurationValue to select.
Definition main.c:226
@ k_hid_byte_bits
Bits per byte.
Definition main.c:225
@ k_hid_off_dev_pid
idProduct LSB byte offset.
Definition main.c:224
@ k_hid_breq_set_config
SET_CONFIGURATION.
Definition main.c:221
@ k_hid_bm_std_dev_in
bmRequestType: Std | Device | In.
Definition main.c:217
@ k_hid_breq_set_addr
SET_ADDRESS.
Definition main.c:220
@ k_hid_breq_get_desc
GET_DESCRIPTOR.
Definition main.c:219
hid_enum_tune_t
Timing / retry tunables for the polled enumeration ladder.
Definition main.c:233
@ k_hid_enum_tries
Reset+probe attempts.
Definition main.c:240
@ k_hid_vbus_settle_ms
VBUS settle before probing.
Definition main.c:234
@ k_hid_recovery_ms
Post-reset recovery (TRSTRCY).
Definition main.c:238
@ k_hid_addr_settle_ms
Post-SET_ADDRESS recovery.
Definition main.c:239
@ k_hid_reset_hold_ms
USB bus-reset hold (>=10 ms).
Definition main.c:237
@ k_hid_attach_spin
Attach spin cap (frozen-tick guard).
Definition main.c:241
@ k_hid_attach_to_ms
Wait for the D+ pull-up.
Definition main.c:235
@ k_hid_debounce_ms
Post-attach debounce (>=100 ms).
Definition main.c:236
static volatile uint32_t s_dbg_rounds_ok
Reports the host confirmed pattern-equal (expect k_hid_rounds).
Definition main.c:172
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_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
@ 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.
SysTick-based tick counter, delay and timestamp helpers.
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
uint32_t ra8_time_ms(void)
Get the current 1 kHz tick count.
Definition ra8_time.c:108
Native USB controller driver public API (device + host modes).
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
ra8_err_t ra8_usb_host_bus_reset(ra8_usb_speed_t speed, bool assert_reset)
Drive (or release) the bus reset line.
uint16_t ra8_usb_host_line_state(ra8_usb_speed_t speed)
Read the host port's D+/D- line state (SYSSTS0.LNST).
ra8_err_t ra8_usb_host_pipe_setup(ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t dev_addr, uint8_t ep_num, bool device_to_host, uint16_t max_packet)
Configure a controller pipe against an attached device's bulk endpoint.
ra8_err_t ra8_usb_host_bulk_in(ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t *buf, uint16_t max_len, uint16_t *out_received)
Receive a bulk transfer from the device into buf.
ra8_err_t ra8_usb_host_init(ra8_usb_speed_t speed)
Bring up a USB controller in HOST mode.
ra8_err_t ra8_usb_host_deinit(ra8_usb_speed_t speed)
Tear down a host-mode controller and drop its MSTP reference.
ra8_err_t ra8_usb_host_control_xfer(ra8_usb_speed_t speed, const ra8_usb_setup_t *setup, uint8_t *data, uint16_t data_len, uint16_t *out_received)
Run a complete host control transfer (SETUP, optional DATA, STATUS).
ra8_err_t ra8_usb_host_set_uact(ra8_usb_speed_t speed, bool enable)
Enable / disable SOF (Start-of-Frame) generation on the bus.
ra8_err_t ra8_usb_host_set_target(ra8_usb_speed_t speed, uint8_t dev_addr)
Retarget the host's default control pipe at a device address.
#define tx_thread_sleep
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Decoded 8-byte USB SETUP packet.
ra8_err_t hid_print(const char *text)
Print a NUL-terminated ASCII string over the console.
ra8_err_t hid_print_fail(const char *what, ra8_err_t err)
Print "FAIL <what> err=0xNNNNNNNN" on its own line.
ra8_err_t hid_print_hex(uint32_t value, uint8_t digits)
Print a value as fixed-width uppercase hex.
@ k_hid_hex_chars_u16
16-bit value -> "ABCD".
void hid_fill_report_body(uint8_t *out, uint32_t len)
Fill the fixed body of a HID report (bytes 1..len-1).
ra8_err_t hid_print_dec(uint32_t value)
Print a uint32_t as ASCII decimal.
@ k_hid_report_len
Vendor input report width (bytes).
@ k_hid_ep_in_num
Device interrupt-IN endpoint num.
@ k_hid_rounds
Reports the host reads + checks.
@ k_hid_pipe_in
Host pipe for the device IN.
@ k_hid_mps
Interrupt endpoint wMaxPacketSize.
@ k_hid_no_mismatch
Probe: no mismatch.
@ k_hid_read_buf
One-MPS receive buffer (bytes).
@ k_hid_dev_addr
Address the host assigns.
@ k_hid_body_idx
Report body starts at byte 1.
@ k_hid_seq_idx
Report byte 0: modifier / rolling seq.
@ k_hid_idle_ticks
Parked-loop back-off (ticks).
@ k_hid_retry_ticks
Pause between ladder retries.
@ k_hid_boot_wait_ticks
Host start delay (1 ms ticks).
static ra8_err_t hid_read_round(uint32_t round)
One report round: read an interrupt-IN report, check its body.
VOID hid_host_worker(ULONG arg)
Host-side worker: retry the full pass until it succeeds.
static ra8_err_t hid_print_enum(uint32_t pid)
Print "enumerated pid=0xNNNN" for the looped device.
static ra8_err_t hid_enum_hunt(uint8_t *desc)
Wait for the device to attach, then bus-reset + read its descriptor.
static ra8_err_t hid_enumerate(uint32_t *out_pid)
Run the full enumeration ladder and open the bulk pipes.
static ra8_err_t hid_print_pass(void)
Print "N reports verified -- USB SELFTEST HID PASS".
static ra8_err_t hid_open_pipes(void)
Open the host receive pipe for the device's HID interrupt-IN endpoint.
static ra8_err_t hid_enum_set_address(void)
SET_ADDRESS to k_hid_dev_addr, then retarget the DCP.
static ra8_err_t hid_enum_set_config(void)
SET_CONFIGURATION(::k_hid_config_value) on the addressed device.
static ra8_err_t hid_host_pass(void)
One full host-side pass: enumerate, then read + check reports.
static ra8_err_t hid_ctrl_get_dev_desc(uint8_t *desc)
GET_DESCRIPTOR(DEVICE) over the polled control engine.
Shared contract for the USB HID self-loop console + host clusters.
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).
static volatile uint32_t s_dbg_mismatch
First mismatching sector, or k_wlun_no_mismatch.