ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ux_dcd_ra8_usb_irq.c File Reference

USBX device-controller-driver bridge to ra8_usb – IRQ pipe-walk. More...

#include <stdint.h>
#include <string.h>
#include "ra8_check.h"
#include "ra8_elc_regs.h"
#include "ra8_isr.h"
#include "ra8_log.h"
#include "ra8_usb_regs.h"
#include "tx_api.h"
#include "ux_api.h"
#include "ux_dcd_ra8_usb.h"
#include "ux_dcd_ra8_usb_internal.h"
#include "ux_device_stack.h"
#include "ux_system.h"
#include "ux_utility.h"
Include dependency graph for ux_dcd_ra8_usb_irq.c:

Go to the source code of this file.

Macros

#define UX_SOURCE_CODE

Enumerations

enum  ra8_usb_dcd_intsts0_hist_t : uint8_t { k_ra8_usb_dcd_intsts0_hist_n = 8U }
 Sizing for the INTSTS0 / CTSQ history rings. More...
enum  ux_dcd_ra8_usb_auto_echo_cfg_t : uint16_t { k_ux_dcd_ra8_usb_auto_echo_max = 512U }

Functions

static void internal_irq_record_snapshot (uint16_t intsts0)
 Record per-bit IRQ counters and the JLink-visible event ring.
static void internal_irq_auto_echo (uint8_t i)
 No-waiter auto-echo drain on the configured OUT pipe.
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.
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.
static void internal_irq_complete_in (UX_SLAVE_TRANSFER *tr, uint8_t i)
 Complete a stashed IN-pipe transfer.
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_complete_out (UX_SLAVE_TRANSFER *tr, uint8_t i)
 Complete a stashed OUT-pipe transfer (or rearm on no-data).
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_walk_pipe (uint8_t i)
 Per-pipe finaliser for the BRDY/BEMP walk in ux_dcd_ra8_usb_irq.
void ux_dcd_ra8_usb_irq (ra8_usb_speed_t speed, uint16_t intsts0)
 Ux dcd ra usb irq.

Variables

volatile uint32_t g_ctrt_irq_count = 0U
 Counter of INTSTS0.CTRT events seen by the dispatcher.
volatile uint16_t g_intsts0_last_dispatch = 0U
 Most-recent INTSTS0 snapshot fed to ux_dcd_ra8_usb_irq.
volatile uint32_t g_intsts0_valid_count = 0U
 Number of dispatch ticks where INTSTS0.VALID was observed.
volatile uint32_t g_intsts0_ctrt_count = 0U
 Number of dispatch ticks where INTSTS0.CTRT was observed.
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 were set.
volatile uint32_t g_intsts0_snapshot_count = 0U
 Total interesting INTSTS0 snapshots seen; modulo k_ra8_usb_dcd_intsts0_hist_n is the next write slot.
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.
volatile uint16_t g_intsts0_observed_or = 0U
 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.
volatile uint32_t g_dcd_auto_echo_drain_ok = 0U
volatile uint32_t g_dcd_auto_echo_drain_skip = 0U
volatile uint32_t g_dcd_auto_echo_tx_ok = 0U
volatile uint32_t g_dcd_auto_echo_tx_err = 0U
volatile uint16_t g_dcd_auto_echo_last_len = 0U
static uint8_t s_dcd_auto_echo_buf [k_ux_dcd_ra8_usb_auto_echo_max]

Detailed Description

USBX device-controller-driver bridge to ra8_usb – IRQ pipe-walk.

Tag
[Ring 5 / PORT] {World: S}

The ISR bottom-half ux_dcd_ra8_usb_irq and its per-pipe BRDY / BEMP finalisers: IN streaming, OUT draining, auto-echo, and orphan-OUT capture.

Split out of ux_dcd_ra8_usb.c to keep each translation unit under the maintainability line cap; the cross-translation-unit contract lives in ux_dcd_ra8_usb_internal.h.

Since
0.1.0

Definition in file ux_dcd_ra8_usb_irq.c.

Macro Definition Documentation

◆ UX_SOURCE_CODE

#define UX_SOURCE_CODE

Definition at line 22 of file ux_dcd_ra8_usb_irq.c.

Enumeration Type Documentation

◆ ra8_usb_dcd_intsts0_hist_t

Sizing for the INTSTS0 / CTSQ history rings.

Enumerator
k_ra8_usb_dcd_intsts0_hist_n 

Slots in g_intsts0_snapshot/g_ctsq_history.

Definition at line 70 of file ux_dcd_ra8_usb_irq.c.

◆ ux_dcd_ra8_usb_auto_echo_cfg_t

Enumerator
k_ux_dcd_ra8_usb_auto_echo_max 

Ux dcd RA8 USB auto echo maximum.

Definition at line 175 of file ux_dcd_ra8_usb_irq.c.

Function Documentation

◆ internal_irq_auto_echo()

void internal_irq_auto_echo ( uint8_t i)
static

No-waiter auto-echo drain on the configured OUT pipe.

When the USBX-side waiter is absent (typically because the worker thread has not yet been dispatched) and the operator has enabled the in-ISR auto-echo path, drain the OUT pipe locally and re-queue the bytes back on the IN pipe. Workaround for ThreadX worker scheduling failure – keeps echo functional without any thread-mode involvement.

THROUGHPUT NOTE. On hardware this echo loop sustains ~2.66 MB/s one-way at HS and ~360 KB/s at FS (measured via scripts/hil/usb/stream_bench.py against Linux cdc_acm). That is ~66 % of the per-microframe scheduling ceiling for HS (4 MB/s at 1 packet/125 us microframe) and ~35 % of FS bulk wire. The bottleneck is NOT this code path – it is the host's cdc_acm URB-completion pipeline (MPS-sized read URBs, one completion per packet, callback latency limits URB recycling). To push past this ceiling needs either a libusb async client, a kernel cdc_acm patch with bigger URBs, or a vendor-specific interface.

Parameters
[in]iPipe index that just signalled BRDY/BEMP with no waiter.
Precondition
Called from ISR context only.
Caller already verified g_dcd.pipes[i].xfer == nullptr.
Postcondition
On a successful drain, the IN pipe holds the echoed payload (with a trailing ZLP when len % MPS == 0).
Counters under s_dcd_auto_echo_* are updated.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 271 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, g_dcd_auto_echo_drain_ok, g_dcd_auto_echo_drain_skip, g_dcd_auto_echo_enable, g_dcd_auto_echo_in_pipe, g_dcd_auto_echo_last_len, g_dcd_auto_echo_out_pipe, g_dcd_auto_echo_tx_err, g_dcd_auto_echo_tx_ok, k_ra8_ok, k_ux_dcd_ra8_usb_auto_echo_max, RA8_INTERNAL, ra8_usb_queue_in(), ra8_usb_queue_out(), ra8_usb_rearm_out_pipe(), and s_dcd_auto_echo_buf.

Referenced by internal_irq_walk_pipe().

◆ internal_irq_complete_in()

void internal_irq_complete_in ( UX_SLAVE_TRANSFER * tr,
uint8_t i )
static

Complete a stashed IN-pipe transfer.

IN: data was already pushed in TRANSFER_REQUEST. Mark complete on the BEMP that follows, and W0C-ack the per-pipe BEMPSTS bit so the global INTSTS0.BEMP flag can de-assert – without this BEMPSTS stays set forever, the global BEMP re-asserts after every dispatch ack, and the ISR storm prevents PendSV from delivering completions to the worker. HUM Ch 36.2.15 BEMPSTS (W0C, write ~pipe_bit to clear only this pipe).

Parameters
[in,out]trStashed transfer to complete.
[in]iPipe index.
Precondition
Called from ISR context only.
g_dcd.pipes[i].xfer == tr.
Postcondition
g_dcd.pipes[i].xfer == nullptr.
Per-pipe BEMPSTS bit is cleared and the waiter is woken (non-standalone).
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 413 of file ux_dcd_ra8_usb_irq.c.

References r_usb_regs_t::BEMPSTS, g_dcd, internal_irq_recover_in_nak(), internal_irq_stage_next_in(), k_dcd_trace_kind_in, k_dcd_trace_no_code, k_ra8_usb_speed_hs, priv_trace_event(), RA8_INTERNAL, ra8_usb_fs(), ra8_usb_hs(), and ra8_usb_queue_in().

Referenced by internal_irq_walk_pipe().

◆ internal_irq_complete_out()

void internal_irq_complete_out ( UX_SLAVE_TRANSFER * tr,
uint8_t i )
static

Complete a stashed OUT-pipe transfer (or rearm on no-data).

Drain the OUT pipe into the stashed buffer. On success post UX_SUCCESS and wake the waiter; on k_ra8_err_no_data proactively W0C-ack NRDYSTS for this pipe and force PIPECTR.PID = BUF so the next host OUT is ACKed. HUM Ch 36.2.13 NRDYSTS + Ch 36.2.27 PIPECTR.

Parameters
[in,out]trStashed transfer to complete.
[in]iPipe index.
Precondition
Called from ISR context only.
g_dcd.pipes[i].xfer == tr.
Postcondition
On success g_dcd.pipes[i].xfer == nullptr and the waiter is woken.
On no-data the OUT pipe is rearmed; no semaphore wake.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 543 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, g_diag, internal_irq_finish_out(), k_dcd_out_drain_max, k_ra8_ok, RA8_INTERNAL, ra8_usb_queue_out(), and ra8_usb_rearm_out_pipe().

Referenced by internal_irq_walk_pipe().

◆ internal_irq_drain_orphan_out()

void internal_irq_drain_orphan_out ( uint8_t i)
static

Capture a no-receiver bulk-OUT packet into the orphan buffer.

Run from the IRQ pipe-walk for an OUT pipe that has no USBX transfer stashed. If a host packet has landed in the controller bank (BRDYSTS set), draining it via ra8_usb_queue_out both W0C-clears BRDYSTS – so the no-receiver BRDY interrupt cannot storm the CPU and starve thread mode (GitHub issue #6) – and preserves the packet in g_orphan_buf for internal_submit_pipe to hand to the next bulk-OUT transfer. The pipe is then parked at PID=NAK so no second packet can land. Skipped for IN pipes, unconfigured pipes, the CDC auto-echo pipe, and while the one-deep buffer is already occupied.

Parameters
[in]iPipe index (1..max_pipes-1).
Precondition
Caller is on the ISR callback path; g_dcd.pipes[i].xfer is NULL.
Bridge is past ux_dcd_ra8_usb_initialize.
Postcondition
On a captured packet g_orphan_len / g_orphan_pipe hold it, BRDYSTS for pipe i is cleared, and the pipe is parked at NAK.
Otherwise no state changes (fast BRDYSTS-clear early return).
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 619 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, g_dcd_auto_echo_enable, g_dcd_auto_echo_out_pipe, g_orphan_buf, g_orphan_len, g_orphan_pipe, k_dcd_trace_kind_ocap, k_ra8_ok, k_ra8_usb_orphan_bytes, priv_trace_event(), RA8_INTERNAL, ra8_usb_park_out_pipe(), and ra8_usb_queue_out().

Referenced by internal_irq_walk_pipe().

◆ internal_irq_finish_out()

void internal_irq_finish_out ( UX_SLAVE_TRANSFER * tr,
uint8_t i,
uint16_t now )
static

Finish a completed OUT transfer: park, trace, wake the waiter.

Parks the pipe at PID=NAK (a host OUT token landing before the class layer arms the next receiver is then NAK'd rather than ACK'd into a FIFO with no waiter – the latter latches BRDYSTS and storms the ISR, GitHub issue #6), records the transfer in the trace ring (with the SCSI opcode + CDB bytes 1..2 when it is a 31-byte CBW), posts UX_SUCCESS, and wakes the waiter.

Parameters
[in,out]trStashed transfer that just completed.
[in]iPipe index.
[in]nowTotal bytes received for this transfer.
Precondition
Called from ISR context only.
g_dcd.pipes[i].xfer == tr.
Postcondition
g_dcd.pipes[i].xfer == nullptr and the waiter is woken.
The pipe is parked at PID=NAK.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 493 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, k_dcd_trace_byte_shift, k_dcd_trace_cbw_len, k_dcd_trace_cbw_op_off, k_dcd_trace_cdb_lba_hi, k_dcd_trace_cdb_lba_lo, k_dcd_trace_kind_out, k_dcd_trace_no_code, k_dcd_trace_op_read10, k_dcd_trace_op_write10, priv_trace_event(), RA8_INTERNAL, and ra8_usb_park_out_pipe().

Referenced by internal_irq_complete_out().

◆ internal_irq_record_snapshot()

void internal_irq_record_snapshot ( uint16_t intsts0)
static

Record per-bit IRQ counters and the JLink-visible event ring.

Bumps g_intsts0_valid_count / g_intsts0_ctrt_count / g_setup_token_observed then, when any event bit (CTRT / VALID / DVST) is set, snapshots the wire-format INTSTS0 along with the decoded CTSQ and DVSQ fields into the round-robin history ring (HUM Ch 36.2.14 / Ch 36.2.16). Folded out of ux_dcd_ra8_usb_irq so the outer ISR-side trampoline stays under the NASA P10 Rule 4 size cap.

Parameters
[in]intsts0INTSTS0 snapshot forwarded by ra8_usb_dispatch.
Precondition
Bridge is past ux_dcd_ra8_usb_initialize.
Caller is on the ISR callback path.
Postcondition
Counters / history ring updated; no INTSTS0 W0C write performed.
No wire-side state mutated.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 211 of file ux_dcd_ra8_usb_irq.c.

References g_ctsq_history, g_dvsq_history, g_intsts0_ctrt_count, g_intsts0_snapshot, g_intsts0_snapshot_count, g_intsts0_valid_count, g_setup_token_observed, k_ra8_int0_bit_ctrt, k_ra8_int0_bit_dvst, k_ra8_int0_dvsq_shift, k_ra8_intsts0_mask_ctsq, k_ra8_intsts0_mask_dvsq, k_ra8_intsts0_mask_valid, k_ra8_usb_dcd_intsts0_hist_n, and RA8_INTERNAL.

Referenced by ux_dcd_ra8_usb_irq().

◆ internal_irq_recover_in_nak()

bool internal_irq_recover_in_nak ( UX_SLAVE_TRANSFER * tr,
uint8_t i,
volatile r_usb_regs_t * reg )
static

Recover a stashed IN transfer whose pipe fell to PID=NAK.

Strand recovery (seen against macOS hosts): a stashed IN transfer must never sit with PIPECTR.PID = NAK – the SIE then NAKs every IN token, the host eventually suspends the bus, and the class thread blocks on the semaphore forever. Two recoverable shapes:

  • a loaded bank (INBUFM set) whose PID=BUF arm was lost: re-arm it;
  • an empty bank with no BEMP pending mid-stream: the previous staging attempt failed; re-stage the current chunk. HUM Ch 36.2.27 PIPEnCTR (PID / INBUFM).
Parameters
[in,out]trStashed transfer being streamed.
[in]iPipe index.
[in]regController register window.
Returns
true when a recovery action was taken (caller returns).
Return values
falseThe pipe is armed normally; continue the walk.
Precondition
Called from ISR context only.
g_dcd.pipes[i].xfer == tr.
Postcondition
On recovery the pipe is re-armed or the chunk re-staged.
g_diag counters record which recovery fired.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 367 of file ux_dcd_ra8_usb_irq.c.

References r_usb_regs_t::BEMPSTS, g_dcd, g_diag, internal_irq_stage_next_in(), k_ra8_pid_nak, k_ra8_pipectr_inbufm, k_ra8_pipectr_pid_mask, r_usb_regs_t::PIPECTR, and ra8_usb_rearm_out_pipe().

Referenced by internal_irq_complete_in().

◆ internal_irq_stage_next_in()

bool internal_irq_stage_next_in ( UX_SLAVE_TRANSFER * tr,
uint8_t i )
static

Stage the next IN chunk of a stashed transfer onto the pipe.

Pushes the next MPS-bounded chunk at the running actual_length offset via ra8_usb_queue_in and advances the offset on success. A failure (typically an FRDY timeout while the SIE holds the FIFO) is counted in g_diag.in_stage_fail and leaves actual_length unchanged so the caller can retry the same chunk on a later walk.

Parameters
[in,out]trStashed transfer being streamed.
[in]iPipe index.
Returns
true when the chunk was queued.
Return values
falsera8_usb_queue_in failed; nothing was consumed.
Precondition
Called from ISR context only.
tr->ux_slave_transfer_request_actual_length is < requested.
Postcondition
On success actual_length advanced by the staged chunk.
On failure g_diag.in_stage_fail is incremented.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 324 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, g_diag, k_ra8_ok, RA8_INTERNAL, and ra8_usb_queue_in().

Referenced by internal_irq_complete_in(), and internal_irq_recover_in_nak().

◆ internal_irq_walk_pipe()

void internal_irq_walk_pipe ( uint8_t i)
static

Per-pipe finaliser for the BRDY/BEMP walk in ux_dcd_ra8_usb_irq.

If no USBX-side waiter is stashed, dispatch to the in-ISR auto-echo path (workaround for ThreadX worker scheduling failure) and the no-receiver orphan-OUT capture. Otherwise dispatch to internal_irq_complete_in or internal_irq_complete_out depending on the pipe direction.

Parameters
[in]iPipe index (1..max_pipes-1).
Precondition
Bridge is past ux_dcd_ra8_usb_initialize.
Caller is on the ISR callback path.
Postcondition
One of: a transfer was completed and the semaphore was put; the OUT pipe was rearmed on no-data; or the auto-echo loop drained the OUT pipe and re-queued on the IN pipe.
g_diag.irq_walk_total is incremented.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 673 of file ux_dcd_ra8_usb_irq.c.

References g_dcd, g_diag, internal_irq_auto_echo(), internal_irq_complete_in(), internal_irq_complete_out(), internal_irq_drain_orphan_out(), and RA8_INTERNAL.

Referenced by ux_dcd_ra8_usb_irq().

◆ ux_dcd_ra8_usb_irq()

void ux_dcd_ra8_usb_irq ( ra8_usb_speed_t speed,
uint16_t intsts0 )

Ux dcd ra usb irq.

ISR-context bottom-half.

See implementation for details.

Parameters
[in,out]speedSee function signature for type and usage.
[in,out]intsts0See function signature for type and usage.
Precondition
Caller has validated arguments.
Module has been initialized.
Postcondition
Side effects bounded to documented state.
Returned value reflects current state.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 709 of file ux_dcd_ra8_usb_irq.c.

References g_ctrt_irq_count, g_dcd, g_intsts0_last_dispatch, g_intsts0_observed_or, internal_irq_record_snapshot(), internal_irq_walk_pipe(), k_ra8_int0_bit_ctrt, k_ra8_int0_bit_dvst, k_ra8_intsts0_mask_valid, k_ux_dcd_ra8_usb_max_pipes, k_ux_dcd_ra8_usb_state_uninit, priv_handle_ctrl_out_data(), priv_handle_ctrt(), and priv_irq_dvst_prelude().

Referenced by priv_event_cb().

Variable Documentation

◆ g_ctrt_irq_count

volatile uint32_t g_ctrt_irq_count = 0U

Counter of INTSTS0.CTRT events seen by the dispatcher.

Bisect probe. Non-zero after host SETUP means the chip is reporting control-stage transitions; zero means SETUPs aren't being latched (HS chirp / termination problem). HUM Ch 36.2.14 p 1985.

Note
Written only by ux_dcd_ra8_usb_irq.
Since
0.1.0

Definition at line 51 of file ux_dcd_ra8_usb_irq.c.

Referenced by ux_dcd_ra8_usb_irq().

◆ g_ctsq_history

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.

Encoding (HUM Ch 36.2.14 p 1985 / ra8_usb_ctsq_t): 0=idle, 1=rdds, 2=rdss, 3=wrds, 4=wrss, 5=wrnd, 6=sqer.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 138 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ g_dcd_auto_echo_drain_ok

volatile uint32_t g_dcd_auto_echo_drain_ok = 0U

Definition at line 179 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().

◆ g_dcd_auto_echo_drain_skip

volatile uint32_t g_dcd_auto_echo_drain_skip = 0U

Definition at line 181 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().

◆ g_dcd_auto_echo_last_len

volatile uint16_t g_dcd_auto_echo_last_len = 0U

Definition at line 187 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().

◆ g_dcd_auto_echo_tx_err

volatile uint32_t g_dcd_auto_echo_tx_err = 0U

Definition at line 185 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().

◆ g_dcd_auto_echo_tx_ok

volatile uint32_t g_dcd_auto_echo_tx_ok = 0U

Definition at line 183 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().

◆ g_dvsq_history

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.

Companion to g_intsts0_snapshot. Slot i holds (intsts0[i] >> 4) & 0x07, i.e. 0=Powered, 1=Default, 2=Address, 3=Configured, 4..7=Suspend (per HUM Ch 36.2.16 p 1986). Saves the human reader from mentally decoding the raw bits.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 168 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ g_intsts0_ctrt_count

volatile uint32_t g_intsts0_ctrt_count = 0U

Number of dispatch ticks where INTSTS0.CTRT was observed.

Bisect probe. Identical to g_ctrt_irq_count but bumped on the snapshot value before the CTRT branch decides whether to handle the SETUP – useful for detecting CTRT latches that hit a snapshot but failed the handler's CTSQ decode. HUM Ch 36.2.14 p 1985.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 100 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ g_intsts0_last_dispatch

volatile uint16_t g_intsts0_last_dispatch = 0U

Most-recent INTSTS0 snapshot fed to ux_dcd_ra8_usb_irq.

Live-debug probe. Read this from JLink to see the current pending interrupt mask + DVSQ/CTSQ field state without halting the polled worker. HUM Ch 36.2.14 p 1985.

Note
Written only by ux_dcd_ra8_usb_irq.
Since
0.1.0

Definition at line 64 of file ux_dcd_ra8_usb_irq.c.

Referenced by ux_dcd_ra8_usb_irq().

◆ g_intsts0_observed_or

volatile uint16_t g_intsts0_observed_or = 0U

Bitwise OR of every INTSTS0 value ever fed to ux_dcd_ra8_usb_irq.

Definitive bisect probe. Read this once via JLink and check bit 3 (mask 0x0008 = VALID) – if it's clear, the controller has NEVER latched a SETUP token since power-on. Distinct from the snapshot ring (which can scroll edges out of view) because OR- accumulating bits is monotonic. HUM Ch 36.2.16 INTSTS0 p 1986 (VALID = bit 3, CTRT = bit 11, DVST = bit 12).

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 154 of file ux_dcd_ra8_usb_irq.c.

Referenced by ux_dcd_ra8_usb_irq().

◆ g_intsts0_snapshot

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 were set.

JLink-readable trace. Index of next write slot is g_intsts0_snapshot_count % k_ra8_usb_dcd_intsts0_hist_n. Only "interesting" ticks are recorded so a noisy idle loop doesn't scroll a real SETUP edge out of the ring. HUM Ch 36.2.14 p 1985.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 115 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ g_intsts0_snapshot_count

volatile uint32_t g_intsts0_snapshot_count = 0U

Total interesting INTSTS0 snapshots seen; modulo k_ra8_usb_dcd_intsts0_hist_n is the next write slot.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 125 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ g_intsts0_valid_count

volatile uint32_t g_intsts0_valid_count = 0U

Number of dispatch ticks where INTSTS0.VALID was observed.

Bisect probe. Distinguishes "controller never latched a SETUP" (count == 0) from "controller latched but our CTRT edge was lost" (count > 0 while g_ctrt_irq_count grows). HUM Ch 36.2.14 INTSTS0.VALID = bit 3, p 1985.

Note
Single-writer (ux_dcd_ra8_usb_irq).
Since
0.1.0

Definition at line 86 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_record_snapshot().

◆ s_dcd_auto_echo_buf

uint8_t s_dcd_auto_echo_buf[k_ux_dcd_ra8_usb_auto_echo_max]
static

Definition at line 189 of file ux_dcd_ra8_usb_irq.c.

Referenced by internal_irq_auto_echo().