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

USBX device-controller-driver bridge to ra8_usb – NVIC ISR trampolines. 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_isr.c:

Go to the source code of this file.

Macros

#define UX_SOURCE_CODE

Enumerations

enum  ra8_usb_storm_cfg_t : uint32_t { k_ra8_usb_storm_mask_run = 8U }
 Tuning constant for the USBFS interrupt-storm guard. More...

Functions

static void internal_isr_bump_counts (uint16_t intsts0)
 Bump the per-bit ISR counters for an INTSTS0 snapshot.
static void internal_usbfs_isr (void *ctx)
 NVIC ISR entry point for the USBFS controller.
static void internal_ack_spurious (ra8_usb_speed_t speed, uint16_t intsts0)
 W0C-ack RSME/SOFR on a spurious USB ISR re-entry.
static void internal_usbhs_isr (void *ctx)
 NVIC ISR entry point for the USBHS controller.
ra8_elc_event_t priv_pick_event (ra8_usb_speed_t speed)
 Pick the ELC event number for a controller.
ra8_isr_handler_t priv_pick_isr (ra8_usb_speed_t speed)
 Pick the ISR trampoline for a controller.
void priv_event_cb (void *ctx, ra8_usb_speed_t speed, uint16_t status_mask)
 ra8_usb_attach_handler trampoline.

Variables

volatile uint32_t g_isr_invocations = 0U
 Counter of NVIC ISR entries through internal_usbfs_isr or internal_usbhs_isr.
volatile uint16_t g_isr_intsts0_or = 0U
 Cumulative bitwise-OR of every INTSTS0 value observed at the entry of internal_usbhs_isr.
volatile uint32_t g_isr_dvst_count = 0U
 Per-bit ISR counter for INTSTS0.DVST (bit 12) entries.
volatile uint32_t g_isr_ctrt_count = 0U
 Per-bit ISR counter for INTSTS0.CTRT (bit 11) entries.
volatile uint32_t g_isr_valid_count = 0U
 Per-bit ISR counter for INTSTS0.VALID (bit 3) entries.
volatile uint32_t g_isr_brdy_count = 0U
 Per-bit ISR counter for INTSTS0.BRDY (bit 8) entries.
volatile uint32_t g_isr_bemp_count = 0U
 Per-bit ISR counter for INTSTS0.BEMP (bit 10) entries.
volatile uint32_t g_isr_nrdy_count = 0U
 Per-bit ISR counter for INTSTS0.NRDY (bit 9) entries.
volatile uint32_t g_isr_sofr_count = 0U
 Per-bit ISR counter for INTSTS0.SOFR (bit 13) entries.
volatile uint32_t g_dcd_irq_spurious_mask_count = 0U

Detailed Description

USBX device-controller-driver bridge to ra8_usb – NVIC ISR trampolines.

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

USBFS / USBHS NVIC interrupt entry points, the per-bit ISR counters, the spurious-entry storm acknowledgement, and the controller-selection helpers that route the polled / interrupt dispatch back into USBX.

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_isr.c.

Macro Definition Documentation

◆ UX_SOURCE_CODE

#define UX_SOURCE_CODE

Definition at line 22 of file ux_dcd_ra8_usb_isr.c.

Enumeration Type Documentation

◆ ra8_usb_storm_cfg_t

enum ra8_usb_storm_cfg_t : uint32_t

Tuning constant for the USBFS interrupt-storm guard.

Enumerator
k_ra8_usb_storm_mask_run 

Consecutive event-less FS ISR entries that trip the NVIC mask.

The 1 ms SysTick handler zeroes the run, so this is a per-ms rate gauge: the bench storm runs ~40 event-less entries/ms and trips this in ~0.2 ms; normal SOFR is ~1/ms and never reaches it. A spurious trip is benign – SysTick re-enables within 1 ms, so a real event is delayed at most 1 ms.

Definition at line 188 of file ux_dcd_ra8_usb_isr.c.

Function Documentation

◆ internal_ack_spurious()

void internal_ack_spurious ( ra8_usb_speed_t speed,
uint16_t intsts0 )
static

W0C-ack RSME/SOFR on a spurious USB ISR re-entry.

The RA8 USB controller asserts its NVIC line for RSME (resume detect) and SOFR (start-of-frame) independent of INTENB0 – on USBHS via the PHY's USBR signal, and on USBFS the same applies (confirmed on the bench: SOFR/RSME entries occur with INTENB0.SOFR and INTENB0.RSME both clear). While the host hammers a NAK'ing pipe the FS resume detector re-asserts RSME continuously, which – without this short-circuit – drives the full dispatch + pipe-walk ~10^5 times/second and starves RTOS thread mode. When the snapshot has no real event bit we W0C-clear the stuck RSME/SOFR flags, bump the spurious counter, and return cheaply.

Parameters
[in]speedWhich controller the spurious entry came from.
[in]intsts0The just-snapshotted INTSTS0 value.
Precondition
Caller already determined (intsts0 & event_msk) == 0.
USB module for speed is initialized (ra8_usb_device_init ran).
Postcondition
g_dcd_irq_spurious_mask_count is incremented.
RSME/SOFR bits that were set are cleared via ra8_usb_clear_status.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 342 of file ux_dcd_ra8_usb_isr.c.

References g_dcd_irq_spurious_mask_count, r_usb_regs_t::INTSTS1, k_ra8_int0_bit_rsme, k_ra8_int0_bit_sofr, k_ra8_int1_bit_attch, k_ra8_int1_bit_bchg, k_ra8_int1_bit_dtch, k_ra8_usb_speed_hs, RA8_INTERNAL, ra8_usb_clear_status(), and ra8_usb_hs().

Referenced by internal_usbhs_isr().

◆ internal_isr_bump_counts()

void internal_isr_bump_counts ( uint16_t intsts0)
static

Bump the per-bit ISR counters for an INTSTS0 snapshot.

Each s_isr_*_count counter is a JLink-readable probe so a bench reader can correlate g_isr_intsts0_or with which event bits fired this tick. Shared by the FS and HS ISRs to keep each outer ISR within the NASA P10 Rule 4 size cap.

Parameters
[in]intsts0Snapshot of INTSTS0 read at the top of the ISR.
Precondition
Snapshot has already been masked against event_msk.
Caller is in NVIC handler mode.
Postcondition
Per-bit counters bumped for every observed event bit.
No INTSTS0 W0C write performed.
Note
ISR-only; must not block.
Since
0.1.0

Definition at line 222 of file ux_dcd_ra8_usb_isr.c.

References g_isr_bemp_count, g_isr_brdy_count, g_isr_ctrt_count, g_isr_dvst_count, g_isr_nrdy_count, g_isr_sofr_count, g_isr_valid_count, k_ra8_int0_bit_bemp, k_ra8_int0_bit_brdy, k_ra8_int0_bit_ctrt, k_ra8_int0_bit_dvst, k_ra8_int0_bit_nrdy, k_ra8_int0_bit_sofr, k_ra8_intsts0_mask_valid, and RA8_INTERNAL.

Referenced by internal_usbfs_isr(), and internal_usbhs_isr().

◆ internal_usbfs_isr()

void internal_usbfs_isr ( void * ctx)
static

NVIC ISR entry point for the USBFS controller.

Registered with ra8_isr_register(k_ra8_elc_event_usbfs_int, ...) during ux_dcd_ra8_usb_initialize. Snapshots INTSTS0, classifies the entry, then forwards it to ra8_usb_dispatch – the dispatch is unconditional, identical to the pre-storm-guard behaviour, so this ISR is behaviour-neutral for the working CDC / HID apps.

The only added behaviour is the storm guard. An entry with no real event bit (only RSME / SOFR / status bits – these assert the NVIC line independent of INTENB0) increments g_isr_spurious_run; a real event resets it. ux_dcd_ra8_usb_irq_reenable (called from the per-app 1 ms SysTick_Handler) zeroes the counter, so it gauges the event-less rate. Once it crosses k_ra8_usb_storm_mask_run within a millisecond a genuine storm is in progress, and priv_usbfs_irq_mask disables the USB IRQ so RTOS thread mode – the otherwise-starved USBX class thread (GitHub issue #6) – gets the CPU back. The SysTick handler re-enables the line within 1 ms. Normal idle SOFR (~1/ms) never trips the guard.

Parameters
[in]ctxUnused; kept to match ra8_isr_handler_t.
Precondition
Bridge is in k_ux_dcd_ra8_usb_state_ready or _active.
ra8_usb_attach_handler has been called (done in the same init).
Postcondition
g_isr_invocations is incremented and ra8_usb_dispatch ran.
On a sustained event-less run the USB IRQ is masked at the NVIC.
Note
Runs in NVIC handler mode; must not block.
See also
ra8_usb_dispatch
priv_usbfs_irq_mask
internal_usbhs_isr
ux_dcd_ra8_usb_irq
Since
0.1.0

Definition at line 286 of file ux_dcd_ra8_usb_isr.c.

References g_dcd_irq_spurious_mask_count, g_isr_intsts0_or, g_isr_invocations, g_isr_spurious_run, internal_isr_bump_counts(), k_ra8_int0_bit_bemp, k_ra8_int0_bit_brdy, k_ra8_int0_bit_ctrt, k_ra8_int0_bit_dvst, k_ra8_int0_bit_nrdy, k_ra8_int0_bit_vbse, k_ra8_intsts0_mask_valid, k_ra8_usb_speed_fs, k_ra8_usb_storm_mask_run, priv_usbfs_irq_mask(), RA8_INTERNAL, ra8_usb_dispatch(), and ra8_usb_intsts0_snapshot().

Referenced by priv_pick_isr().

◆ internal_usbhs_isr()

void internal_usbhs_isr ( void * ctx)
static

NVIC ISR entry point for the USBHS controller.

Snapshot INTSTS0 and gate the rest of the ISR on the event bits (8..15 plus the VALID flag). Spurious / USBR-driven re-entry is short-circuited via internal_ack_spurious. Real events are forwarded to ra8_usb_dispatch, which performs the canonical W0C ack and invokes the USBX-side handler.

Parameters
[in]ctxOpaque ISR context (unused; kept for the ICU callback ABI).
Precondition
USBHS module is past ra8_usb_device_init.
Caller is the NVIC USBHS_INT vector.
Postcondition
g_isr_invocations is incremented.
On a real event ra8_usb_dispatch ran; on a spurious one RSME/SOFR were W0C-cleared and g_dcd_irq_spurious_mask_count is incremented.
Note
ISR-only; must not block. Not re-entrant within a single controller.
Since
0.1.0

Definition at line 387 of file ux_dcd_ra8_usb_isr.c.

References g_isr_intsts0_or, g_isr_invocations, g_isr_spurious_run, internal_ack_spurious(), internal_isr_bump_counts(), k_ra8_int0_bit_bemp, k_ra8_int0_bit_brdy, k_ra8_int0_bit_ctrt, k_ra8_int0_bit_dvst, k_ra8_int0_bit_nrdy, k_ra8_int0_bit_vbse, k_ra8_intsts0_mask_valid, k_ra8_usb_speed_hs, k_ra8_usb_storm_mask_run, priv_usbfs_irq_mask(), RA8_INTERNAL, ra8_usb_dispatch(), and ra8_usb_intsts0_snapshot().

Referenced by priv_pick_isr().

◆ priv_event_cb()

void priv_event_cb ( void * ctx,
ra8_usb_speed_t speed,
uint16_t status_mask )

ra8_usb_attach_handler trampoline.

ra8_usb_attach_handler trampoline into ux_dcd_ra8_usb_irq.

See implementation for details.

Parameters
[in,out]ctxSee function signature.
[in,out]speedSee function signature.
[in,out]status_maskSee function signature.
Precondition
Module has been initialized.
Caller has validated arguments.
Postcondition
Side effects bounded to documented state.
State reflects operation result.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 500 of file ux_dcd_ra8_usb_isr.c.

References ux_dcd_ra8_usb_irq().

Referenced by ux_dcd_ra8_usb_initialize().

◆ priv_pick_event()

ra8_elc_event_t priv_pick_event ( ra8_usb_speed_t speed)

Pick the ELC event number for a controller.

Parameters
[in]speedWhich controller (FS or HS).
Returns
ra8_elc_event_t event number for that controller.
Precondition
speed is k_ra8_usb_speed_fs or k_ra8_usb_speed_hs.
Postcondition
No state mutated.
Note
Pure function.
Since
0.1.0

See implementation for details.

Return values
0Success or default value.
Precondition
Module has been initialized.
Postcondition
Side effects bounded to documented state.

Definition at line 457 of file ux_dcd_ra8_usb_isr.c.

References k_ra8_elc_event_usbfs_int, k_ra8_elc_event_usbhs_int_resume, and k_ra8_usb_speed_hs.

Referenced by internal_init_bind_owner(), and internal_usbfs_storm_guard_init().

◆ priv_pick_isr()

ra8_isr_handler_t priv_pick_isr ( ra8_usb_speed_t speed)

Pick the ISR trampoline for a controller.

Parameters
[in]speedWhich controller (FS or HS).
Returns
Function pointer to the trampoline.
Precondition
speed is k_ra8_usb_speed_fs or k_ra8_usb_speed_hs.
Postcondition
No state mutated.
Note
Pure function.
Since
0.1.0

See implementation for details.

Return values
0Success or default value.
Precondition
Module has been initialized.
Postcondition
Side effects bounded to documented state.

Definition at line 481 of file ux_dcd_ra8_usb_isr.c.

References internal_usbfs_isr(), internal_usbhs_isr(), and k_ra8_usb_speed_hs.

Referenced by internal_init_bind_owner().

Variable Documentation

◆ g_dcd_irq_spurious_mask_count

volatile uint32_t g_dcd_irq_spurious_mask_count = 0U

Definition at line 159 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_ack_spurious(), and internal_usbfs_isr().

◆ g_isr_bemp_count

volatile uint32_t g_isr_bemp_count = 0U

Per-bit ISR counter for INTSTS0.BEMP (bit 10) entries.

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 133 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_brdy_count

volatile uint32_t g_isr_brdy_count = 0U

Per-bit ISR counter for INTSTS0.BRDY (bit 8) entries.

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 124 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_ctrt_count

volatile uint32_t g_isr_ctrt_count = 0U

Per-bit ISR counter for INTSTS0.CTRT (bit 11) entries.

Sibling of g_isr_dvst_count for the control-transfer- stage-transition bit (HUM Ch 36.2.14 p 1985).

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 102 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_dvst_count

volatile uint32_t g_isr_dvst_count = 0U

Per-bit ISR counter for INTSTS0.DVST (bit 12) entries.

Incremented inside internal_usbhs_isr whenever the snapshot has the device-state-transition bit set. Distinguishes "ISR fired with DVST" from the bridge-side g_dvst_irq_count which counts events after they have already been forwarded to the USBX stack.

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 90 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_intsts0_or

volatile uint16_t g_isr_intsts0_or = 0U

Cumulative bitwise-OR of every INTSTS0 value observed at the entry of internal_usbhs_isr.

Each ISR entry samples INTSTS0 (HUM Ch 36.2.14 p 1985) and folds it into this accumulator with |=. JLink-readable: the set bits tell which event sources have ever fired since boot (BRDY/NRDY/BEMP/CTRT/DVST/SOFR/RSME/VBSE in bits 8..15, plus VALID in bit 3 and the read-only DVSQ/VBSTS status fields). Used to distinguish "ISR runs but no event bits set" (interrupt storm from an un-acked source) from "ISR runs with real events".

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 75 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_usbfs_isr(), and internal_usbhs_isr().

◆ g_isr_invocations

volatile uint32_t g_isr_invocations = 0U

Counter of NVIC ISR entries through internal_usbfs_isr or internal_usbhs_isr.

Reaches non-zero on the first USB IRQ delivered through ra8_isr_register / NVIC. Stays at 0 if the IELSR slot was never routed, the NVIC line was masked, or the vector trampoline did not land in the substrate dispatcher (e.g. weak Default_Handler still winning the link). Read via JLink to confirm interrupts fire. HUM Ch 13 NVIC + Ch 14 ICU IELSR.

Note
Written only by the two ISR trampolines.
Since
0.1.0

Definition at line 56 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_usbfs_isr(), and internal_usbhs_isr().

◆ g_isr_nrdy_count

volatile uint32_t g_isr_nrdy_count = 0U

Per-bit ISR counter for INTSTS0.NRDY (bit 9) entries.

Storm-localisation probe: a value in the millions after a failed MSC scan means a pipe is NAK'ing host tokens and the NRDY status is re-asserting INTSTS0.NRDY faster than the dispatcher clears it. Written by internal_usbfs_isr and internal_usbhs_isr.

Since
0.1.0

Definition at line 145 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_sofr_count

volatile uint32_t g_isr_sofr_count = 0U

Per-bit ISR counter for INTSTS0.SOFR (bit 13) entries.

Storm-localisation probe. SOFR fires once per USB frame (1 kHz on full-speed); a count far above 1000 * uptime_s means the ISR is re-entering on a bit other than SOFR while SOFR happens to be co-asserted. Written by internal_usbfs_isr and internal_usbhs_isr.

Since
0.1.0

Definition at line 157 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().

◆ g_isr_valid_count

volatile uint32_t g_isr_valid_count = 0U

Per-bit ISR counter for INTSTS0.VALID (bit 3) entries.

Counts ISR entries where the SETUP-detect flag was already latched at snapshot time. The actual SETUP drain is performed by ux_dcd_ra8_usb_irq via ra8_usb_dispatch -> priv_event_cb.

Note
Written only by internal_usbhs_isr.
Since
0.1.0

Definition at line 115 of file ux_dcd_ra8_usb_isr.c.

Referenced by internal_isr_bump_counts().