|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
USBX device-controller-driver bridge to ra8_usb – device-state (DVST) 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_sentinel_t : uint16_t { k_ra8_usb_u16_unset = 0xFFFFU } |
| "Not yet captured" sentinel for 16-bit register snapshots. More... | |
| enum | ra8_usb_dcd_rhst_hist_t : uint8_t { k_ra8_usb_dcd_rhst_hist_n = 16U } |
| Sizing for the DVSTCTR0.RHST history ring. More... | |
| enum | ra8_usb_dcd_rhst_t : uint8_t { k_ra8_usb_rhst_fs = 2U , k_ra8_usb_rhst_hs = 3U } |
| DVSTCTR0.RHST[2:0] settled link-speed encodings. More... | |
Functions | |
| static unsigned long | internal_dvst_map_dvsq_to_ux_state (uint16_t dvsq) |
| Map a DVSQ-bits-4..6 value to the USBX device-state enum. | |
| static void | internal_dvst_record_history (uint16_t dvsq) |
| Record one DVST event into the JLink-readable causal history. | |
| static bool | internal_dvst_policy_apply (UX_SLAVE_DEVICE *device, uint16_t dvsq, unsigned long new_state) |
| DVSQ mirror policy: may new_state be written into USBX? | |
| static void | internal_handle_dvst (ra8_usb_speed_t speed, uint16_t intsts0) |
| Handle the DVST (device-state-changed) interrupt branch. | |
| static void | internal_dvst_track_speed (uint8_t rhst) |
| Mirror the negotiated link speed from DVSTCTR0.RHST into USBX. | |
| void | priv_irq_dvst_prelude (ra8_usb_speed_t speed, uint16_t intsts0) |
| Capture DVSTCTR0 / RHST history, mirror speed, dispatch DVST. | |
Variables | |
| volatile uint32_t | g_dvst_irq_count = 0U |
| Counter of INTSTS0.DVST (device-state-transition) events. | |
| volatile uint16_t | g_dvstctr0_at_first_dvst = (uint16_t)k_ra8_usb_u16_unset |
| Snapshot of DVSTCTR0 (RHST field) on first DVST event. | |
| volatile uint8_t | g_rhst_history [(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
| Per-DVST-event capture of DVSTCTR0.RHST[2:0]. | |
| volatile uint32_t | g_rhst_history_count = 0U |
| Total DVST events seen; modulo k_ra8_usb_dcd_rhst_hist_n is the next write slot. | |
| volatile uint16_t | g_dvstctr0_history [(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
| Per-dispatch-tick capture of the full DVSTCTR0 register. | |
| volatile uint32_t | g_dvstctr0_history_count = 0U |
| Total dispatch ticks observed; modulo k_ra8_usb_dcd_rhst_hist_n is the next write slot in g_dvstctr0_history. | |
| volatile uint16_t | g_intsts1_history [(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
| Per-dispatch-tick capture of the full INTSTS1 register. | |
| volatile uint8_t | g_dvst_state_history [(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
| Per-DVST-event capture of the decoded DVSQ[2:0] field. | |
| volatile uint32_t | g_dvst_state_history_count = 0U |
| Total DVST events recorded into g_dvst_state_history. | |
USBX device-controller-driver bridge to ra8_usb – device-state (DVST) path.
Device-state-change handling: DVSQ decode, the USBX device-state mirror policy, the negotiated-speed framework re-aim, and the DVST history ring.
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.c.
| #define UX_SOURCE_CODE |
Definition at line 22 of file ux_dcd_ra8_usb_dvst.c.
| enum ra8_usb_dcd_rhst_hist_t : uint8_t |
Sizing for the DVSTCTR0.RHST history ring.
| Enumerator | |
|---|---|
| k_ra8_usb_dcd_rhst_hist_n | Slots in g_rhst_history. |
Definition at line 79 of file ux_dcd_ra8_usb_dvst.c.
| enum ra8_usb_dcd_rhst_t : uint8_t |
DVSTCTR0.RHST[2:0] settled link-speed encodings.
HUM Ch 36.2.5 / Ch 37 DVSTCTR0 p 1971: the controller writes this after the reset/chirp handshake. Only the two settled, addressable speeds matter to the speed mirror; LS (1), in-reset (4) and undefined (0) are transient and leave the mirror untouched.
| Enumerator | |
|---|---|
| k_ra8_usb_rhst_fs | Full speed settled. |
| k_ra8_usb_rhst_hs | High speed settled. |
Definition at line 198 of file ux_dcd_ra8_usb_dvst.c.
| enum ra8_usb_dcd_sentinel_t : uint16_t |
"Not yet captured" sentinel for 16-bit register snapshots.
| Enumerator | |
|---|---|
| k_ra8_usb_u16_unset | Snapshot has not been latched yet. |
Definition at line 57 of file ux_dcd_ra8_usb_dvst.c.
|
static |
Map a DVSQ-bits-4..6 value to the USBX device-state enum.
DVSQ bit 6 set => Suspended-from-X variants. Non-suspend Powered (0x00) is treated as ATTACHED for the chapter-9 gate.
| [in] | dvsq | DVSQ bits extracted from INTSTS0 (mask 0x70 plus suspend bit). |
| UX_DEVICE_SUSPENDED | Suspend variant observed. |
| UX_DEVICE_ATTACHED | Default or Powered. |
| UX_DEVICE_ADDRESSED | DVSQ=010 Address state. |
| UX_DEVICE_CONFIGURED | DVSQ=011 Configured state. |
Definition at line 226 of file ux_dcd_ra8_usb_dvst.c.
References k_ra8_dvsq_address, k_ra8_dvsq_configured, k_ra8_dvsq_default, k_ra8_dvsq_powered, k_ra8_dvsq_suspend, k_ra8_intsts0_mask_dvsq, and RA8_INTERNAL.
Referenced by internal_handle_dvst().
|
static |
DVSQ mirror policy: may new_state be written into USBX?
The chapter-9 stack owns the ADDRESSED/CONFIGURED transitions (it sets them while processing SET_ADDRESS / SET_CONFIGURATION) and the mirror must never demote that state asynchronously: USBX class threads (storage) gate on CONFIGURED and suspend themselves permanently when they wake to anything else. Policy: suspends are not propagated (traffic pauses, gates keep); upgrades apply directly; a disconnect + apply happens ONLY on a genuine Default-state entry (true bus reset). A generic "any downgrade is a reset" rule does not work because the hardware DVSQ LAGS the stack during configuration – it sits in Address state until SET_CONFIGURATION's status stage completes, and ISR INTSTS0 snapshots can be staler still – so it tears the just-built configuration down microseconds after activation (observed against macOS at HS as a sub-millisecond configure/deactivate loop with the storage thread never scheduled). The Default-entry disconnect is required: macOS's MSC driver resets the device at start-of-probe, and without the teardown the stack treats the re-issued SET_CONFIGURATION as a same-value no-op (no interface mount, no class re-activation) and the storage thread parks forever.
| [in,out] | device | USBX device instance (state read; on Default entry the configuration is torn down). |
| [in] | dvsq | Masked DVSQ field from the INTSTS0 snapshot. |
| [in] | new_state | dvsq mapped to a UX_DEVICE_* state. |
| true | Upgrade, or Default-state entry (post-disconnect). |
| false | Suspend or a stale/lagging downgrade; do not touch. |
Definition at line 323 of file ux_dcd_ra8_usb_dvst.c.
References k_ra8_dvsq_default.
Referenced by internal_handle_dvst().
|
static |
Record one DVST event into the JLink-readable causal history.
One byte per event: high nibble = the raw DVSQ field (shifted), low nibble = ux_slave_device_state at IRQ entry (0xF when USBX is not bound yet). Reading the ring alongside the SETUP trace reconstructs who demoted/upgraded the chapter-9 state.
| [in] | dvsq | Masked INTSTS0.DVSQ field for this event. |
Definition at line 262 of file ux_dcd_ra8_usb_dvst.c.
References g_dvst_state_history, g_dvst_state_history_count, k_dcd_trace_kind_dvst, k_dcd_trace_nib_shift, k_dcd_trace_nibble, k_ra8_int0_dvsq_shift, k_ra8_usb_dcd_rhst_hist_n, priv_trace_event(), and RA8_INTERNAL.
Referenced by internal_handle_dvst().
|
static |
Mirror the negotiated link speed from DVSTCTR0.RHST into USBX.
The HS controller does not know its link speed until the host's reset/chirp handshake settles: connected to an HS host it runs at high speed, to an FS host it falls back to full speed. USBX serves descriptors from the CURRENT framework pointer (ux_system_slave_device_framework), which ux_dcd_ra8_usb_init seeds from the HS slot for the HS controller. If the link settles at FS, that pointer must be re-aimed at the full-speed framework (64-byte bulk MPS), otherwise the host reads a 512-byte-MPS bulk descriptor on a full-speed link and the bulk pipes never carry a CBW (observed in the chip-to-chip self-loop: an FS host drives the HS device, device sticks at ADDRESSED, storage class thread never runs media_read). This mirrors both ux_system_slave_speed and the current framework to the settled RHST. Only settled FS/HS values act; transient RHST (LS / in-reset / undefined) leaves both alone.
| [in] | rhst | Masked DVSTCTR0.RHST[2:0] from the DVST snapshot. |
rhst is the 3-bit RHST field (already masked). Definition at line 430 of file ux_dcd_ra8_usb_dvst.c.
References k_ra8_usb_rhst_fs, k_ra8_usb_rhst_hs, and RA8_INTERNAL.
Referenced by priv_irq_dvst_prelude().
|
static |
Handle the DVST (device-state-changed) interrupt branch.
Extracts the DVSQ field from intsts0, records it in the ring-buffer history for JLink readout, mirrors the decoded state into the USBX device-state field via internal_dvst_map_dvsq_to_ux_state under the internal_dvst_policy_apply policy, and re-arms the DCP after bus reset (Default-state entry) per the FSP usb_pstd_busreset reference flow. Without the rearm the IP silently drops the host's first SETUP token after bus reset.
| [in] | speed | Which controller fired (k_ra8_usb_speed_fs or k_ra8_usb_speed_hs). |
| [in] | intsts0 | INTSTS0 snapshot captured at the top of the ISR. |
Definition at line 360 of file ux_dcd_ra8_usb_dvst.c.
References g_last_dispatched_setup_fp, internal_dvst_map_dvsq_to_ux_state(), internal_dvst_policy_apply(), internal_dvst_record_history(), k_ra8_dvsq_default, k_ra8_dvsq_suspend, k_ra8_intsts0_mask_dvsq, priv_dvst_default_state(), and RA8_INTERNAL.
Referenced by priv_irq_dvst_prelude().
| void priv_irq_dvst_prelude | ( | ra8_usb_speed_t | speed, |
| uint16_t | intsts0 ) |
Capture DVSTCTR0 / RHST history, mirror speed, dispatch DVST.
Pulled out of ux_dcd_ra8_usb_irq so the outer ISR fits in one page. Reads DVSTCTR0 (HUM Ch 36.2.5 p 1971) for RHST history, latches the first-observed value into g_dvstctr0_at_first_dvst, mirrors the settled link speed via internal_dvst_track_speed, then calls internal_handle_dvst for the state-machine update.
| [in] | speed | Which controller fired (FS or HS). |
| [in] | intsts0 | INTSTS0 snapshot (forwarded to internal_handle_dvst). |
Definition at line 472 of file ux_dcd_ra8_usb_dvst.c.
References r_usb_regs_t::DVSTCTR0, g_dvst_irq_count, g_dvstctr0_at_first_dvst, g_rhst_history, g_rhst_history_count, internal_dvst_track_speed(), internal_handle_dvst(), k_ra8_usb_dcd_rhst_hist_n, k_ra8_usb_dvsq_field_mask, k_ra8_usb_speed_hs, k_ra8_usb_u16_unset, ra8_usb_fs(), and ra8_usb_hs().
Referenced by ux_dcd_ra8_usb_irq().
| volatile uint32_t g_dvst_irq_count = 0U |
Counter of INTSTS0.DVST (device-state-transition) events.
Bisect probe. Each bus reset / set-address / set-config raises DVST; zero after attach means the host isn't reaching the device. HUM Ch 36.2.14 p 1985.
Definition at line 51 of file ux_dcd_ra8_usb_dvst.c.
Referenced by priv_irq_dvst_prelude().
| volatile uint8_t g_dvst_state_history[(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
Per-DVST-event capture of the decoded DVSQ[2:0] field.
JLink-readable trace of every device-state transition (independent of the "interesting tick" filter that gates g_dvsq_history). Each DVST IRQ writes the pre-shifted DVSQ value (0=Powered, 1=Default, 2=Address, 3=Configured, 4..7=Suspend variant per HUM Ch 36.2.16 p 1986). A healthy enumeration shows 1, 1, 2, 2, 3, ...; the "stuck-in-default" symptom shows 1, 5, 1, 5, 1, 5, ... (Default <-> Suspended-from-Default loop).
Definition at line 177 of file ux_dcd_ra8_usb_dvst.c.
Referenced by internal_dvst_record_history().
| volatile uint32_t g_dvst_state_history_count = 0U |
Total DVST events recorded into g_dvst_state_history.
Modulo k_ra8_usb_dcd_rhst_hist_n is the next write slot.
Definition at line 188 of file ux_dcd_ra8_usb_dvst.c.
Referenced by internal_dvst_record_history().
| volatile uint16_t g_dvstctr0_at_first_dvst = (uint16_t)k_ra8_usb_u16_unset |
Snapshot of DVSTCTR0 (RHST field) on first DVST event.
Bisect probe. RHST[2:0] (HUM Ch 36.2.5 p 1971) reports the negotiated bus speed. 1=LS, 2=FS, 3=HS, 4=reset. If the HS chirp handshake succeeded this should latch 3 (HS); 2 means the chip is stuck in FS termination after bus reset.
Definition at line 73 of file ux_dcd_ra8_usb_dvst.c.
Referenced by priv_irq_dvst_prelude().
| volatile uint16_t g_dvstctr0_history[(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
Per-dispatch-tick capture of the full DVSTCTR0 register.
Bisect probe for the post-chirp HS bring-up stall. After a successful HS chirp the controller settles DVSTCTR0.RHST = 011 (HUM Ch 37.2.5 DVSTCTR0 / Ch 36.2.5 mirror, p 1971). The hypothesis under test is whether DVSTCTR0.HSPROC (bit 2 of the RHST 3-bit encoding – value 0b100 = 4 – per FSP r_usb_bitdefine.h USB_HSPROC = 0x0004) auto-clears or wedges, and whether any other DVSTCTR0 bit (UACT bit 6, RESUME bit 5, USBRST bit 6 in host mirror, WKUP bit 8, RWUPE bit 9, USBRESM bit 10, HNPBTOA bit 11, EXICEN bit 12, VBUSEN bit 13) flips between the chirp completion and the host's first SETUP/SOF token. INTSTS1.BCHG-only events with no SACK/CTRT mean the host stopped after chirp; capturing the full DVSTCTR0 word per tick lets the bench confirm the field is stable at 0x???3 (RHST=HS) and not silently flapping.
Ring size 16 chosen to match g_rhst_history so JLink scripts can read both arrays in one transaction.
Definition at line 132 of file ux_dcd_ra8_usb_dvst.c.
| volatile uint32_t g_dvstctr0_history_count = 0U |
Total dispatch ticks observed; modulo k_ra8_usb_dcd_rhst_hist_n is the next write slot in g_dvstctr0_history.
Definition at line 143 of file ux_dcd_ra8_usb_dvst.c.
| volatile uint16_t g_intsts1_history[(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
Per-dispatch-tick capture of the full INTSTS1 register.
Companion probe to g_dvstctr0_history. INTSTS1 (HUM Ch 36.2.17 p 2001) carries BCHG (bit 14), DTCH (bit 12), ATTCH (bit 11), EOFERR (bit 6), SIGN (bit 5), SACK (bit 4) for host mode and the bus-change shadow for device mode. The 0.2.0 bring-up symptom is BCHG-only (bit 14) with no SACK ever; this ring lets the bench confirm whether any SACK / EOFERR / SIGN edge arrives in the dispatch window after RHST settles.
Definition at line 160 of file ux_dcd_ra8_usb_dvst.c.
| volatile uint8_t g_rhst_history[(uint32_t) k_ra8_usb_dcd_rhst_hist_n] = {} |
Per-DVST-event capture of DVSTCTR0.RHST[2:0].
JLink-readable.
RHST encoding (HUM Ch 36.2.5 p 1971 / Ch 37 DVSTCTR0): 0=undefined / chirp limbo, 1=LS, 2=FS, 3=HS, 4=in-reset. On a successful HS attach the array typically reads 0,4,3,...; on FS-fallback 0,4,2,...; on chirp failure (the 0.2.0 USB-HS bring-up symptom) every slot reads 0 even after dozens of host resets.
Definition at line 96 of file ux_dcd_ra8_usb_dvst.c.
Referenced by priv_irq_dvst_prelude().
| volatile uint32_t g_rhst_history_count = 0U |
Total DVST events seen; modulo k_ra8_usb_dcd_rhst_hist_n is the next write slot.
Definition at line 106 of file ux_dcd_ra8_usb_dvst.c.
Referenced by priv_irq_dvst_prelude().