36#include "ux_device_stack.h"
38#include "ux_utility.h"
70typedef enum : uint8_t {
175typedef enum : uint16_t {
217 if ((intsts0 & valid_bit) != 0U) {
223 if ((intsts0 & ctrt_bit) != 0U) {
226 const uint16_t interesting_mask = (uint16_t)(ctrt_bit | valid_bit | dvst_bit);
227 if ((intsts0 & interesting_mask) != 0U) {
274 g_dcd.pipes[i].dir_in == 0U) {
281 const uint16_t out_mps =
g_dcd.pipes[i].max_pkt;
288 if (out_mps != 0U && (len % out_mps) == 0U) {
326 const uint16_t total = (uint16_t)tr->ux_slave_transfer_request_requested_length;
327 const uint16_t sent = (uint16_t)tr->ux_slave_transfer_request_actual_length;
328 const uint16_t mps =
g_dcd.pipes[i].max_pkt;
329 const uint16_t rem = (uint16_t)(total - sent);
330 const uint16_t chunk = (rem > mps) ? mps : rem;
336 tr->ux_slave_transfer_request_actual_length = (
ULONG)((uint32_t)sent + (uint32_t)chunk);
369 const uint16_t pipe_bit = (uint16_t)(1U << i);
370 const uint16_t total = (uint16_t)tr->ux_slave_transfer_request_requested_length;
371 const uint16_t sent = (uint16_t)tr->ux_slave_transfer_request_actual_length;
372 const uint16_t ctr = reg->
PIPECTR[i - 1U];
381 if ((reg->
BEMPSTS & pipe_bit) == 0U) {
416 if (reg ==
nullptr) {
419 const uint16_t pipe_bit = (uint16_t)(1U << i);
420 const uint16_t total = (uint16_t)tr->ux_slave_transfer_request_requested_length;
421 const uint16_t sent = (uint16_t)tr->ux_slave_transfer_request_actual_length;
433 if ((reg->
BEMPSTS & pipe_bit) == 0U) {
447 reg->
BEMPSTS = (uint16_t)(~pipe_bit);
451 reg->
BEMPSTS = (uint16_t)(~pipe_bit);
458 if (tr->ux_slave_transfer_request_force_zlp == (
ULONG)UX_TRUE) {
459 tr->ux_slave_transfer_request_force_zlp = (
ULONG)UX_FALSE;
464 tr->ux_slave_transfer_request_completion_code = UX_SUCCESS;
465 g_dcd.pipes[i].xfer =
nullptr;
466#ifndef UX_DEVICE_STANDALONE
467 (void)tx_semaphore_put(&tr->ux_slave_transfer_request_semaphore);
497 uint16_t trace_len = now;
517 tr->ux_slave_transfer_request_completion_code = UX_SUCCESS;
518 g_dcd.pipes[i].xfer =
nullptr;
519#ifndef UX_DEVICE_STANDALONE
520 (void)tx_semaphore_put(&tr->ux_slave_transfer_request_semaphore);
553 const uint16_t total = (uint16_t)tr->ux_slave_transfer_request_requested_length;
554 const uint16_t mps =
g_dcd.pipes[i].max_pkt;
560 const uint16_t got = (uint16_t)tr->ux_slave_transfer_request_actual_length;
561 uint16_t want = (uint16_t)(total - got);
568 &tr->ux_slave_transfer_request_data_pointer[got],
573 g_diag.irq_walk_pipe2_no_data++;
578 g_diag.irq_walk_pipe2_complete++;
580 const uint16_t now = (uint16_t)(got + len);
581 tr->ux_slave_transfer_request_actual_length = (
ULONG)now;
621 if (
g_dcd.pipes[i].dir_in != 0U) {
624 if (
g_dcd.pipes[i].ep_addr == 0U) {
676 UX_SLAVE_TRANSFER* tr =
g_dcd.pipes[i].xfer;
683 g_diag.irq_walk_pipe2_seen++;
685 if (
g_dcd.pipes[i].dir_in != 0U) {
723 const bool have_ctrt = (intsts0 & ctrt_bit) != 0U;
724 const bool have_valid = (intsts0 & valid_bit) != 0U;
725 const bool have_dvst = (intsts0 & dvst_bit) != 0U;
751 else if (have_valid) {
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
Event Link Controller (ELC) register layout for the Renesas RA8D2.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
NVIC + ICU IELSR allocator.
Lightweight Logging Interface for ra8-firmware.
ra8_err_t ra8_usb_park_out_pipe(ra8_usb_speed_t speed, uint8_t pipe_num)
Park an OUT pipe at PID=NAK so an idle pipe stays quiescent.
ra8_err_t ra8_usb_queue_out(ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t *out_buf, uint16_t *inout_len, bool rearm)
Drain an OUT transfer (host -> device) from pipe_num.
ra8_err_t ra8_usb_rearm_out_pipe(ra8_usb_speed_t speed, uint8_t pipe_num)
Re-arm an OUT pipe that the controller has parked at PID=NAK.
ra8_usb_speed_t
Selects which controller instance the call targets.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
ra8_err_t ra8_usb_queue_in(ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
Queue an IN transfer (device -> host) on pipe_num.
USB Full-Speed + High-Speed controller layout for the Renesas RA8D2.
@ k_ra8_pipectr_inbufm
IN buffer monitor.
@ k_ra8_pipectr_pid_mask
PID[1:0] response field.
@ k_ra8_pid_nak
NAK response.
static volatile r_usb_regs_t * ra8_usb_hs(void)
Get pointer to the USB HS controller register block.
@ k_ra8_intsts0_mask_dvsq
Device state.
@ k_ra8_intsts0_mask_valid
SETUP packet detect flag.
@ k_ra8_intsts0_mask_ctsq
Control transfer stage.
@ k_ra8_int0_bit_dvst
Device-state transition.
@ k_ra8_int0_bit_ctrt
Control-transfer-stage transition.
static volatile r_usb_regs_t * ra8_usb_fs(void)
Compile-time offset and size insurance for r_usb_regs_t.
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
USB FS / HS register window (device-mode subset).
volatile uint16_t PIPECTR[k_ra8_usb_pipectr_count]
+0x070 PIPE1..9 ctrl.
volatile uint16_t BEMPSTS
+0x04A BEMP Interrupt Status.
USBX device-controller-driver (DCD) bridge to ra8_usb.
@ k_ux_dcd_ra8_usb_max_pipes
DCP + 9 PIPE entries (HUM 36.1).
@ k_ux_dcd_ra8_usb_state_uninit
Bridge not yet initialized.
USBX device-controller-driver bridge to ra8_usb – per-module cross-translation-unit contract.
volatile uint32_t g_dcd_auto_echo_enable
Non-zero once ISR-side auto-echo is armed.
void priv_trace_event(uint8_t kind, uint8_t code, uint16_t length)
Append one packed event to the JLink-readable trace ring.
@ k_ra8_int0_dvsq_shift
DVSQ[2:0] field starts at bit 4.
uint8_t g_dcd_auto_echo_out_pipe
Pipe drained by the in-ISR auto-echo path.
uint16_t g_orphan_len
Held orphan byte count; 0 = empty.
uint8_t g_dcd_auto_echo_in_pipe
Pipe the auto-echo path re-queues onto.
ra8_usb_dcd_t g_dcd
The single bridge instance, defined in ux_dcd_ra8_usb.c.
@ k_dcd_trace_no_code
Code when none applies.
@ k_dcd_trace_cdb_lba_lo
CDB byte: LBA bits 7..0.
@ k_dcd_trace_cbw_op_off
CDB opcode offset inside a CBW.
@ k_dcd_trace_kind_out
Bulk-OUT transfer completed.
@ k_dcd_trace_cbw_len
BOT CBW wire length.
@ k_dcd_out_drain_max
Max OUT banks drained per ISR pass.
@ k_dcd_trace_cdb_lba_hi
CDB byte: LBA bits 15..8.
@ k_dcd_trace_op_read10
SCSI READ(10) opcode.
@ k_dcd_trace_op_write10
SCSI WRITE(10) opcode.
@ k_dcd_trace_byte_shift
CDB byte-pair packing shift.
@ k_dcd_trace_kind_ocap
Orphan OUT packet captured.
@ k_dcd_trace_kind_in
Bulk-IN transfer completed.
ra8_usb_dcd_diag_t g_diag
Bridge diagnostic counter block, defined in ux_dcd_ra8_usb.c.
void priv_handle_ctrt(ra8_usb_speed_t speed, uint16_t intsts0)
Handle the CTRT (control-transfer-stage) interrupt branch.
volatile uint32_t g_setup_token_observed
Counter of proven device-side SETUP-token latches.
void priv_irq_dvst_prelude(ra8_usb_speed_t speed, uint16_t intsts0)
Capture DVSTCTR0 / RHST history, mirror speed, dispatch DVST.
uint8_t g_orphan_buf[k_ra8_usb_orphan_bytes]
One held no-receiver bulk-OUT packet.
uint8_t g_orphan_pipe
Pipe the held orphan packet is on.
@ k_ra8_usb_orphan_bytes
One full-speed bulk MPS packet.
void priv_handle_ctrl_out_data(ra8_usb_speed_t speed)
Drain a deferred control-OUT data stage and run chapter-9.
static void internal_irq_drain_orphan_out(uint8_t i)
Capture a no-receiver bulk-OUT packet into the orphan buffer.
static void internal_irq_complete_out(UX_SLAVE_TRANSFER *tr, uint8_t i)
Complete a stashed OUT-pipe transfer (or rearm on no-data).
volatile uint32_t g_dcd_auto_echo_tx_err
static uint8_t s_dcd_auto_echo_buf[k_ux_dcd_ra8_usb_auto_echo_max]
static void internal_irq_complete_in(UX_SLAVE_TRANSFER *tr, uint8_t i)
Complete a stashed IN-pipe transfer.
ux_dcd_ra8_usb_auto_echo_cfg_t
@ k_ux_dcd_ra8_usb_auto_echo_max
Ux dcd RA8 USB auto echo maximum.
volatile uint32_t g_intsts0_snapshot_count
Total interesting INTSTS0 snapshots seen; modulo k_ra8_usb_dcd_intsts0_hist_n is the next write slot.
static void internal_irq_walk_pipe(uint8_t i)
Per-pipe finaliser for the BRDY/BEMP walk in ux_dcd_ra8_usb_irq.
volatile uint32_t g_intsts0_valid_count
Number of dispatch ticks where INTSTS0.VALID was observed.
volatile uint32_t g_intsts0_ctrt_count
Number of dispatch ticks where INTSTS0.CTRT was observed.
void ux_dcd_ra8_usb_irq(ra8_usb_speed_t speed, uint16_t intsts0)
Ux dcd ra usb irq.
static bool internal_irq_stage_next_in(UX_SLAVE_TRANSFER *tr, uint8_t i)
Stage the next IN chunk of a stashed transfer onto the pipe.
volatile uint16_t g_dcd_auto_echo_last_len
volatile uint8_t g_ctsq_history[(uint32_t) k_ra8_usb_dcd_intsts0_hist_n]
Ring buffer of the last 8 INTSTS0.CTSQ[2:0] values observed with CTRT or VALID asserted.
ra8_usb_dcd_intsts0_hist_t
Sizing for the INTSTS0 / CTSQ history rings.
@ k_ra8_usb_dcd_intsts0_hist_n
Slots in g_intsts0_snapshot/g_ctsq_history.
volatile uint16_t g_intsts0_observed_or
Bitwise OR of every INTSTS0 value ever fed to ux_dcd_ra8_usb_irq.
volatile uint8_t g_dvsq_history[(uint32_t) k_ra8_usb_dcd_intsts0_hist_n]
Per-snapshot DVSQ[2:0] field, pre-decoded for JLink readers.
static void internal_irq_record_snapshot(uint16_t intsts0)
Record per-bit IRQ counters and the JLink-visible event ring.
volatile uint16_t g_intsts0_last_dispatch
Most-recent INTSTS0 snapshot fed to ux_dcd_ra8_usb_irq.
static void internal_irq_finish_out(UX_SLAVE_TRANSFER *tr, uint8_t i, uint16_t now)
Finish a completed OUT transfer: park, trace, wake the waiter.
static void internal_irq_auto_echo(uint8_t i)
No-waiter auto-echo drain on the configured OUT pipe.
volatile uint16_t g_intsts0_snapshot[(uint32_t) k_ra8_usb_dcd_intsts0_hist_n]
Ring buffer of the last 8 INTSTS0 values seen by the worker on ticks where any of CTRT/VALID/DVST wer...
volatile uint32_t g_ctrt_irq_count
Counter of INTSTS0.CTRT events seen by the dispatcher.
volatile uint32_t g_dcd_auto_echo_tx_ok
static bool internal_irq_recover_in_nak(UX_SLAVE_TRANSFER *tr, uint8_t i, volatile r_usb_regs_t *reg)
Recover a stashed IN transfer whose pipe fell to PID=NAK.
volatile uint32_t g_dcd_auto_echo_drain_ok
volatile uint32_t g_dcd_auto_echo_drain_skip