ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ns_usb_host.c
Go to the documentation of this file.
1
30
31#include <stdint.h>
32#include <string.h>
33
34#include "ns_usb_internal.h"
35#include "ra8_usb.h"
36#include "tx_api.h"
37
38/* =============================================================================
39 * Host-side bench milestone counters (NS .bss; J-Link reads these)
40 * =============================================================================
41 */
42
50volatile uint32_t g_tz_usb_host_phase;
51
58volatile uint32_t g_tz_usb_host_pid;
59
67volatile uint32_t g_tz_usb_host_rounds_ok;
68
75volatile uint32_t g_tz_usb_host_err;
76
77/* =============================================================================
78 * HS host: polled CDC enumerate + bulk echo over the self-loop
79 * =============================================================================
80 */
81
89
96
102CHAR s_ns_host_thread_name[] = "ns_usb_host";
103
117
143
159static void ns_host_pattern_fill(uint32_t round, uint8_t* out, uint32_t len)
160{
161 for (uint32_t i = 0U; i < len; i++) {
162 const uint32_t v = (round * (uint32_t)k_ns_pat_round_mul) + (i * (uint32_t)k_ns_pat_idx_mul) +
163 (uint32_t)k_ns_pat_bias;
164 out[i] = (uint8_t)(v & (uint32_t)k_ns_byte_mask);
165 }
166}
167
181[[nodiscard]] static ra8_err_t ns_host_get_dev_desc(uint8_t* desc)
182{
183 const ra8_usb_setup_t setup = {
184 .bm_request_type = (uint8_t)k_ns_bm_std_dev_in,
185 .b_request = (uint8_t)k_ns_breq_get_desc,
186 .w_value = (uint16_t)((uint16_t)k_ns_desc_device << (uint16_t)k_ns_byte_bits),
187 .w_index = 0U,
188 .w_length = (uint16_t)k_ns_dev_desc_len,
189 };
190 uint16_t rx = 0U;
191 const ra8_err_t err =
193 if (err != k_ra8_ok) {
194 return err;
195 }
196 return (rx == (uint16_t)k_ns_dev_desc_len) ? k_ra8_ok : k_ra8_err_hw_error;
197}
198
212[[nodiscard]] static ra8_err_t ns_host_enum_hunt(uint8_t* desc)
213{
215 const uint32_t t0 = ra8_time_ms();
216 for (uint32_t spin = 0U; spin < (uint32_t)k_ns_attach_spin; spin++) {
218 break;
219 }
220 if ((ra8_time_ms() - t0) > (uint32_t)k_ns_attach_to_ms) {
221 break;
222 }
223 }
226 for (uint8_t attempt = 0U; attempt < (uint8_t)k_ns_enum_tries; attempt++) {
233 err = ns_host_get_dev_desc(desc);
234 if (err == k_ra8_ok) {
235 return k_ra8_ok;
236 }
237 }
238 return err;
239}
240
252[[nodiscard]] static ra8_err_t ns_host_set_address(void)
253{
254 const ra8_usb_setup_t setup = {
255 .bm_request_type = (uint8_t)k_ns_bm_std_dev_out,
256 .b_request = (uint8_t)k_ns_breq_set_addr,
257 .w_value = (uint16_t)k_ns_dev_addr,
258 .w_index = 0U,
259 .w_length = 0U,
260 };
261 const ra8_err_t err = ra8_usb_host_control_xfer(k_ra8_usb_speed_hs, &setup, nullptr, 0U, nullptr);
262 if (err != k_ra8_ok) {
263 return err;
264 }
267}
268
280[[nodiscard]] static ra8_err_t ns_host_set_config(void)
281{
282 const ra8_usb_setup_t setup = {
283 .bm_request_type = (uint8_t)k_ns_bm_std_dev_out,
284 .b_request = (uint8_t)k_ns_breq_set_config,
285 .w_value = (uint16_t)k_ns_config_value,
286 .w_index = 0U,
287 .w_length = 0U,
288 };
289 return ra8_usb_host_control_xfer(k_ra8_usb_speed_hs, &setup, nullptr, 0U, nullptr);
290}
291
303[[nodiscard]] static ra8_err_t ns_host_open_pipes(void)
304{
306 (uint8_t)k_ns_host_pipe_out,
307 (uint8_t)k_ns_dev_addr,
308 (uint8_t)k_ns_ep_out_num,
309 false,
310 (uint16_t)k_ns_mps);
311 if (err != k_ra8_ok) {
312 return err;
313 }
315 (uint8_t)k_ns_host_pipe_in,
316 (uint8_t)k_ns_dev_addr,
317 (uint8_t)k_ns_ep_in_num,
318 true,
319 (uint16_t)k_ns_mps);
320}
321
334[[nodiscard]] static ra8_err_t ns_host_enumerate(uint32_t* out_pid)
335{
336 uint8_t desc[k_ns_dev_desc_len] = {};
337 ra8_err_t err = ns_host_enum_hunt(desc);
338 if (err != k_ra8_ok) {
339 return err;
340 }
341 *out_pid = (uint32_t)desc[k_ns_off_dev_pid] |
342 ((uint32_t)desc[(uint32_t)k_ns_off_dev_pid + 1U] << (uint32_t)k_ns_byte_bits);
343 err = ns_host_set_address();
344 if (err != k_ra8_ok) {
345 return err;
346 }
347 err = ns_host_set_config();
348 if (err != k_ra8_ok) {
349 return err;
350 }
351 return ns_host_open_pipes();
352}
353
368[[nodiscard]] static ra8_err_t ns_host_echo_round(uint32_t round)
369{
370 static uint8_t s_tx[k_ns_payload] = {};
371 static uint8_t s_rx[k_ns_echo_buf] = {};
372 ns_host_pattern_fill(round, s_tx, (uint32_t)k_ns_payload);
374 (uint8_t)k_ns_host_pipe_out,
375 s_tx,
376 (uint16_t)k_ns_payload);
377 if (err != k_ra8_ok) {
378 return err;
379 }
380 uint16_t rx = 0U;
382 (uint8_t)k_ns_host_pipe_in,
383 s_rx,
384 (uint16_t)k_ns_echo_buf,
385 &rx);
386 if (err != k_ra8_ok) {
387 return err;
388 }
389 if (rx != (uint16_t)k_ns_payload) {
391 }
392 if (memcmp(s_rx, s_tx, (size_t)k_ns_payload) != 0) {
394 }
395 return k_ra8_ok;
396}
397
399{
400 (void)arg;
402
403 uint32_t pid = 0U;
404 while (1) {
407 if (err != k_ra8_ok) {
408 g_tz_usb_host_err = (uint32_t)err;
410 continue;
411 }
413 err = ns_host_enumerate(&pid);
414 if (err != k_ra8_ok) {
415 g_tz_usb_host_err = (uint32_t)err;
418 continue;
419 }
420 g_tz_usb_host_pid = pid;
422 break;
423 }
424
425 /* Enumerated. Run bulk echo rounds forever; rounds_ok advancing is the
426 * end-to-end self-loop proof (host bulk-OUT -> device auto-echo -> host
427 * bulk-IN, byte-checked). */
429 uint32_t round = 0U;
430 while (1) {
431 const ra8_err_t err = ns_host_echo_round(round);
432 if (err == k_ra8_ok) {
434 } else if (g_tz_usb_host_err == 0U) {
435 g_tz_usb_host_err = (uint32_t)err;
436 }
437 round += 1U;
438 }
439}
static ra8_err_t ns_host_enum_hunt(uint8_t *desc)
Wait for attach, then bus-reset + read the device descriptor.
volatile uint32_t g_tz_usb_host_pid
idProduct the HS host read from the looped FS device (expect 0x000A).
Definition ns_usb_host.c:58
volatile uint32_t g_tz_usb_host_err
First non-OK ra8_err_t from the host ladder (0 = none yet).
Definition ns_usb_host.c:75
volatile uint32_t g_tz_usb_host_phase
HS-host ladder phase: 0 boot, 1 host-init, 2 enumerating, 3 echoing, 4 first full pass done.
Definition ns_usb_host.c:50
static ra8_err_t ns_host_open_pipes(void)
Open the host bulk pipes for the device's CDC data endpoints.
static ra8_err_t ns_host_set_address(void)
SET_ADDRESS to k_ns_dev_addr, then retarget the DCP.
VOID ns_host_worker(ULONG arg)
HS host worker – enumerate the looped FS device, then echo forever.
static void ns_host_pattern_fill(uint32_t round, uint8_t *out, uint32_t len)
Fill an echo payload with this round's deterministic bytes.
static ra8_err_t ns_host_echo_round(uint32_t round)
One echo round: bulk-OUT a pattern, bulk-IN the echo, compare.
static ra8_err_t ns_host_enumerate(uint32_t *out_pid)
Full enumeration ladder: hunt, SET_ADDRESS, SET_CONFIG, open pipes.
ns_host_tune_t
Host enumeration timing / retry / geometry tunables.
@ k_ns_ep_in_num
Device bulk-IN endpoint number.
@ k_ns_pat_round_mul
Per-round pattern multiplier.
@ k_ns_attach_spin
Attach spin cap (frozen-tick guard).
@ k_ns_boot_wait_tk
Host start delay (ticks).
@ k_ns_addr_settle_ms
Post-SET_ADDRESS recovery.
@ k_ns_payload
Bytes per echo round (sub-MPS).
@ k_ns_host_pipe_out
Host pipe for the device bulk-OUT.
@ k_ns_mps
Bulk endpoint wMaxPacketSize (FS).
@ k_ns_attach_to_ms
Wait for the D+ pull-up.
@ k_ns_byte_mask
Byte mask.
@ k_ns_reset_hold_ms
USB bus-reset hold (>=10 ms).
@ k_ns_pat_idx_mul
Per-index pattern multiplier.
@ k_ns_vbus_settle_ms
VBUS settle before probing.
@ k_ns_enum_tries
Reset+probe attempts.
@ k_ns_host_pipe_in
Host pipe for the device bulk-IN.
@ k_ns_retry_tk
Pause between failed enum passes.
@ k_ns_debounce_ms
Post-attach debounce (>=100 ms).
@ k_ns_ep_out_num
Device bulk-OUT endpoint number.
@ k_ns_pat_bias
Pattern constant bias.
@ k_ns_dev_addr
Address the host assigns.
@ k_ns_echo_buf
One-MPS host scratch buffer.
@ k_ns_recovery_ms
Post-reset recovery (TRSTRCY).
ns_host_req_t
Chapter-9 standard request / descriptor constants for the host.
@ k_ns_dev_desc_len
DEVICE descriptor length.
@ k_ns_breq_set_config
SET_CONFIGURATION.
@ k_ns_breq_get_desc
GET_DESCRIPTOR.
@ k_ns_bm_std_dev_out
bmRequestType: Std | Device | Out.
@ k_ns_breq_set_addr
SET_ADDRESS.
@ k_ns_desc_device
DEVICE descriptor type.
@ k_ns_bm_std_dev_in
bmRequestType: Std | Device | In.
@ k_ns_off_dev_pid
idProduct LSB byte offset.
@ k_ns_config_value
bConfigurationValue to select.
@ k_ns_byte_bits
Bits per byte.
static ra8_err_t ns_host_set_config(void)
SET_CONFIGURATION(::k_ns_config_value) on the addressed device.
volatile uint32_t g_tz_usb_host_rounds_ok
Bulk echo rounds the HS host has verified byte-equal (advances forever once the loop is healthy – the...
Definition ns_usb_host.c:67
static ra8_err_t ns_host_get_dev_desc(uint8_t *desc)
GET_DESCRIPTOR(DEVICE) over the polled host control engine.
Private split-seam shared between ns_usb.c and ns_usb_host.c (#96).
TX_THREAD s_ns_host_thread
ThreadX TCB for the HS host worker (defined in ns_usb_host.c).
Definition ns_usb_host.c:88
CHAR s_ns_host_thread_name[]
HS host worker thread name (defined in ns_usb_host.c; ThreadX CHAR*).
@ k_ns_host_stack_bytes
HS host worker stack (bytes).
UCHAR s_ns_host_stack[k_ns_host_stack_bytes]
Stack backing storage for s_ns_host_thread (defined in ns_usb_host.c).
Definition ns_usb_host.c:95
@ 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.
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_bulk_out(ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
Transmit one bulk packet to the device and wait for the ACK.
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
char CHAR
ThreadX-compatible CHAR (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Opaque thread stand-in for the host build.
Decoded 8-byte USB SETUP packet.