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

Native USB controller driver public API – shared types + device mode. More...

#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_usb_device.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_usb_setup_t
 Decoded 8-byte USB SETUP packet. More...

Typedefs

typedef void(* ra8_usb_event_fn_t) (void *ctx, ra8_usb_speed_t speed, uint16_t status_mask)
 USB event callback signature.

Enumerations

enum  ra8_usb_speed_t : uint8_t {
  k_ra8_usb_speed_fs = 0U ,
  k_ra8_usb_speed_hs = 1U
}
 Selects which controller instance the call targets. More...
enum  ra8_usb_dev_state_t : uint8_t {
  k_ra8_usb_dev_state_powered = 0U ,
  k_ra8_usb_dev_state_default = 1U ,
  k_ra8_usb_dev_state_address = 2U ,
  k_ra8_usb_dev_state_configured = 3U ,
  k_ra8_usb_dev_state_suspended = 4U
}
 Decoded INTSTS0.DVSQ[2:0] device-state values. More...
enum  ra8_usb_ep_dir_t : uint8_t {
  k_ra8_usb_ep_dir_out = 0U ,
  k_ra8_usb_ep_dir_in = 1U
}
 Endpoint direction. More...
enum  ra8_usb_ep_type_t : uint8_t {
  k_ra8_usb_ep_type_bulk = 0U ,
  k_ra8_usb_ep_type_intr = 1U ,
  k_ra8_usb_ep_type_iso = 2U
}
 Transfer type for a non-control endpoint. More...

Functions

ra8_err_t ra8_usb_device_init (ra8_usb_speed_t speed)
 Bring up a USB controller in device mode.
ra8_err_t ra8_usb_device_deinit (ra8_usb_speed_t speed)
 Tear down a USB controller and drop its MSTP reference.
ra8_err_t ra8_usb_device_attach (ra8_usb_speed_t speed, bool attached)
 Raise / drop the D+ pull-up to advertise the device to the host.
ra8_err_t ra8_usb_get_status (ra8_usb_speed_t speed, uint16_t *out_mask)
 Read raw INTSTS0 snapshot.
ra8_err_t ra8_usb_clear_status (ra8_usb_speed_t speed, uint16_t mask)
 Clear bits in INTSTS0.
ra8_err_t ra8_usb_get_device_state (ra8_usb_speed_t speed, ra8_usb_dev_state_t *out_state)
 Read the decoded device state from INTSTS0.DVSQ[2:0].
ra8_err_t ra8_usb_set_address (ra8_usb_speed_t speed, uint8_t address)
 Program the device USB address into USBADDR.
ra8_err_t ra8_usb_device_busreset_rearm (ra8_usb_speed_t speed)
 Re-arm the default control pipe (DCP) after a host-issued bus reset.
ra8_err_t ra8_usb_configure_endpoint (ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t ep_addr, ra8_usb_ep_dir_t dir, ra8_usb_ep_type_t type, uint16_t max_packet)
 Configure a non-control PIPE for IN or OUT bulk / interrupt / iso transfers.
ra8_err_t ra8_usb_stall_endpoint (ra8_usb_speed_t speed, uint8_t pipe_num)
 Stall a configured endpoint.
ra8_err_t ra8_usb_queue_in (ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
 Queue an IN transfer (device -> host) on pipe_num.
ra8_err_t ra8_usb_queue_out (ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t *out_buf, uint16_t *inout_len, bool rearm)
 Drain an OUT transfer (host -> device) from pipe_num.
ra8_err_t ra8_usb_rearm_out_pipe (ra8_usb_speed_t speed, uint8_t pipe_num)
 Re-arm an OUT pipe that the controller has parked at PID=NAK.
ra8_err_t ra8_usb_park_out_pipe (ra8_usb_speed_t speed, uint8_t pipe_num)
 Park an OUT pipe at PID=NAK so an idle pipe stays quiescent.
ra8_err_t ra8_usb_read_setup_if_valid (ra8_usb_speed_t speed, ra8_usb_setup_t *out_setup)
 Snapshot the current SETUP packet from the controller, gated on INTSTS0.VALID (FS / CTRT path).
ra8_err_t ra8_usb_read_setup_unconditional (ra8_usb_speed_t speed, ra8_usb_setup_t *out_setup)
 Snapshot the current SETUP packet from the controller without gating on INTSTS0.VALID (HS / SQMON polled-worker path).
ra8_err_t ra8_usb_control_response (ra8_usb_speed_t speed, bool accept)
 Issue a control-transfer status response on EP0.
ra8_err_t ra8_usb_dcp_in_data (ra8_usb_speed_t speed, const uint8_t *data, uint16_t len)
 Push the EP0 / DCP IN data-stage payload for a control transfer.
ra8_err_t ra8_usb_dcp_out_arm (ra8_usb_speed_t speed)
 Arm the DCP (EP0) to receive a host-to-device control data stage.
ra8_err_t ra8_usb_dcp_out_read (ra8_usb_speed_t speed, uint8_t *buf, uint16_t cap, uint16_t *out_rx)
 Drain an armed control-OUT data stage from the DCP (EP0).
void ra8_usb_attach_handler (ra8_usb_speed_t speed, ra8_usb_event_fn_t fn, void *ctx)
 Install (or detach) the per-controller USB event handler.
void ra8_usb_dispatch (ra8_usb_speed_t speed)
 Snapshot INTSTS0 and fire the installed event handler.
uint16_t ra8_usb_intsts0_snapshot (ra8_usb_speed_t speed)
 Read INTSTS0 without acking any bits.
ra8_err_t ra8_usb_enter_stop (ra8_usb_speed_t speed)
 Drop the controller's MSTP gate without touching SYSCFG.
ra8_err_t ra8_usb_exit_stop (ra8_usb_speed_t speed)
 Re-enable the controller's MSTP gate (counterpart to ra8_usb_enter_stop).

Detailed Description

Native USB controller driver public API – shared types + device mode.

Device-mode half of the hand-written, FSP-equivalent driver for the two USB controllers on the Renesas RA8D2 (USBFS @ 0x40250000, USBHS @ 0x40351000). This sub-header carries the public types shared by both device and host modes plus the device-mode lifecycle, status, endpoint, control-transfer, IRQ-delivery, and power surface. The host-mode surface lives in ra8_usb_host.h. Both are aggregated by the thin umbrella ra8_usb.h.

Since
0.1.0

Definition in file ra8_usb_device.h.

Typedef Documentation

◆ ra8_usb_event_fn_t

typedef void(* ra8_usb_event_fn_t) (void *ctx, ra8_usb_speed_t speed, uint16_t status_mask)

USB event callback signature.

Parameters
[in]ctxCaller-supplied context.
[in]speedWhich controller fired.
[in]status_maskSnapshot of INTSTS0 at dispatch time.
Note
Invoked from the dispatch site (typically ISR context).

Definition at line 105 of file ra8_usb_device.h.

Enumeration Type Documentation

◆ ra8_usb_dev_state_t

enum ra8_usb_dev_state_t : uint8_t

Decoded INTSTS0.DVSQ[2:0] device-state values.

Stable enum used by the public surface. Internal masks still live in ra8_usb_regs.h::ra8_usb_dvsq_t.

Enumerator
k_ra8_usb_dev_state_powered 

Powered, no reset yet.

k_ra8_usb_dev_state_default 

Default (post reset).

k_ra8_usb_dev_state_address 

Address assigned.

k_ra8_usb_dev_state_configured 

Configured.

k_ra8_usb_dev_state_suspended 

Suspended.

Definition at line 51 of file ra8_usb_device.h.

◆ ra8_usb_ep_dir_t

enum ra8_usb_ep_dir_t : uint8_t

Endpoint direction.

Enumerator
k_ra8_usb_ep_dir_out 

Host -> device.

k_ra8_usb_ep_dir_in 

Device -> host.

Definition at line 63 of file ra8_usb_device.h.

◆ ra8_usb_ep_type_t

enum ra8_usb_ep_type_t : uint8_t

Transfer type for a non-control endpoint.

Enumerator
k_ra8_usb_ep_type_bulk 

Bulk transfer.

k_ra8_usb_ep_type_intr 

Interrupt transfer.

k_ra8_usb_ep_type_iso 

Isochronous transfer.

Definition at line 72 of file ra8_usb_device.h.

◆ ra8_usb_speed_t

enum ra8_usb_speed_t : uint8_t

Selects which controller instance the call targets.

Enumerator
k_ra8_usb_speed_fs 

Full-Speed controller (USBFS @ 0x40250000).

k_ra8_usb_speed_hs 

High-Speed controller (USBHS @ 0x40351000).

Definition at line 39 of file ra8_usb_device.h.

Function Documentation

◆ ra8_usb_attach_handler()

void ra8_usb_attach_handler ( ra8_usb_speed_t speed,
ra8_usb_event_fn_t fn,
void * ctx )

Install (or detach) the per-controller USB event handler.

Each controller (USBFS, USBHS) has its own callback slot, so one firmware image can run different upper-layer drivers on each controller simultaneously (e.g. USBX/DCD bridge on USBHS, a bare-CDC handler on USBFS). The matching ra8_usb_dispatch(speed) only fires the callback registered for that speed.

Parameters
[in]speedWhich controller's callback slot to update.
[in]fnCallback. NULL detaches.
[in]ctxContext passed to fn.

Slot replacement performs no fallible work; callers observe completion when this function returns.

Precondition
speed is k_ra8_usb_speed_fs or k_ra8_usb_speed_hs.
Caller serializes this update with ra8_usb_dispatch(speed).
Postcondition
Subsequent ra8_usb_dispatch(speed) calls route through fn.
Passing NULL for fn prevents subsequent callback invocation for the selected controller.
Note
Not thread-safe.
Since
0.1.0

Definition at line 90 of file ra8_usb_irq.c.

References internal_cb_slot(), s_usb_ctx, and s_usb_fn.

Referenced by ra8_usb_pal_deinit(), ra8_usb_pal_init(), ux_dcd_ra8_usb_initialize(), and ux_dcd_ra8_usb_uninitialize().

◆ ra8_usb_clear_status()

ra8_err_t ra8_usb_clear_status ( ra8_usb_speed_t speed,
uint16_t mask )
nodiscard

Clear bits in INTSTS0.

Parameters
[in]speedWhich controller.
[in]maskBits to clear.
Returns
ra8_err_t error code.
Return values
k_ra8_okBits cleared.
k_ra8_err_invalid_argspeed out of range.
Precondition
None.
Postcondition
INTSTS0 & mask == 0.
Note
Not thread-safe.
Since
0.1.0

Clear bits in INTSTS0.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]maskSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 367 of file ra8_usb_device.c.

References r_usb_regs_t::INTSTS0, k_ra8_err_invalid_arg, k_ra8_ok, and priv_pick().

Referenced by demo_poll_once(), and internal_ack_spurious().

◆ ra8_usb_configure_endpoint()

ra8_err_t ra8_usb_configure_endpoint ( ra8_usb_speed_t speed,
uint8_t pipe_num,
uint8_t ep_addr,
ra8_usb_ep_dir_t dir,
ra8_usb_ep_type_t type,
uint16_t max_packet )
nodiscard

Configure a non-control PIPE for IN or OUT bulk / interrupt / iso transfers.

Programs PIPESEL, PIPECFG, PIPEMAXP, PIPECTR[n] for pipe_num. Mirrors FSP's usb_cstd_pipe_table writes condensed for the device-mode case. The pipe is left with PID = NAK so the stack can queue data with ra8_usb_queue_in / ra8_usb_queue_out before transitioning to BUF.

Parameters
[in]speedWhich controller.
[in]pipe_numPIPE number 1..9.
[in]ep_addrEndpoint address (USB EP number, 1..15).
[in]dirEndpoint direction.
[in]typeEndpoint type.
[in]max_packetMaximum packet size.
Returns
ra8_err_t error code.
Return values
k_ra8_okPipe configured.
k_ra8_err_invalid_argPipe / EP / dir / type / size invalid.
Precondition
ra8_usb_device_init ran for this speed.
Postcondition
Pipe responds NAK, software toggle cleared.
Note
Not thread-safe.
Since
0.1.0

Configure a non-control PIPE for IN or OUT bulk / interrupt / iso transfers.

See the public header for the documented contract; this definition implements it. Sequence (FIT r_usb_creg_abs.c::usb_cstd_pipe_init mirror): quiesce -> PIPESEL window write of PIPECFG/PIPEMAXP/PIPEPERI -> deselect window -> finalize PIPECTR -> arm per-pipe IRQ.

Parameters
[in]speedWhich controller (FS/HS).
[in]pipe_numPipe index 1..9.
[in]ep_addrUSB endpoint address (low nibble = EP number).
[in]dirIN/OUT direction.
[in]typeBulk / Interrupt / Iso.
[in]max_packetwMaxPacketSize from the descriptor.
Returns
Result code.
Return values
k_ra8_okPipe configured and PID set per direction.
k_ra8_err_invalid_argspeed/pipe/ep/type/max_packet out of range.
Precondition
Controller is powered (ra8_usb_device_init has run).
Pipe is not currently mid-transfer (caller serialises).
Postcondition
PIPECFG/PIPEMAXP/PIPEPERI reflect the requested config.
BRDYENB or BEMPENB bit for pipe is set per direction.
Note
Not thread-safe.
Since
0.1.0

Definition at line 661 of file ra8_usb_device.c.

References internal_check_ep_args(), internal_pipe_arm_irq(), internal_pipe_finalize(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_ep_type_bulk, r_usb_regs_t::PIPEBUF, r_usb_regs_t::PIPECFG, r_usb_regs_t::PIPEMAXP, r_usb_regs_t::PIPEPERI, r_usb_regs_t::PIPESEL, priv_pick(), priv_pipe_quiesce(), priv_pipebuf_word(), and priv_pipecfg_word().

Referenced by internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_configure_pipes(), internal_endpoint_create(), and internal_endpoint_create().

◆ ra8_usb_control_response()

ra8_err_t ra8_usb_control_response ( ra8_usb_speed_t speed,
bool accept )
nodiscard

Issue a control-transfer status response on EP0.

Wraps the DCPCTR.PID + DCPCTR.CCPL dance documented in HUM Ch 36.2.21. Pass accept = true to drive ACK / move to the status stage; accept = false issues STALL on EP0.

Parameters
[in]speedWhich controller.
[in]accepttrue for ACK, false for STALL.
Returns
ra8_err_t error code.
Return values
k_ra8_okResponse written.
k_ra8_err_invalid_argspeed out of range.
Precondition
ra8_usb_device_init ran for this speed.
Postcondition
DCPCTR PID set accordingly; CCPL pulsed on accept.
Note
Not thread-safe.
Since
0.1.0

Issue a control-transfer status response on EP0.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]acceptSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 567 of file ra8_usb_xfer.c.

References r_usb_regs_t::DCPCTR, k_ra8_dcpctr_bit_ccpl, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pid_buf, k_ra8_pid_stall, priv_dcp_pid(), priv_pick(), and priv_rmw16().

Referenced by demo_dispatch_setup(), demo_poll_once(), internal_ctrt_dispatch_fresh_setup(), internal_dispatch_class_setup(), internal_ep0_transfer(), priv_handle_ctrl_out_data(), priv_handle_ctrt(), ra8_usb_paud_handle_setup(), ra8_usb_phid_handle_setup(), ra8_usb_pprn_handle_setup(), and ra8_usb_pvnd_handle_setup().

◆ ra8_usb_dcp_in_data()

ra8_err_t ra8_usb_dcp_in_data ( ra8_usb_speed_t speed,
const uint8_t * data,
uint16_t len )
nodiscard

Push the EP0 / DCP IN data-stage payload for a control transfer.

The host has issued a control-IN SETUP (e.g. GET_DESCRIPTOR) and the device-side stack now needs to deliver the response bytes. This call selects the DCP via CFIFOSEL.CURPIPE = 0, then iteratively writes the payload into CFIFO in DCPMAXP-sized chunks, asserting BVAL after each chunk and waiting for FRDY to re-assert (which the controller raises after sending the previous chunk to the host). DCPCTR.PID is raised from NAK to BUF after the first chunk so the controller answers the IN tokens. CCPL is not pulsed here: the status stage is host-initiated and is acknowledged later when CTSQ transitions to the status-stage value (handled by the bridge's CTRT path).

For len > DCPMAXP (the common case for CONFIGURATION descriptors), the function blocks until every chunk has been handed to the controller. If len is an exact non-zero multiple of DCPMAXP, no terminating zero-length packet is sent here; the host asks for the exact wTotalLength and is satisfied by the last full-size packet.

Parameters
[in]speedWhich controller (FS or HS).
[in]dataPointer to the IN data-stage payload. May be nullptr only if len == 0.
[in]lenByte count. May exceed DCPMAXP; the call will chunk.
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes written, PID raised to BUF.
k_ra8_err_invalid_argBad speed / data / length combination.
k_ra8_err_hw_timeoutFRDY never asserted.
Precondition
ra8_usb_device_init ran for this speed.
A control-IN SETUP was just observed (CTSQ = read data stage).
Postcondition
EP0 IN buffer holds the data, DCPCTR.PID = BUF.
Note
Not thread-safe.
Since
0.1.0

Push the EP0 / DCP IN data-stage payload for a control transfer.

Push a control-IN data-stage payload (or zero-length packet) into the DCP FIFO, set BVAL=1 and DCPCTR.PID=BUF so the chip transmits on the next IN token from the host. Captures pre/post register snapshots into g_dcp_push_count and friends for JLink-readable diagnostic. The status stage (CCPL) is intentionally NOT pulsed here – the bridge handles it on the CTSQ status-stage edge.

Parameters
[in]speedWhich controller (FS or HS).
[in]dataPayload bytes (may be NULL when len==0).
[in]lenByte count; may exceed DCPMAXP and will be chunked.
Returns
ra8_err_t result code.
Return values
k_ra8_okPayload queued; PID=BUF.
k_ra8_err_invalid_argspeed out of range OR data NULL with len > 0.
k_ra8_err_hw_timeoutFRDY never asserted within the bound.
Precondition
Caller has cleared INTSTS0.VALID (PID writes are gated by VALID per HUM Ch 37.2.31 p 2095).
USB module clock and power are on.
Postcondition
On success, len bytes have been queued and DCPCTR.PID == BUF.
On error, DCPCTR.PID is left unchanged from its prior value.
Note
Not thread-safe; caller holds the DCP lock.
Since
0.1.0

Definition at line 214 of file ra8_usb_xfer.c.

References r_usb_regs_t::CFIFOCTR, r_usb_regs_t::DCPCTR, g_dcp_cfifoctr_post, g_dcp_cfifoctr_pre, g_dcp_dcpctr_post_push, g_dcp_dcpctr_pre_push, g_dcp_last_err, g_dcp_last_len, g_dcp_push_count, internal_dcp_in_payload(), internal_dcp_in_zlp(), k_ra8_err_invalid_arg, k_ra8_fifoctr_bclr, k_ra8_ok, priv_pick(), and priv_select_cfifo().

Referenced by demo_printer_setup(), demo_stage_descriptor(), and internal_ep0_transfer().

◆ ra8_usb_dcp_out_arm()

ra8_err_t ra8_usb_dcp_out_arm ( ra8_usb_speed_t speed)
nodiscard

Arm the DCP (EP0) to receive a host-to-device control data stage.

The non-blocking front half of the control-OUT receive (the OUT counterpart of ra8_usb_dcp_in_data). Clears any stale DCP BRDY latch, enables the DCP BRDY interrupt, and sets DCPCTR.PID = BUF so the SIE ACKs the host's OUT token. Returns immediately – the host's OUT packet then raises a fresh USB IRQ where ra8_usb_dcp_out_read drains the bank. The arm/read split is mandatory on the USB self-loop, where the FS device ISR and the HS host worker thread share one CPU: a blocking receive in the SETUP ISR would spin out the very thread that must send the data.

Parameters
[in]speedWhich controller (FS or HS).
Returns
ra8_err_t error code.
Return values
k_ra8_okDCP armed (BRDY enabled, PID = BUF).
k_ra8_err_invalid_argspeed selects no controller.
k_ra8_err_hw_timeoutBRDYENB read-back did not latch the DCP bit.
Precondition
ra8_usb_device_init ran for this speed.
A control-OUT SETUP with wLength > 0 was just observed and VALID cleared.
Postcondition
DCP BRDY is enabled and DCPCTR.PID = BUF.
The host's OUT data is ACKed into the DCP bank on arrival.
Note
Non-blocking; ISR-safe. Not thread-safe against a concurrent EP0 user.
See also
ra8_usb_dcp_out_read
Since
0.1.0

Arm the DCP (EP0) to receive a host-to-device control data stage.

Prepares the DCP (EP0) to receive the data stage of a host-to-device control transfer (e.g. a DFU_DNLOAD firmware block) WITHOUT blocking: clears any stale DCP BRDY latch, enables the DCP BRDY interrupt so the host's OUT packet raises a fresh USB IRQ, and sets PID=BUF so the SIE ACKs the OUT token (until then the host NAK-retries the data packet). The matching ra8_usb_dcp_out_read() drains the bank from the BRDY ISR. Splitting arm from read is mandatory on the self-loop: the FS device ISR and the HS host worker share one CPU, so a blocking receive in the SETUP ISR would spin out the very thread that must SEND the data.

Parameters
[in]speedController (FS/HS) the control transfer is on.
Returns
k_ra8_ok when the DCP is armed, else an arg/HW code.
Return values
k_ra8_okDCP armed; BRDY enabled and PID=BUF.
k_ra8_err_invalid_argspeed selects no controller.
k_ra8_err_hw_timeoutBRDYENB read-back did not latch the DCP bit.
Precondition
A SETUP for an OUT request with wLength > 0 has just been decoded.
INTSTS0.VALID has been cleared (the PID write gate is open).
Postcondition
DCP BRDY is enabled and PID=BUF; the host's OUT data is ACKed on arrival.
Note
Non-blocking; ISR-safe. Device-side only.
Since
0.1.0

Definition at line 570 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BRDYENB, r_usb_regs_t::BRDYSTS, r_usb_regs_t::CFIFOCTR, r_usb_regs_t::DCPCTR, k_ra8_dcpctr_bit_ccpl, k_ra8_dcpctr_bit_sqset, k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_fifoctr_bclr, k_ra8_ok, k_ra8_pid_buf, k_ra8_pid_nak, k_ra8_usb_dcp_pipe0_bit, priv_dcp_pid(), priv_pick(), priv_rmw16(), and priv_select_cfifo().

Referenced by internal_pull_data_stage(), and internal_try_defer_ctrl_out().

◆ ra8_usb_dcp_out_read()

ra8_err_t ra8_usb_dcp_out_read ( ra8_usb_speed_t speed,
uint8_t * buf,
uint16_t cap,
uint16_t * out_rx )
nodiscard

Drain an armed control-OUT data stage from the DCP (EP0).

The back half of the control-OUT receive: call from the BRDY ISR once ra8_usb_dcp_out_arm armed the DCP and the host's OUT packet landed (DCP BRDY asserted). Disables the one-shot DCP BRDY, drains one buffer bank via the CFIFO into buf, and parks DCPCTR.PID = NAK. Used for class requests that carry a host->device data stage (e.g. DFU_DNLOAD); the control-write status stage is driven separately via the CCPL pulse.

Parameters
[in]speedWhich controller (FS or HS).
[out]bufDestination for the received bytes (non-NULL).
[in]capCapacity of buf in bytes.
[out]out_rxReceives the host's packet length in bytes (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okA packet (possibly zero-length) was drained.
k_ra8_err_invalid_argBad speed, or buf / out_rx NULL.
k_ra8_err_no_dataDCP BRDY is not set; the OUT packet has not landed.
k_ra8_err_hw_timeoutCFIFO never reported FRDY for the DCP bank.
Precondition
ra8_usb_dcp_out_arm armed the DCP for this transfer.
Caller observed the DCP BRDY interrupt (or polls it via the no-data return).
Postcondition
out_rx holds the host's DTLN; buf holds min(DTLN, cap) bytes.
DCP BRDY is disabled + cleared and DCPCTR.PID = NAK.
Note
Non-blocking past a bounded CFIFO FRDY wait; ISR-safe.
See also
ra8_usb_dcp_out_arm
Since
0.1.0

Drain an armed control-OUT data stage from the DCP (EP0).

Drains one buffer-bank's worth of control-OUT data from the DCP (EP0) after ra8_usb_dcp_out_arm() armed it and the host's OUT packet landed (DCP BRDY asserted). Disables the one-shot DCP BRDY, W0C-clears the latch, drains via the CFIFO, and parks the DCP NAK. Does NOT re-arm (unlike the old blocking variant): the caller is the BRDY ISR, so the bank is already full. Single bank (one packet up to the DCP MPS); the control-write status stage is driven separately via the CCPL pulse.

Parameters
[in]speedController (FS/HS) the transfer is on.
[out]bufDestination for the received bytes.
[in]capCapacity of buf in bytes.
[out]out_rxReceives the byte count the host sent (DTLN).
Returns
k_ra8_ok on a drained packet (incl. a ZLP), else a no-data/timeout code.
Return values
k_ra8_okA packet (possibly zero-length) was drained.
k_ra8_err_invalid_argspeed invalid or buf / out_rx NULL.
k_ra8_err_no_dataDCP BRDY is not set; the OUT packet has not landed.
k_ra8_err_hw_timeoutCFIFO never reported FRDY for the DCP bank.
Precondition
ra8_usb_dcp_out_arm() armed the DCP for this transfer.
Caller observed the DCP BRDY interrupt (or polls it via the no-data return).
Postcondition
out_rx holds the host's packet length; buf holds min(DTLN, cap).
DCP BRDY is disabled + cleared and the DCP PID is left NAK.
Note
Non-blocking past a bounded CFIFO FRDY wait; ISR-safe. Device-side only.
Since
0.1.0

Definition at line 634 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BRDYENB, r_usb_regs_t::BRDYSTS, r_usb_regs_t::CFIFOCTR, k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_err_no_data, k_ra8_fifoctr_bclr, k_ra8_fifoctr_dtln, k_ra8_ok, k_ra8_pid_nak, k_ra8_usb_dcp_pipe0_bit, priv_dcp_pid(), priv_fifo_read(), priv_pick(), priv_select_cfifo(), and priv_wait_frdy().

Referenced by internal_pull_data_stage(), and priv_handle_ctrl_out_data().

◆ ra8_usb_device_attach()

ra8_err_t ra8_usb_device_attach ( ra8_usb_speed_t speed,
bool attached )
nodiscard

Raise / drop the D+ pull-up to advertise the device to the host.

Parameters
[in]speedWhich controller.
[in]attachedtrue to assert pull-up, false to drop.
Returns
ra8_err_t error code.
Return values
k_ra8_okPull-up state updated.
k_ra8_err_invalid_argspeed out of range.
Precondition
ra8_usb_device_init has been called for this speed.
Postcondition
On success, SYSCFG.DPRPU matches attached.
Note
Not thread-safe.
Since
0.1.0

Raise / drop the D+ pull-up to advertise the device to the host.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]attachedSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 267 of file ra8_usb_device.c.

References g_lpsts_after_attach, g_syscfg_after_attach, g_syscfg_before_dprpu, g_syssts0_after_attach, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_syscfg_bit_cnen, k_ra8_syscfg_bit_dprpu, k_ra8_usb_speed_hs, priv_pick(), priv_rmw16(), ra8_usbhs_lpsts(), r_usb_regs_t::SYSCFG, and r_usb_regs_t::SYSSTS0.

Referenced by cdc_device_worker(), demo_usb_bringup(), 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(), ra8_nsc_usb_attach(), ra8_usb_cdc_attach(), ra8_usb_cdc_deinit(), ra8_usb_pal_attach(), ra8_usb_pal_deinit(), ra8_usb_paud_close(), ra8_usb_phid_close(), ra8_usb_pmsc_close(), ra8_usb_pprn_close(), ra8_usb_pvnd_close(), sdmsc_device_worker(), selftest_device_worker(), selftest_device_worker(), and wlun_device_worker().

◆ ra8_usb_device_busreset_rearm()

ra8_err_t ra8_usb_device_busreset_rearm ( ra8_usb_speed_t speed)
nodiscard

Re-arm the default control pipe (DCP) after a host-issued bus reset.

The RA8D2 USB IP latches INTSTS0.DVST whenever the host drives a USB bus reset that puts the controller into the Default state (DVSQ == 0x10). FSP's reference flow (usb_pstd_busreset in r_usb_basic/src/driver/r_usb_psignal.c) re-programmes DCPCFG = 0 and DCPMAXP = max_packet on every such transition so the IP is ready to ACK the host's first SETUP token within the 10 ms window USB 2.0 Section 9.2.6.3 mandates between reset-deassert and the first GET_DESCRIPTOR. Without this re-arm the controller silently drops SETUP tokens, the host re-issues bus reset, and the device loops forever between Default and Suspended-from-Default (DVSQ = 0x10 -> 0x50).

Specifically this call:

  1. Re-writes DCPCFG = 0 (no continuous transfers).
  2. Re-writes DCPMAXP = 64 (HS / FS bMaxPacketSize0).
  3. Clears DCPCTR so PID returns to NAK and CCPL is de-asserted.
  4. Walks PIPECTR[1..9] clearing PID + ACLRM so any pre-reset pipe state is forgotten.
  5. Re-applies the device-mode INTENB0 mask (BEMP / BRDY / NRDY / CTRT / DVST / SOFR / RSME / VBSE) – the IP can drop CTRT enables across a bus reset on some silicon revisions.
Parameters
[in]speedWhich controller (k_ra8_usb_speed_fs or _hs).
Returns
ra8_err_t error code.
Return values
k_ra8_okDCP re-armed.
k_ra8_err_invalid_argspeed out of range.
Precondition
ra8_usb_device_init ran for this speed.
Caller observed a DVST interrupt with DVSQ == default.
Postcondition
DCPMAXP == 64, DCPCTR == 0, all PIPECTR[i] PID == NAK.
INTENB0 matches the post-init device-mode mask.
Note
Safe to call from IRQ-callback context.
Since
0.1.0

Re-arm the default control pipe (DCP) after a host-issued bus reset.

Re-default DCPCFG/DCPMAXP, clear all PIPECTR[*], drop BRDYSTS/NRDYSTS/BEMPSTS, clear the DCP FIFO via CFIFOCTR.BCLR, and re-arm INTENB0 with the post-init mask. Mirrors FSP r_usb_psignal.c::usb_pstd_bus_reset.

Parameters
[in]speedWhich controller (FS or HS).
Returns
ra8_err_t result code.
Return values
k_ra8_okSuccess.
k_ra8_err_invalid_argspeed out of range.
Precondition
Module clock and power are on.
Caller is in IRQ-callback context (DVST=Default branch).
Postcondition
DCPCFG=0, DCPMAXP=64, DCP FIFO cleared, INTENB0 re-armed.
All non-control PIPECTR[*] cleared (PID=NAK).
Note
Not thread-safe; caller holds the DCP lock.
Since
0.1.0

Definition at line 478 of file ra8_usb_device.c.

References r_usb_regs_t::BEMPSTS, r_usb_regs_t::BRDYSTS, r_usb_regs_t::INTENB0, internal_dcp_reset_defaults(), k_ra8_err_invalid_arg, 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_ok, k_ra8_usb_pipectr_count, r_usb_regs_t::NRDYSTS, r_usb_regs_t::PIPECTR, and priv_pick().

Referenced by demo_handle_dvst(), and priv_dvst_default_state().

◆ ra8_usb_device_deinit()

ra8_err_t ra8_usb_device_deinit ( ra8_usb_speed_t speed)
nodiscard

Tear down a USB controller and drop its MSTP reference.

Parameters
[in]speedWhich controller to release.
Returns
ra8_err_t error code.
Return values
k_ra8_okController released.
k_ra8_err_invalid_argspeed out of range.
Precondition
Single-threaded shutdown context.
Postcondition
SYSCFG, INTENB0, INTENB1 all zero.
Controller MSTP-gated.
Note
Not thread-safe.
See also
ra8_usb_device_init
Since
0.1.0

Tear down a USB controller and drop its MSTP reference.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 234 of file ra8_usb_device.c.

References r_usb_regs_t::BEMPENB, r_usb_regs_t::BRDYENB, r_usb_regs_t::INTENB0, r_usb_regs_t::INTENB1, k_ra8_err_invalid_arg, r_usb_regs_t::NRDYENB, priv_mstp(), priv_pick(), ra8_mstp_disable(), and r_usb_regs_t::SYSCFG.

Referenced by ra8_usb_cdc_deinit(), ra8_usb_cdc_init(), ra8_usb_composite_close(), ra8_usb_pal_deinit(), ra8_usb_paud_close(), ra8_usb_phid_close(), ra8_usb_pmsc_close(), ra8_usb_pprn_close(), ra8_usb_pvnd_close(), and ux_dcd_ra8_usb_uninitialize().

◆ ra8_usb_device_init()

ra8_err_t ra8_usb_device_init ( ra8_usb_speed_t speed)
nodiscard

Bring up a USB controller in device mode.

Mirrors FSP's hw_usb_pmodule_init for the chosen instance:

  1. Releases the controller's MSTP gate.
  2. Drives SYSCFG.SCKE high and waits until the clock is stable.
  3. Clears SYSCFG.DRPD (host pull-down) and sets SYSCFG.USBE.
  4. Sets SYSCFG.HSE for the HS instance only.
  5. Programs the C/D0/D1 FIFOSEL access width to 16-bit.
  6. Loads the default control pipe (DCP) max-packet size to 64.
  7. Enables the device-mode interrupt set (BEMPE | BRDYE | NRDYE | DVSE | CTRE | VBSE).

D+ pull-up stays off; the caller raises it via ra8_usb_device_attach once descriptors are wired up.

Parameters
[in]speedWhich controller to bring up.
Returns
ra8_err_t error code.
Return values
k_ra8_okController ready, D+ pull-up off.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_hw_init_failedMSTP release failed.
Precondition
Caller holds single-threaded init context (or IRQs masked).
ra8_mstp_init and ra8_pwr_init have run.
Postcondition
Controller is clocked, D+ pull-up off, IRQs unmasked at controller level (NVIC line still owned by ra8_irq).
ra8_usb_get_device_state returns k_ra8_usb_dev_state_powered.
Note
Not thread-safe.
See also
ra8_usb_device_attach
ra8_usb_device_deinit
Since
0.1.0

Bring up a USB controller in device mode.

Dispatches FS vs HS bring-up, then programmes shared FIFO, DCP, and INTENB0 fields.

Parameters
[in]speedSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_argInvalid speed.
k_ra8_err_hw_timeoutHS PHY PLL lock timeout.
Precondition
MSTP and clock subsystem are armed.
Caller is single-threaded init context.
Postcondition
Module powered and SYSCFG.USBE = 1.
INTENB0 carries device-mode interrupt mask.
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 186 of file ra8_usb_device.c.

References g_lpsts_after_phy_bringup, g_syscfg_after_phy_bringup, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_speed_hs, priv_mstp(), priv_pick(), priv_usb_init_common(), priv_usbfs_module_bringup(), priv_usbhs_phy_bringup(), ra8_log_info_val, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, ra8_usbhs_lpsts(), s_tag, and r_usb_regs_t::SYSCFG.

Referenced by ra8_board_usbhs_device_init(), ra8_nsc_usb_init(), ra8_usb_cdc_init(), ra8_usb_composite_init(), ra8_usb_pal_init(), ra8_usb_paud_init(), ra8_usb_phid_init(), ra8_usb_pmsc_init(), ra8_usb_pprn_init(), ra8_usb_pvnd_init(), and ux_dcd_ra8_usb_initialize().

◆ ra8_usb_dispatch()

void ra8_usb_dispatch ( ra8_usb_speed_t speed)

Snapshot INTSTS0 and fire the installed event handler.

Reads INTSTS0, clears it, and invokes the registered callback with the snapshot. Designed to be called from the controller's NVIC ISR (USBFS_INT or USBHS_INT).

Parameters
[in]speedWhich controller fired.
Precondition
None.
Postcondition
INTSTS0 zeroed.
Note
Re-entrant only across instances; not within a single controller.
Since
0.1.0
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.

Snapshot INTSTS0 and fire the installed event handler.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 109 of file ra8_usb_irq.c.

References internal_cb_slot(), r_usb_regs_t::INTSTS0, 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_rsme, k_ra8_int0_bit_sofr, k_ra8_int0_bit_vbse, priv_pick(), s_usb_ctx, and s_usb_fn.

Referenced by internal_usbfs_isr(), internal_usbhs_isr(), and ns_usb_worker().

◆ ra8_usb_enter_stop()

ra8_err_t ra8_usb_enter_stop ( ra8_usb_speed_t speed)
nodiscard

Drop the controller's MSTP gate without touching SYSCFG.

Parameters
[in]speedWhich controller.
Returns
ra8_err_t error code.
Return values
k_ra8_okMSTP gate set.
k_ra8_err_invalid_argspeed out of range.
Precondition
None.
Postcondition
Controller is power-gated; register access is undefined.
Note
Not thread-safe.
Since
0.1.0

Drop the controller's MSTP gate without touching SYSCFG.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 192 of file ra8_usb_irq.c.

References k_ra8_err_invalid_arg, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, priv_mstp(), and ra8_mstp_disable().

◆ ra8_usb_exit_stop()

ra8_err_t ra8_usb_exit_stop ( ra8_usb_speed_t speed)
nodiscard

Re-enable the controller's MSTP gate (counterpart to ra8_usb_enter_stop).

Parameters
[in]speedWhich controller.
Returns
ra8_err_t error code.
Return values
k_ra8_okMSTP gate cleared.
k_ra8_err_invalid_argspeed out of range.
Precondition
None.
Postcondition
Controller registers are accessible.
Note
Not thread-safe.
Since
0.1.0

Re-enable the controller's MSTP gate (counterpart to ra8_usb_enter_stop).

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 213 of file ra8_usb_irq.c.

References k_ra8_err_invalid_arg, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, priv_mstp(), and ra8_mstp_enable().

◆ ra8_usb_get_device_state()

ra8_err_t ra8_usb_get_device_state ( ra8_usb_speed_t speed,
ra8_usb_dev_state_t * out_state )
nodiscard

Read the decoded device state from INTSTS0.DVSQ[2:0].

Parameters
[in]speedWhich controller.
[out]out_stateReceives the decoded state.
Returns
ra8_err_t error code.
Return values
k_ra8_okState read.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_state was NULL.
Precondition
out_state non-NULL.
Postcondition
No controller state mutated.
Note
Not thread-safe.
Since
0.1.0

Read the decoded device state from INTSTS0.DVSQ[2:0].

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]out_stateSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 392 of file ra8_usb_device.c.

References internal_decode_dvsq(), r_usb_regs_t::INTSTS0, k_ra8_err_invalid_arg, k_ra8_ok, priv_pick(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by demo_handle_dvst().

◆ ra8_usb_get_status()

ra8_err_t ra8_usb_get_status ( ra8_usb_speed_t speed,
uint16_t * out_mask )
nodiscard

Read raw INTSTS0 snapshot.

Parameters
[in]speedWhich controller.
[out]out_maskReceives the current INTSTS0.
Returns
ra8_err_t error code.
Return values
k_ra8_okMask returned.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_mask was NULL.
Precondition
out_mask non-NULL.
Postcondition
No controller state mutated.
Note
Not thread-safe.
Since
0.1.0

Read raw INTSTS0 snapshot.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]out_maskSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 341 of file ra8_usb_device.c.

References r_usb_regs_t::INTSTS0, k_ra8_err_invalid_arg, k_ra8_ok, priv_pick(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by demo_poll_once().

◆ ra8_usb_intsts0_snapshot()

uint16_t ra8_usb_intsts0_snapshot ( ra8_usb_speed_t speed)

Read INTSTS0 without acking any bits.

Snapshot accessor used by callers that want to inspect DVSQ / CTSQ status fields between dispatch ticks without disturbing the IRQ-bit state. Returns 0 if speed is invalid.

Parameters
[in]speedController selector.
Returns
Raw INTSTS0 value.
Return values
0invalid speed or controller not powered.
Precondition
Module is initialized via ra8_usb_device_init.
Caller has the controller powered.
Postcondition
No INTSTS0 bits are modified.
Returned value reflects the controller at call time.
Note
Pure MMIO read; safe to call from any context.
Since
0.1.0

Read INTSTS0 without acking any bits.

Pure MMIO read; no INTSTS0 bits are modified.

Parameters
[in]speedSee header.
Returns
INTSTS0 raw value.
Return values
0Invalid speed or controller not powered.
Precondition
Module state is consistent.
Controller register window is mapped.
Postcondition
No bits in INTSTS0 modified.
Caller-visible state matches the documented contract.
Note
Safe to call from any context.
Since
0.1.0

Definition at line 170 of file ra8_usb_irq.c.

References r_usb_regs_t::INTSTS0, and priv_pick().

Referenced by internal_usbfs_isr(), internal_usbhs_isr(), and ns_usb_worker().

◆ ra8_usb_park_out_pipe()

ra8_err_t ra8_usb_park_out_pipe ( ra8_usb_speed_t speed,
uint8_t pipe_num )
nodiscard

Park an OUT pipe at PID=NAK so an idle pipe stays quiescent.

The inverse of ra8_usb_rearm_out_pipe. An OUT pipe left at PID=BUF with its per-pipe BRDY enabled but with no consumer ready will ACK the next host OUT token into the pipe FIFO, latch BRDYSTS, and – because nothing drains it – hold INTSTS0.BRDY asserted, which re-fires the USB ISR continuously and starves RTOS thread mode. Parking the pipe at PID=NAK makes the controller NAK host OUT tokens (normal USB flow control: the host simply retries), so no data enters the FIFO, BRDYSTS never latches, and the ISR stays quiet until a consumer arms the pipe with ra8_usb_rearm_out_pipe.

Parameters
[in]speedWhich controller (FS / HS).
[in]pipe_numPIPE1..PIPE9 (must not be 0; DCP uses DCPCTR).
Returns
ra8_err_t error code.
Return values
k_ra8_okPipe parked at PID=NAK.
k_ra8_err_invalid_argspeed invalid or pipe_num out of range.
Precondition
Pipe was previously configured via ra8_usb_configure_endpoint with dir = k_ra8_usb_ep_dir_out.
No transfer is currently in flight on the pipe.
Postcondition
PIPECTR[pipe_num-1].PID == NAK.
Note
Not thread-safe; caller serialises against ra8_usb_rearm_out_pipe.
See also
ra8_usb_rearm_out_pipe
ra8_usb_configure_endpoint
Since
0.1.0

Park an OUT pipe at PID=NAK so an idle pipe stays quiescent.

See the public header for the documented contract; this definition implements it. Forces PIPECTR.PID = NAK so the controller NAKs (rather than ACKs) host OUT tokens while the pipe has no consumer, keeping BRDYSTS clear and the USB ISR quiescent.

Parameters
[in]speedSee header.
[in]pipe_numSee header.
Returns
Result code.
Return values
k_ra8_okPipe parked at PID=NAK.
k_ra8_err_invalid_argArgument out of range.
Precondition
Speed maps to a real controller.
Pipe 1..9.
Postcondition
PIPECTR PID == NAK for pipe_num.
The host's subsequent OUT tokens on this pipe are NAKed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 441 of file ra8_usb_xfer.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pid_nak, k_ra8_usb_max_pipe_num, priv_pick(), and priv_pipe_pid().

Referenced by internal_endpoint_arm_out_pid(), internal_irq_drain_orphan_out(), and internal_irq_finish_out().

◆ ra8_usb_queue_in()

ra8_err_t ra8_usb_queue_in ( ra8_usb_speed_t speed,
uint8_t pipe_num,
const uint8_t * data,
uint16_t len )
nodiscard

Queue an IN transfer (device -> host) on pipe_num.

Selects pipe_num on CFIFOSEL, waits for FRDY, writes data[0..len-1] 16-bit-aligned, asserts BVAL, and switches the pipe PID to BUF so the controller hands the buffer to the SIE on the next IN token. Short / zero-length packets are handled naturally because BVAL is asserted regardless of length.

Parameters
[in]speedWhich controller.
[in]pipe_numPIPE number 1..9.
[in]dataBuffer to transmit (NULL allowed iff len == 0).
[in]lenTransmit byte count, 0..max_packet of the pipe.
Returns
ra8_err_t error code.
Return values
k_ra8_okTransfer queued.
k_ra8_err_invalid_argPipe / len / data combination invalid.
k_ra8_err_hw_timeoutFRDY never asserted.
Precondition
Pipe previously configured via ra8_usb_configure_endpoint(..., dir = IN, ...).
Postcondition
Pipe PID set to BUF.
BVAL asserted on the FIFO port.
Note
Not thread-safe.
Since
0.1.0

Queue an IN transfer (device -> host) on pipe_num.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]pipe_numSee implementation.
[in]dataSee implementation.
[in]lenSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 59 of file ra8_usb_xfer.c.

References r_usb_regs_t::CFIFOCTR, k_ra8_err_invalid_arg, k_ra8_fifoctr_bval, k_ra8_ok, k_ra8_pid_buf, k_ra8_usb_max_pipe_num, k_ra8_usb_pipe_max_packet, priv_fifo_write(), priv_pick(), priv_pipe_pid(), priv_select_cfifo(), priv_wait_frdy(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_bulk_xfer(), internal_control_xfer(), internal_irq_auto_echo(), internal_irq_complete_in(), internal_irq_stage_next_in(), internal_submit_in_pipe(), ra8_usb_cdc_send(), ra8_usb_haud_send_samples(), ra8_usb_hcdc_ecm_send_frame(), ra8_usb_hcdc_send(), ra8_usb_host_bulk_out(), ra8_usb_paud_send_frame(), ra8_usb_phid_send_report(), ra8_usb_pprn_send(), and ra8_usb_pvnd_send().

◆ ra8_usb_queue_out()

ra8_err_t ra8_usb_queue_out ( ra8_usb_speed_t speed,
uint8_t pipe_num,
uint8_t * out_buf,
uint16_t * inout_len,
bool rearm )
nodiscard

Drain an OUT transfer (host -> device) from pipe_num.

Counterpart to ra8_usb_queue_in. Selects pipe_num, waits for FRDY, and reads up to *inout_len bytes from the FIFO. When rearm is true the pipe PID is set back to BUF so the controller ACKs the next host OUT token; when false the PID is left untouched so the caller owns the arm/park decision – re-arming would re-open the pipe for a window in which a stray host OUT packet could land with no receiver and storm the ISR.

Parameters
[in]speedWhich controller.
[in]pipe_numPIPE number 1..9.
[out]out_bufReceive buffer.
[in,out]inout_lenOn entry: capacity. On exit: bytes read.
[in]rearmtrue re-arms PID=BUF after the drain; false leaves the PID untouched (caller arms or parks).
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes read.
k_ra8_err_no_dataBuffer was empty.
k_ra8_err_invalid_argPipe / pointers invalid.
k_ra8_err_hw_timeoutFRDY never asserted.
Precondition
Pipe previously configured for OUT.
out_buf, inout_len non-NULL, *inout_len > 0.
Postcondition
Pipe PID is BUF if rearm, otherwise left unchanged.
*inout_len reflects actual byte count delivered.
Note
Not thread-safe.
Since
0.1.0

Drain an OUT transfer (host -> device) from pipe_num.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]pipe_numSee implementation.
[in]out_bufSee implementation.
[in]inout_lenSee implementation.
[in]rearmSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 308 of file ra8_usb_xfer.c.

References r_usb_regs_t::BRDYSTS, r_usb_regs_t::CFIFOCTR, internal_check_queue_out_args(), k_ra8_err_invalid_arg, k_ra8_err_no_data, k_ra8_fifoctr_bclr, k_ra8_fifoctr_dtln, k_ra8_ok, k_ra8_pid_buf, priv_fifo_read(), priv_pick(), priv_pipe_pid(), priv_select_cfifo(), priv_wait_frdy(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_bulk_xfer(), internal_control_xfer(), internal_irq_auto_echo(), internal_irq_complete_out(), internal_irq_drain_orphan_out(), ra8_usb_cdc_recv(), ra8_usb_haud_recv_samples(), ra8_usb_hcdc_ecm_recv_frame(), ra8_usb_hcdc_recv(), ra8_usb_hhid_get_input_report(), ra8_usb_paud_recv_frame(), ra8_usb_phid_recv_report(), ra8_usb_pprn_recv(), and ra8_usb_pvnd_recv().

◆ ra8_usb_read_setup_if_valid()

ra8_err_t ra8_usb_read_setup_if_valid ( ra8_usb_speed_t speed,
ra8_usb_setup_t * out_setup )
nodiscard

Snapshot the current SETUP packet from the controller, gated on INTSTS0.VALID (FS / CTRT path).

Reads the four mirror registers USBREQ, USBVAL, USBINDX, USBLENG and clears INTSTS0.VALID. The function returns k_ra8_err_no_data when VALID == 0 so the FS / CTRT-driven path can poll the same routine without producing stale dispatches. Use ra8_usb_read_setup_unconditional on the HS / SQMON polled-worker path where the SIE may auto-clear VALID before the worker observes the SETUP edge.

Parameters
[in]speedWhich controller.
[out]out_setupDecoded 8-byte SETUP packet.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP captured.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_setup was NULL.
k_ra8_err_no_dataINTSTS0.VALID was clear.
Precondition
out_setup non-NULL.
Postcondition
INTSTS0.VALID cleared on success.
Note
Call from CTRT-handling path. HS dispatcher must use ra8_usb_read_setup_unconditional instead.
See also
ra8_usb_read_setup_unconditional
Since
0.1.0

Snapshot the current SETUP packet from the controller, gated on INTSTS0.VALID (FS / CTRT path).

VALID-gated SETUP drain. Returns k_ra8_err_no_data when INTSTS0.VALID is clear; otherwise drains USBREQ/USBVAL/ USBINDX/USBLENG and W0C-clears VALID.

Parameters
[in]speedSee header.
[in]out_setupSee header.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_no_dataINTSTS0.VALID was clear at entry.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_setup was NULL.
Precondition
Module state is consistent.
out_setup is non-NULL.
Postcondition
On success, INTSTS0.VALID is W0C-cleared.
On success, *out_setup mirrors the chip's SETUP latch.
Note
Not thread-safe; FS / CTRT path uses this variant.
Since
0.1.0

Definition at line 479 of file ra8_usb_xfer.c.

References ra8_usb_setup_t::b_request, ra8_usb_setup_t::bm_request_type, r_usb_regs_t::INTSTS0, k_ra8_err_invalid_arg, k_ra8_err_no_data, k_ra8_intsts0_mask_valid, k_ra8_ok, k_ra8_usb_byte_bits, k_ra8_usb_byte_mask, priv_pick(), RA8_CHECK_NULL_PTR, s_tag, r_usb_regs_t::USBINDX, r_usb_regs_t::USBLENG, r_usb_regs_t::USBREQ, r_usb_regs_t::USBVAL, ra8_usb_setup_t::w_index, ra8_usb_setup_t::w_length, and ra8_usb_setup_t::w_value.

Referenced by demo_poll_once().

◆ ra8_usb_read_setup_unconditional()

ra8_err_t ra8_usb_read_setup_unconditional ( ra8_usb_speed_t speed,
ra8_usb_setup_t * out_setup )
nodiscard

Snapshot the current SETUP packet from the controller without gating on INTSTS0.VALID (HS / SQMON polled-worker path).

On HS the polled SETUP worker observes DCPCTR.SQMON == 1 (HUM Ch 37.2.31 p 2095, race-immune SETUP-latched signal) AFTER the SIE has already auto-cleared INTSTS0.VALID. The captured SETUP latch registers USBREQ / USBVAL / USBINDX / USBLENG (HUM Ch 37.2.21..24 p 2087..2090) survive that auto-clear – only a fresh SETUP token can overwrite them. This entry point therefore skips the VALID gate and drains the captured registers directly, then defensively W0C-clears VALID (no-op if already 0).

Parameters
[in]speedWhich controller.
[out]out_setupDecoded 8-byte SETUP packet.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP drained from captured registers.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_setup was NULL.
Precondition
out_setup non-NULL.
Caller has independent proof a SETUP arrived (e.g. SQMON==1).
Postcondition
*out_setup mirrors USBREQ/USBVAL/USBINDX/USBLENG.
INTSTS0.VALID is W0C-cleared.
Note
Call from the HS / SQMON polled-dispatcher path.
See also
ra8_usb_read_setup_if_valid
Since
0.1.0

Snapshot the current SETUP packet from the controller without gating on INTSTS0.VALID (HS / SQMON polled-worker path).

Race-free SETUP drain for the HS / SQMON polled-worker path. On HS the polled dispatcher routinely observes DCPCTR.SQMON == 1 (race-immune SETUP-latched signal, HUM Ch 37.2.31 p 2095) AFTER the SIE has already auto-cleared INTSTS0.VALID. The captured registers USBREQ/USBVAL/USBINDX/ USBLENG remain latched (HUM Ch 37.2.21..24 p 2087..2090) – only the VALID flag is cleared. This entry point therefore skips the VALID gate and drains the captured registers directly, then defensively W0C-acks VALID in case the SIE re-asserted it before our store.

Parameters
[in]speedWhich controller.
[out]out_setupDecoded 8-byte SETUP packet.
Returns
Result code.
Return values
k_ra8_okSETUP drained from the captured registers.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrout_setup was NULL.
Precondition
Caller has independent proof a SETUP arrived (e.g. SQMON==1).
out_setup is non-NULL.
Postcondition
*out_setup mirrors USBREQ/USBVAL/USBINDX/USBLENG.
INTSTS0.VALID is W0C-cleared (no-op if already 0).
Note
Not thread-safe; HS / SQMON path uses this variant.
Since
0.1.0

Definition at line 529 of file ra8_usb_xfer.c.

References ra8_usb_setup_t::b_request, ra8_usb_setup_t::bm_request_type, r_usb_regs_t::INTSTS0, k_ra8_err_invalid_arg, k_ra8_intsts0_mask_valid, k_ra8_ok, k_ra8_usb_byte_bits, k_ra8_usb_byte_mask, priv_pick(), RA8_CHECK_NULL_PTR, s_tag, r_usb_regs_t::USBINDX, r_usb_regs_t::USBLENG, r_usb_regs_t::USBREQ, r_usb_regs_t::USBVAL, ra8_usb_setup_t::w_index, ra8_usb_setup_t::w_length, and ra8_usb_setup_t::w_value.

Referenced by internal_ctrt_dispatch_fresh_setup().

◆ ra8_usb_rearm_out_pipe()

ra8_err_t ra8_usb_rearm_out_pipe ( ra8_usb_speed_t speed,
uint8_t pipe_num )
nodiscard

Re-arm an OUT pipe that the controller has parked at PID=NAK.

The RA8D2 USB-FS / USB-HS pipe state machine auto-flips PID from BUF to NAK after every successful BUF cycle on a single-buffered pipe (HUM Ch 36 – single-buffered OUT pipes). ra8_usb_queue_out leaves the PID untouched after a drain, so the OUT pipe sits at NAK and the controller NAKs incoming transactions (NRDYSTS accumulates the NAK responses). This helper clears the per-pipe NRDYSTS bit (W0C) and unconditionally re-asserts PID=BUF so the pipe is ready to ACK the next host OUT token. Safe to call proactively from the polled-dispatch worker on every iteration for each OUT pipe that has a pending USBX transfer.

Parameters
[in]speedWhich controller (FS / HS).
[in]pipe_numPIPE1..PIPE9 (must not be 0; DCP uses DCPCTR).
Returns
ra8_err_t error code.
Return values
k_ra8_okPipe re-armed at PID=BUF, NRDYSTS bit acked.
k_ra8_err_invalid_argspeed invalid or pipe_num out of range.
Precondition
Pipe was previously configured via ra8_usb_configure_endpoint with dir = k_ra8_usb_ep_dir_out.
Caller serialises against ra8_usb_queue_out for the same pipe.
Postcondition
NRDYSTS bit pipe_num is cleared.
PIPECTR[pipe_num-1].PID == BUF.
Note
Not thread-safe; the polled-dispatch worker is the sole caller on hardware.
See also
ra8_usb_queue_out
ra8_usb_configure_endpoint
Since
0.1.0

Re-arm an OUT pipe that the controller has parked at PID=NAK.

See the public header for the documented contract; this definition implements it. The hardware-required sequence per HUM Ch 36.2.13 (NRDYSTS, W0C) and Ch 36.2.27 (PIPECTR.PID) is:

  1. Ack NRDYSTS bit pipe_num by writing 0 to that bit (W0C: write ~pipe_bit to clear only the target bit and preserve the rest).
  2. Force PID=BUF on the pipe so the controller ACKs the next OUT token from the host instead of NAK'ing it.
Parameters
[in]speedSee header.
[in]pipe_numSee header.
Returns
Result code.
Return values
k_ra8_okPipe re-armed.
k_ra8_err_invalid_argArgument out of range.
Precondition
Speed maps to a real controller.
Pipe 1..9.
Postcondition
NRDYSTS bit pipe_num cleared.
PIPECTR PID == BUF for pipe_num.
Note
Not thread-safe.
Since
0.1.0

Definition at line 398 of file ra8_usb_xfer.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pid_buf, k_ra8_usb_max_pipe_num, r_usb_regs_t::NRDYSTS, priv_pick(), and priv_pipe_pid().

Referenced by internal_endpoint_arm_out_pid(), internal_irq_auto_echo(), internal_irq_complete_out(), internal_irq_recover_in_nak(), internal_submit_consume_orphan(), and internal_submit_pipe().

◆ ra8_usb_set_address()

ra8_err_t ra8_usb_set_address ( ra8_usb_speed_t speed,
uint8_t address )
nodiscard

Program the device USB address into USBADDR.

Called by the chapter-9 stack after a successful SET_ADDRESS SETUP completion. The controller answers SET_ADDRESS automatically before the status stage; this helper only stores the address so the host's subsequent IN tokens land on the right device.

Parameters
[in]speedWhich controller.
[in]addressUSB address (0..127).
Returns
ra8_err_t error code.
Return values
k_ra8_okAddress written.
k_ra8_err_invalid_argspeed out of range or address > 127.
Precondition
Bus is in default state (post reset, pre SET_ADDRESS).
Postcondition
USBADDR.USBADDR[6:0] == address.
Note
Not thread-safe.
Since
0.1.0

Program the device USB address into USBADDR.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]addressSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 418 of file ra8_usb_device.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_max_address, k_ra8_usbaddr_addr_mask, priv_pick(), and r_usb_regs_t::USBADDR.

Referenced by demo_dispatch_setup(), internal_do_set_address(), internal_do_set_address(), internal_do_set_address(), internal_do_set_address(), internal_do_set_address(), and internal_handle_standard().

◆ ra8_usb_stall_endpoint()

ra8_err_t ra8_usb_stall_endpoint ( ra8_usb_speed_t speed,
uint8_t pipe_num )
nodiscard

Stall a configured endpoint.

Parameters
[in]speedWhich controller.
[in]pipe_numPIPE number 0..9 (0 = DCP).
Returns
ra8_err_t error code.
Return values
k_ra8_okPID set to STALL.
k_ra8_err_invalid_argPipe out of range.
Precondition
ra8_usb_device_init ran for this speed.
Postcondition
Pipe responds STALL until the stack clears the halt.
Note
Not thread-safe.
Since
0.1.0

Stall a configured endpoint.

See the public header for the documented contract; this definition implements it.

Parameters
[in]speedSee implementation.
[in]pipe_numSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 716 of file ra8_usb_device.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pid_stall, k_ra8_usb_max_pipe_num, priv_dcp_pid(), priv_pick(), and priv_pipe_pid().

Referenced by internal_endpoint_stall().