|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
USBX device-controller-driver bridge to ra8_usb – DVST Default-state mirror path. 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"Go to the source code of this file.
Macros | |
| #define | UX_SOURCE_CODE |
Enumerations | |
| enum | ra8_usb_dcd_default_poll_t : uint32_t { k_ra8_usb_dcd_default_poll_iters = 200000U } |
| Tight-poll loop sizing for the Default-state VALID hunt. More... | |
| enum | ra8_usb_dcpctr_bits_t : uint16_t { k_ra8_dcpctr_mask_sqmon = (uint16_t)(1U << 6U) } |
| Selected DCPCTR bit masks (HUM Ch 37.2.31 p 2095). More... | |
Functions | |
| static void | internal_dvst_capture_setup_mirror (uint16_t usbreq_live, uint16_t usbval_live, uint16_t usbindx_live, uint16_t usbleng_live) |
| Capture the persistent SETUP mirror into the JLink-readable probe. | |
| static void | internal_dvst_dispatch_if_new (volatile r_usb_regs_t *reg, uint16_t usbreq_live, uint16_t usbval_live, uint16_t usbindx_live, uint16_t usbleng_live) |
| Unconditionally dispatch a Default-state SETUP if USBREQ changed. | |
| void | priv_dvst_default_state (ra8_usb_speed_t speed) |
| Process the DVSQ=Default branch of internal_handle_dvst. | |
Variables | |
| volatile uint32_t | g_busreset_rearm_count = 0U |
| Number of times ra8_usb_device_busreset_rearm was invoked from the DVST handler in response to a Default-state entry. | |
| volatile uint16_t | g_dcpctr_after_rearm = 0U |
| Snapshot of DCPCTR taken at the end of every busreset_rearm. | |
| volatile uint16_t | g_intenb0_after_rearm = 0U |
| Snapshot of INTENB0 taken at the end of every busreset_rearm. | |
| volatile uint16_t | g_cfifosel_after_rearm = 0U |
| Snapshot of CFIFOSEL taken at the end of every busreset_rearm. | |
| volatile uint16_t | g_dcpctr_pre_rearm = 0U |
| Snapshot of DCPCTR taken at the START of every busreset_rearm. | |
| volatile uint32_t | g_setup_token_observed = 0U |
| Counter of proven device-side SETUP-token latches. | |
| static volatile uint16_t | s_prev_dcpctr_sqmon = 0U |
| Last-observed value of DCPCTR.SQMON (masked to bit 6). | |
| volatile uint32_t | g_dispatch_attempts = 0U |
| Count of SQMON-driven dispatch attempts (regardless of outcome). | |
| volatile uint16_t | g_intsts0_at_sqmon_edge = 0U |
| Snapshot of INTSTS0 captured immediately before the SQMON-driven ra8_usb_read_setup_unconditional call. | |
| volatile uint16_t | g_intsts0_observed_or_recent = 0U |
| Most-recent INTSTS0 value sampled at the start of the Default-state tight-poll for VALID (HUM Ch 37.2.18 p 2081, VALID = bit 3, mask 0x0008). | |
| volatile uint16_t | g_dcpctr_bit_map_observed = 0U |
| Cumulative bitwise-OR of every DCPCTR value sampled at the Default-state DVST entry. | |
| volatile uint16_t | g_usbreq_first_nonzero = 0U |
| First non-zero USBREQ value captured by the tight-poll Default-state loop (HUM Ch 37.2.26 p 2090). | |
| volatile uint32_t | g_unconditional_dispatch_count = 0U |
| Count of unconditional _ux_device_stack_control_request_process invocations made by the Default-state polled worker. | |
| volatile uint16_t | g_last_dispatched_usbreq = 0U |
| Last USBREQ (HUM Ch 37.2.26 p 2090) value forwarded to the chapter-9 dispatcher by the unconditional Default-state worker. | |
USBX device-controller-driver bridge to ra8_usb – DVST Default-state mirror path.
The DVSQ=Default branch of the DVST handler: persistent SETUP-mirror capture, the unconditional Default-state SETUP dispatch, and the bus-reset DCP re-arm probes.
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.
Definition in file ux_dcd_ra8_usb_dvst_default.c.
| #define UX_SOURCE_CODE |
Definition at line 22 of file ux_dcd_ra8_usb_dvst_default.c.
| enum ra8_usb_dcd_default_poll_t : uint32_t |
Tight-poll loop sizing for the Default-state VALID hunt.
The polled worker reaches internal_handle_dvst once per Default-state DVST tick. Inside that tick we tight-poll INTSTS0 for VALID (HUM Ch 37.2.18 p 2081, mask 0x0008) without yielding so that the SIE's auto-clear of VALID does not race the dispatcher. The iteration count is calibrated for ~2 ms of wall time on the Cortex-M85 @ 1 GHz:
| Enumerator | |
|---|---|
| k_ra8_usb_dcd_default_poll_iters | ~2 ms upper bound. |
Definition at line 317 of file ux_dcd_ra8_usb_dvst_default.c.
| enum ra8_usb_dcpctr_bits_t : uint16_t |
Selected DCPCTR bit masks (HUM Ch 37.2.31 p 2095).
| Enumerator | |
|---|---|
| k_ra8_dcpctr_mask_sqmon | SQMON (bit 6): SETUP-latched flag. |
Definition at line 325 of file ux_dcd_ra8_usb_dvst_default.c.
|
static |
Capture the persistent SETUP mirror into the JLink-readable probe.
The HS SIE auto-clears INTSTS0.VALID (HUM Ch 37.2.18 p 2081) and DCPCTR.SQMON (HUM Ch 37.2.32 p 2093) faster than the polled worker can observe them, so flag-gated reads race the controller and miss every SETUP. The four mirrors USBREQ/USBVAL/USBINDX/USBLENG (HUM Ch 37.2.26..29 p 2090..2092) latch the wire-format SETUP and PERSIST across the SIE's auto-clears. If any mirror is non-zero, copy them into g_setup_packet_buffer in USB 2.0 Ch 9.3 wire byte order.
| [in] | usbreq_live | USBREQ snapshot. |
| [in] | usbval_live | USBVAL snapshot. |
| [in] | usbindx_live | USBINDX snapshot. |
| [in] | usbleng_live | USBLENG snapshot. |
Definition at line 353 of file ux_dcd_ra8_usb_dvst_default.c.
References g_setup_packet_buffer, g_setup_packet_count, g_usbreq_first_nonzero, k_setup_byte_mask, k_setup_byte_shift, k_setup_idx_bmrt, k_setup_idx_brq, k_setup_idx_idx_hi, k_setup_idx_idx_lo, k_setup_idx_len_hi, k_setup_idx_len_lo, k_setup_idx_val_hi, k_setup_idx_val_lo, and RA8_INTERNAL.
Referenced by priv_dvst_default_state().
|
static |
Unconditionally dispatch a Default-state SETUP if USBREQ changed.
Gate ONLY on USBREQ-change so the same SETUP cannot re-fire across DVST entries within one Default dwell. A fresh USBREQ wire value (different from g_last_dispatched_usbreq) is treated as a new SETUP and pushed into chapter-9, even when both VALID and SQMON have already been auto-cleared by the SIE. After dispatch we W0C-ack INTSTS0.VALID and pulse a benign DCPCTR write.
| [in] | reg | Controller register block for the current speed. |
| [in] | usbreq_live | USBREQ wire value just read. |
| [in] | usbval_live | USBVAL wire value just read. |
| [in] | usbindx_live | USBINDX wire value just read. |
| [in] | usbleng_live | USBLENG wire value just read. |
Definition at line 404 of file ux_dcd_ra8_usb_dvst_default.c.
References ra8_usb_setup_t::b_request, ra8_usb_setup_t::bm_request_type, r_usb_regs_t::DCPCTR, g_dispatch_skip_reason, g_last_dispatched_usbreq, g_setup_dispatch_count, g_setup_token_observed, g_unconditional_dispatch_count, r_usb_regs_t::INTSTS0, k_ra8_dcpctr_mask_sqmon, k_ra8_intsts0_mask_valid, k_ra8_usb_skip_usbreq_unchanged, k_setup_byte_mask, k_setup_byte_shift, priv_dispatch_setup(), RA8_INTERNAL, ra8_usb_setup_t::w_index, ra8_usb_setup_t::w_length, and ra8_usb_setup_t::w_value.
Referenced by priv_dvst_default_state().
| void priv_dvst_default_state | ( | ra8_usb_speed_t | speed | ) |
Process the DVSQ=Default branch of internal_handle_dvst.
Process the DVSQ=Default branch of the DVST handler.
Captures DCPCTR / INTSTS0 probes, drains the persistent SETUP mirrors, dispatches a fresh SETUP if USBREQ changed, then re-arms DCP via ra8_usb_device_busreset_rearm so the IP can latch the host's next SETUP token (FSP usb_pstd_busreset parity). HUM Ch 36.2.7 / 36.2.10 / 36.2.21 (FS) and Ch 37 mirrors.
| [in] | speed | Which controller fired. |
Definition at line 453 of file ux_dcd_ra8_usb_dvst_default.c.
References r_usb_regs_t::CFIFOSEL, r_usb_regs_t::DCPCTR, g_busreset_rearm_count, g_cfifosel_after_rearm, g_dcpctr_after_rearm, g_dcpctr_bit_map_observed, g_dcpctr_pre_rearm, g_dispatch_attempts, g_intenb0_after_rearm, g_intsts0_at_sqmon_edge, g_intsts0_observed_or_recent, r_usb_regs_t::INTENB0, internal_dvst_capture_setup_mirror(), internal_dvst_dispatch_if_new(), r_usb_regs_t::INTSTS0, k_ra8_dcpctr_mask_sqmon, k_ra8_usb_speed_hs, ra8_usb_device_busreset_rearm(), ra8_usb_fs(), ra8_usb_hs(), s_prev_dcpctr_sqmon, r_usb_regs_t::USBINDX, r_usb_regs_t::USBLENG, r_usb_regs_t::USBREQ, and r_usb_regs_t::USBVAL.
Referenced by internal_handle_dvst().
| volatile uint32_t g_busreset_rearm_count = 0U |
Number of times ra8_usb_device_busreset_rearm was invoked from the DVST handler in response to a Default-state entry.
Bisect probe. After plug-in macOS issues a bus reset every ~10 ms until SETUP succeeds. If this counter grows but g_setup_packet_count stays at 0, the re-arm is firing but the IP is still failing to latch SETUP – look at PIPECFG / DCPMAXP via JLink. If the counter never grows, the DVST -> Default branch isn't being taken (check g_dvst_state_history).
Definition at line 55 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_cfifosel_after_rearm = 0U |
Snapshot of CFIFOSEL taken at the end of every busreset_rearm.
Bisect probe. The rearm no longer writes CFIFOSEL (probe data showed the in-IRQ write of 0x0400 read back as 0x0000 on the HS instance, and FSP usb_pstd_bus_reset never touches CFIFOSEL – SETUP latching uses USBREQ/USBVAL/USBINDX/USBLENG, not the CFIFO port). This snapshot now just records whatever value was already programmed by the previous data-stage. HUM Ch 36.2.7 / 37.2.8 CFIFOSEL p 1976 / 2071.
Definition at line 109 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_dcpctr_after_rearm = 0U |
Snapshot of DCPCTR taken at the end of every busreset_rearm.
Bisect probe for the "VALID never asserts after bus reset" symptom. The rearm intentionally does NOT write DCPCTR (HUM Ch 36.2.21 / 37.2.31 p 1991 / 2093 documents that a USB bus reset auto-defaults PID to NAK and CCPL to 0), so this snapshot reflects whatever the SIE left in DCPCTR after the bus reset and any SETUP-receipt state machine that completed before the rearm fired. Expected value with PID=NAK and CCPL/SUREQ low: 0x0000. A non-zero value means the IP latched something (PBUSY=bit 5, SQMON=bit 6, BSTS=bit 15); SQMON=1 is the strongest "SETUP arrived" signal in device mode (HUM Ch 37.2.31 p 2095, SQMON flag description).
Definition at line 75 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_dcpctr_bit_map_observed = 0U |
Cumulative bitwise-OR of every DCPCTR value sampled at the Default-state DVST entry.
Definitive bisect probe for "which DCPCTR bits has the SIE ever raised?". Per HUM Ch 37.2.32 p 2093 the DCPCTR reset value is 0x0040 (bit 6 SQMON defaults to 1 = DATA1-expected); a value other than 0x0040 means the SIE has mutated PID, CCPL, PINGE, PBUSY, SQSET, SQCLR, SUREQCLR, CSSTS, CSCLR, SUREQ, or BSTS at least once since power-on. HUM Ch 37.2.32 p 2095..2096.
Definition at line 247 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_dcpctr_pre_rearm = 0U |
Snapshot of DCPCTR taken at the START of every busreset_rearm.
Captured BEFORE any rearm-side writes so it reflects the state the host's bus reset left the DCP in. Compared against g_dcpctr_after_rearm to confirm that the rearm did (or did not) mutate DCP fields.
Bit positions of interest (HUM Ch 36.2.21 / 37.2.31 DCPCTR p 1991 / 2093, full bit table on p 2095..2096):
Definition at line 136 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint32_t g_dispatch_attempts = 0U |
Count of SQMON-driven dispatch attempts (regardless of outcome).
Incremented on every Default-state DVST tick, before the SQMON-driven SETUP drain. Pair with g_setup_dispatch_count to see how many attempts produced a successful drain.
Definition at line 194 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_intenb0_after_rearm = 0U |
Snapshot of INTENB0 taken at the end of every busreset_rearm.
Bisect probe; expected value matches the device-mode mask in internal_usb_init_common – BEMP|BRDY|NRDY|CTRT|DVST|SOFR|RSME|VBSE = 0xFD00 (bits 8..15 set except bit 12 – wait, bit 12 = DVST = set; bits 11..15 = CTRT/DVST/ SOFR/RSME/VBSE; bits 8..10 = BRDY/NRDY/BEMP; combined = 0xFF00). If this reads back zero, INTENB0 was clobbered after rearm and the next CTRT edge will not raise an IRQ. HUM Ch 36.2.10 INTENB0 p 1980.
Definition at line 92 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_intsts0_at_sqmon_edge = 0U |
Snapshot of INTSTS0 captured immediately before the SQMON-driven ra8_usb_read_setup_unconditional call.
VALID is bit 3 of INTSTS0 (HUM Ch 36.2.14 p 1985). On HS this probe routinely reads back without bit 3 set: the SIE auto-clears VALID before the polled worker observes the SQMON edge. The captured SETUP-latch registers (USBREQ/USBVAL/USBINDX/USBLENG, HUM Ch 37.2.21 ..24 p 2087..2090) survive that auto-clear, which is why the HS path uses ra8_usb_read_setup_unconditional – it drains the latch directly without gating on VALID.
Definition at line 212 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_intsts0_observed_or_recent = 0U |
Most-recent INTSTS0 value sampled at the start of the Default-state tight-poll for VALID (HUM Ch 37.2.18 p 2081, VALID = bit 3, mask 0x0008).
Distinct from g_intsts0_observed_or (which OR-accumulates forever and saturates after the first VBSE storm). This probe is over-written every Default-state DVST tick with the live INTSTS0 read just before the tight-poll loop, so a JLink reader can answer "what did INTSTS0 look like this iteration?" without losing the bit pattern to the cumulative-OR. HUM Ch 37.2.18 INTSTS0 p 2081.
Definition at line 230 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().
| volatile uint16_t g_last_dispatched_usbreq = 0U |
Last USBREQ (HUM Ch 37.2.26 p 2090) value forwarded to the chapter-9 dispatcher by the unconditional Default-state worker.
Used as the de-duplication key: the worker dispatches only when the live USBREQ differs from this latch, so the same SETUP cannot be re-fired across loop iterations within a single bus-state dwell. Reset to 0 after a fresh dispatch records the new value.
Definition at line 297 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by internal_dvst_dispatch_if_new().
| volatile uint32_t g_setup_token_observed = 0U |
Counter of proven device-side SETUP-token latches.
Counter incremented every time the IRQ snapshot proves the device-side controller latched a SETUP token from the host.
Defined in ux_dcd_ra8_usb_dvst_default.c.
Two independent evidence paths fold into this counter:
Note: INTSTS1.SACK is HOST-mode only (HUM Ch 37.2.19 SACK flag p 2084: "Values read from the SACK flag in device controller mode are invalid."), so SACK cannot serve as a SETUP-receipt probe.
Definition at line 162 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by internal_dvst_dispatch_if_new(), and internal_irq_record_snapshot().
| volatile uint32_t g_unconditional_dispatch_count = 0U |
Count of unconditional _ux_device_stack_control_request_process invocations made by the Default-state polled worker.
Incremented every time the worker dispatches a SETUP without gating on INTSTS0.VALID (HUM Ch 37.2.18 p 2081) or DCPCTR.SQMON (HUM Ch 37.2.32 p 2093). The dispatch fires whenever the latched USBREQ (HUM Ch 37.2.26 p 2090) differs from g_last_dispatched_usbreq, which prevents infinite re-dispatch of the same SETUP transaction.
Definition at line 282 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by internal_dvst_dispatch_if_new().
| volatile uint16_t g_usbreq_first_nonzero = 0U |
First non-zero USBREQ value captured by the tight-poll Default-state loop (HUM Ch 37.2.26 p 2090).
Pure latch: stays 0 until the polled worker reads back a non-zero USBREQ (bRequest in bits 15..8, bmRequestType in bits 7..0). For a standard GET_DESCRIPTOR(DEVICE) this latches as 0x0680 (bRequest=0x06, bmRequestType=0x80). Stays 0 forever means the SIE has never latched a SETUP transaction into the USBREQ/USBVAL/USBINDX/USBLENG mirrors – proof the host's SETUP tokens are not reaching the device.
Definition at line 265 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by internal_dvst_capture_setup_mirror().
|
static |
Last-observed value of DCPCTR.SQMON (masked to bit 6).
Retained as a JLink-readable probe; the previous rising-edge gate that consumed this value has been removed because it fired only once per session and starved the dispatcher whenever the very first SQMON observation already had VALID=0. Dispatch is now driven by ra8_usb_read_setup_unconditional on the HS / SQMON path, which skips the VALID gate entirely (the SIE auto-clears VALID before the polled worker observes the SETUP edge), drains the SETUP-latch mirrors directly, and W0C-clears VALID defensively on the way out. HUM Ch 36.2.14 p 1985, Ch 37.2.31 p 2095.
Definition at line 181 of file ux_dcd_ra8_usb_dvst_default.c.
Referenced by priv_dvst_default_state().