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

USBX device-controller-driver (DCD) bridge to ra8_usb. More...

#include "ra8_usb.h"
Include dependency graph for ux_dcd_ra8_usb.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ra8_usb_dcd_state_t : uint8_t {
  k_ux_dcd_ra8_usb_state_uninit = 0U ,
  k_ux_dcd_ra8_usb_state_ready = 1U ,
  k_ux_dcd_ra8_usb_state_active = 2U
}
 Run-state of the DCD bridge. More...
enum  ra8_usb_dcd_limits_t : uint8_t { k_ux_dcd_ra8_usb_max_pipes = 10U }
 Compile-time sizing of the bridge. More...

Functions

ra8_err_t ux_dcd_ra8_usb_initialize (ra8_usb_speed_t speed)
 Register the ra8_usb bridge as the active USBX DCD.
ra8_err_t ux_dcd_ra8_usb_uninitialize (void)
 Tear down the ra8_usb DCD bridge.
void ux_dcd_ra8_usb_irq (ra8_usb_speed_t speed, uint16_t intsts0)
 ISR-context bottom-half.
ra8_usb_dcd_state_t ux_dcd_ra8_usb_state (void)
 Read the bridge run-state.
void ux_dcd_ra8_usb_auto_echo_enable (uint8_t out_pipe, uint8_t in_pipe)
 Enable ISR-side auto-echo from a bulk OUT pipe to a bulk IN pipe.
void ux_dcd_ra8_usb_irq_reenable (void)
 Re-enable the USB NVIC IRQ at the controller level.
unsigned int _ux_dcd_ra8_usb_function (struct UX_SLAVE_DCD_STRUCT *dcd, unsigned int function, void *parameter)
 ux dcd ra usb function.

Detailed Description

USBX device-controller-driver (DCD) bridge to ra8_usb.

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

Plumbs Eclipse USBX's device stack onto the project's hand-written ra8_usb_* register-level driver (libs/ra8_hal/inc/ra8_usb.h). The shim implements the eight-function dispatch contract that USBX expects to find behind UX_SLAVE_DCD::ux_slave_dcd_function and is what _ux_device_stack_initialize ultimately reaches when the application calls ux_device_class_cdc_acm_initialize and brings a class up.

Surface

The dispatch table _ux_dcd_ra8_usb_function switches on the UX_DCD_* command codes:

The bridge is intentionally thin: it never allocates, never owns any host-stack state, and never blocks. Class-layer threads (the CDC bulk-in / bulk-out threads in particular) supply the UX_SLAVE_TRANSFER semaphore that ux_dcd_ra8_usb_irq posts on BRDY completion.

Since
0.1.0

Definition in file ux_dcd_ra8_usb.h.

Enumeration Type Documentation

◆ ra8_usb_dcd_limits_t

enum ra8_usb_dcd_limits_t : uint8_t

Compile-time sizing of the bridge.

Independent of UX_MAX_ED so we can statically pin the pipe table without dragging in ux_api.h from this header.

Enumerator
k_ux_dcd_ra8_usb_max_pipes 

DCP + 9 PIPE entries (HUM 36.1).

Definition at line 83 of file ux_dcd_ra8_usb.h.

◆ ra8_usb_dcd_state_t

enum ra8_usb_dcd_state_t : uint8_t

Run-state of the DCD bridge.

Enumerator
k_ux_dcd_ra8_usb_state_uninit 

Bridge not yet initialized.

k_ux_dcd_ra8_usb_state_ready 

Bridge installed; bus idle.

k_ux_dcd_ra8_usb_state_active 

Class-layer transfers active.

Definition at line 70 of file ux_dcd_ra8_usb.h.

Function Documentation

◆ _ux_dcd_ra8_usb_function()

unsigned int _ux_dcd_ra8_usb_function ( struct UX_SLAVE_DCD_STRUCT * dcd,
unsigned int function,
void * parameter )

ux dcd ra usb function.

See implementation for details.

Parameters
[in,out]dcdSee function signature for type and usage.
[in,out]functionSee function signature for type and usage.
[in,out]parameterSee function signature for type and usage.
Returns
Result code or value; see implementation.
Return values
0Success or default value.
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

ux dcd ra usb function.

Stamped into UX_SLAVE_DCD::ux_slave_dcd_function during ux_dcd_ra8_usb_initialize. The USBX device stack calls this with a UX_DCD_* selector to request endpoint create/destroy, transfer request, transfer abort, stall, and similar primitives; the trampoline routes each to the matching internal_* helper.

Parameters
[in,out]dcdUSBX DCD ownership block (currently unused; the bridge keeps its own static state in g_dcd).
[in]functionUSBX UX_DCD_* selector (e.g. UX_DCD_TRANSFER_REQUEST).
[in,out]parameterSelector-dependent argument (UX_SLAVE_TRANSFER* / UX_SLAVE_ENDPOINT* / opaque).
Returns
USBX result code from the dispatched helper.
Return values
UX_SUCCESSFunction handled.
UX_CONTROLLER_UNKNOWNBridge has not been initialized.
UX_ERRORSelector unsupported, or helper rejected the call.
UX_TRANSFER_ERRORTransfer-request helper failed.
Precondition
Bridge is past ux_dcd_ra8_usb_initialize (or the call returns UX_CONTROLLER_UNKNOWN).
Caller is the USBX device stack.
Postcondition
g_dcd updated per the dispatched selector.
Wire-side state may have been mutated (CREATE / STALL).
Note
Runs on the USBX device task context; not ISR-safe.
Since
0.1.0

Definition at line 281 of file ux_dcd_ra8_usb_ep.c.

References g_dcd, internal_count_change_state(), internal_endpoint_create(), internal_endpoint_destroy(), internal_endpoint_stall(), k_ux_dcd_ra8_usb_state_active, k_ux_dcd_ra8_usb_state_ready, k_ux_dcd_ra8_usb_state_uninit, and priv_transfer_request().

Referenced by internal_init_bind_owner(), and internal_init_setup_ep0().

◆ ux_dcd_ra8_usb_auto_echo_enable()

void ux_dcd_ra8_usb_auto_echo_enable ( uint8_t out_pipe,
uint8_t in_pipe )

Enable ISR-side auto-echo from a bulk OUT pipe to a bulk IN pipe.

Workaround for a ThreadX scheduling failure on this silicon where the application worker thread blocks indefinitely on tx_semaphore_get after the CDC class activates. With auto-echo on, the bridge's internal_irq_walk_pipe drains the OUT pipe in-place and re-queues the data on the IN pipe entirely inside the USB IRQ – no thread-mode dispatch required.

Parameters
[in]out_pipePipe index of the bulk OUT endpoint (e.g. 2 for CDC).
[in]in_pipePipe index of the bulk IN endpoint (e.g. 1 for CDC).
Precondition
Both pipes have been configured via the USBX endpoint-create path (i.e. host has issued SET_CONFIGURATION).
Called from task / startup context, not from inside an ISR.
Postcondition
Subsequent BRDY events on out_pipe with no USBX waiter drive the auto-echo body and re-queue on in_pipe.
Auto-echo counters under s_dcd_auto_echo_* start tracking.
Note
Bypasses USBX for the data path; do not combine with _ux_device_class_cdc_acm_read / _write on the same pipes.
Since
0.1.0

Enable ISR-side auto-echo from a bulk OUT pipe to a bulk IN pipe.

All data arriving on out_pipe (bulk OUT) is drained and re-queued onto in_pipe (bulk IN) from inside the IRQ path. Workaround for ThreadX worker thread scheduling failure on this silicon. Once enabled, the loop runs whenever internal_irq_walk_pipe encounters an OUT pipe with no waiter; see internal_irq_auto_echo for the body.

Parameters
[in]out_pipePipe index to drain on (bulk OUT).
[in]in_pipePipe index to re-queue on (bulk IN).
Returns
No value; the call cannot fail.
Note
Auto-echo is enabled on the requested pipe pair.
Precondition
Both pipes are configured via ra8_usb_configure_endpoint.
Called from task / startup context (not from inside an ISR).
Postcondition
g_dcd_auto_echo_enable == 1.
g_dcd_auto_echo_out_pipe == out_pipe and g_dcd_auto_echo_in_pipe == in_pipe.
Note
Not thread-safe; intended for one-shot configuration at startup.
Since
0.1.0

Definition at line 141 of file ux_dcd_ra8_usb.c.

References g_dcd_auto_echo_enable, g_dcd_auto_echo_in_pipe, and g_dcd_auto_echo_out_pipe.

Referenced by demo_cdc_activate(), demo_cdc_activate(), and ns_cdc_activate().

◆ ux_dcd_ra8_usb_initialize()

ra8_err_t ux_dcd_ra8_usb_initialize ( ra8_usb_speed_t speed)
nodiscard

Register the ra8_usb bridge as the active USBX DCD.

Wraps ra8_usb_device_init and stamps the global _ux_system_slave -> ux_system_slave_dcd so subsequent ux_device_class_*_initialize calls land on this bridge. The D+ pull-up is left off; the caller raises it via ra8_usb_device_attach / ra8_nsc_usb_attach once descriptors are wired up.

Parameters
[in]speedWhich controller (FS or HS).
Returns
ra8_err_t error code.
Return values
k_ra8_okDCD installed; ready for class init.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_hw_init_failedra8_usb_device_init failed.
Precondition
_ux_system_initialize has run.
Single-threaded init context.
Postcondition
_ux_system_slave -> ux_system_slave_dcd.ux_slave_dcd_function points at the bridge dispatcher.
ra8_usb_* controller is clocked, IRQs unmasked.
Note
Not thread-safe.
See also
ux_dcd_ra8_usb_uninitialize
Since
0.1.0

Register the ra8_usb bridge as the active USBX DCD.

Initialises the underlying ra8_usb_* register layer for the given speed (FS or HS), attaches the bridge's priv_event_cb so the dispatcher can re-enter USBX, binds the controller into the USBX DCD ownership block (_ux_system_slave), wires the matching ELC event into the NVIC, parses the active device descriptor framework, and stamps EP0 so the chapter-9 dispatcher accepts the host's first SETUP token. Idempotent across calls: re-running with the same speed is a no-op once g_dcd.state has reached ready.

Parameters
[in]speedWhich controller to bring up (k_ra8_usb_speed_fs or k_ra8_usb_speed_hs).
Returns
ra8_err_t status code.
Return values
k_ra8_okBridge fully initialized and ready for enumeration.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_internalA fallible driver or ownership initialisation step failed.
Precondition
_ux_system_slave is bound by _ux_device_stack_initialize.
Caller is on the USBX device task / init context (not in IRQ).
Postcondition
g_dcd.state is k_ux_dcd_ra8_usb_state_ready on success.
EP0 transfer request is populated and the device is in ATTACHED state.
Note
Not thread-safe; intended to run once during USBX init.
Since
0.1.0

Definition at line 521 of file ux_dcd_ra8_usb.c.

References g_dcd, g_lpsts_after_dcd_init, g_syscfg_after_dcd_init, internal_init_bind_owner(), internal_init_parse_framework(), internal_init_setup_ep0(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_speed_hs, priv_event_cb(), ra8_log_info, RA8_RETURN_ON_ERROR, ra8_usb_attach_handler(), ra8_usb_device_init(), ra8_usb_hs(), ra8_usbhs_lpsts(), s_tag, and r_usb_regs_t::SYSCFG.

Referenced by cdc_device_worker(), demo_worker(), demo_worker_start_dcd(), dfu_device_worker(), hid_device_worker(), hid_device_worker(), microsd_device_worker(), mlun_device_worker(), ns_usb_worker(), ospirw_device_worker(), sdmsc_device_worker(), selftest_device_worker(), selftest_device_worker(), and wlun_device_worker().

◆ ux_dcd_ra8_usb_irq()

void ux_dcd_ra8_usb_irq ( ra8_usb_speed_t speed,
uint16_t intsts0 )

ISR-context bottom-half.

Decodes INTSTS0 and posts the relevant USBX transfer semaphore.

Wired into the project's USB ISR via ra8_usb_attach_handler during ux_dcd_ra8_usb_initialize. The handler walks the BRDY / BEMP / CTRT bits, looks up the active UX_SLAVE_TRANSFER, copies bytes in / out of the pipe FIFO via ra8_usb_queue_in / ra8_usb_queue_out, and posts the request semaphore on completion.

Parameters
[in]speedWhich controller fired (passed through from ra8_usb_dispatch).
[in]intsts0Snapshot of INTSTS0 at the time of the IRQ.
Precondition
Bridge is in k_ux_dcd_ra8_usb_state_ready or _active.
Postcondition
INTSTS0 event bits the bridge handles are cleared.
Note
Re-entrant only across speed instances (FS vs HS).
Since
0.1.0
Precondition
Module has been initialized.
Postcondition
Side effects bounded to documented state.

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().

◆ ux_dcd_ra8_usb_irq_reenable()

void ux_dcd_ra8_usb_irq_reenable ( void )

Re-enable the USB NVIC IRQ at the controller level.

Call from a periodic context (SysTick, watchdog) to recover after the ISR's spurious-entry path masked the line to stop a USBR-driven IRQ storm. Writes 1 to NVIC ISER[0] bit 0.

Precondition
ra8_isr mapped USBHS to NVIC IRQ 0 (project-wide invariant).
Caller is the periodic re-arm context, not the storm-affected ISR.
Postcondition
NVIC routes the next USBHS event to internal_usbhs_isr.
No other CPU / module state is changed.
Note
Idempotent; safe to call from polling context.
Since
0.1.0

Re-enable the USB NVIC IRQ at the controller level.

The recovery half of the USBFS interrupt-storm guard. Each USB-FS app's SysTick_Handler calls this every 1 ms. Zeroing g_isr_spurious_run makes that counter a per-millisecond rate gauge – so normal idle SOFR can never accumulate to the mask threshold – and re-enabling the NVIC line undoes any mask internal_usbfs_isr applied. Re-enabling an already-enabled line is a no-op, so calling this outside a storm is harmless. SysTick is used rather than a ThreadX TX_TIMER because it is an exception handler: it keeps running even while a storm has thread mode – and the ThreadX timer subsystem – starved.

Returns
No value; the helper is unconditional.
Note
g_isr_spurious_run == 0 and the USB IRQ line is enabled.
Precondition
s_usb_irq_slot resolved (ux_dcd_ra8_usb_initialize has run).
Called from the per-app 1 ms SysTick handler (exception context).
Postcondition
g_isr_spurious_run == 0.
NVIC re-routes the next USB event to the registered trampoline.
Note
Idempotent; intended to be called from the 1 ms SysTick handler.
Since
0.1.0

Definition at line 260 of file ux_dcd_ra8_usb.c.

◆ ux_dcd_ra8_usb_state()

ra8_usb_dcd_state_t ux_dcd_ra8_usb_state ( void )

Read the bridge run-state.

Test-only; not part of the USBX contract.

Returns
Current ra8_usb_dcd_state_t.
Precondition
None.
Postcondition
No state mutated.
Note
Thread-safe (single 8-bit load).
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.

Read the bridge run-state.

See implementation for details.

Returns
Result code or value; see implementation.
Return values
0Success or default value.
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 603 of file ux_dcd_ra8_usb.c.

References g_dcd.

◆ ux_dcd_ra8_usb_uninitialize()

ra8_err_t ux_dcd_ra8_usb_uninitialize ( void )
nodiscard

Tear down the ra8_usb DCD bridge.

Returns
ra8_err_t error code.
Return values
k_ra8_okBridge released.
k_ra8_err_invalid_stateBridge was never initialized.
Precondition
ux_dcd_ra8_usb_initialize previously succeeded.
Postcondition
Controller MSTP-gated; subsequent USBX calls fail.
Note
Not thread-safe.
Since
0.1.0

Tear down the ra8_usb DCD bridge.

See implementation for details.

Returns
Result code or value; see implementation.
Return values
0Success or default value.
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 569 of file ux_dcd_ra8_usb.c.

References g_dcd, k_ra8_err_invalid_state, k_ra8_ok, k_ux_dcd_ra8_usb_state_uninit, ra8_usb_attach_handler(), and ra8_usb_device_deinit().