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

USB device-mode data path: pipe queue, DCP control data, SETUP. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_usb.h"
#include "ra8_usb_internal.h"
#include "ra8_usb_regs.h"
Include dependency graph for ra8_usb_xfer.c:

Go to the source code of this file.

Functions

ra8_err_t ra8_usb_queue_in (ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
 Implementation of ra8_usb_queue_in().
static ra8_err_t internal_dcp_in_payload (volatile r_usb_regs_t *reg, const uint8_t *data, uint16_t len)
 Send the EP0 IN data-stage payload as one or more DCP chunks.
static ra8_err_t internal_dcp_in_zlp (volatile r_usb_regs_t *reg)
 Send a zero-length data stage on the DCP IN endpoint.
ra8_err_t ra8_usb_dcp_in_data (ra8_usb_speed_t speed, const uint8_t *data, uint16_t len)
 Implementation of ra8_usb_dcp_in_data().
static ra8_err_t internal_check_queue_out_args (uint8_t pipe_num, const uint8_t *out_buf, const uint16_t *inout_len)
 Argument validation helper for 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)
 Implementation of ra8_usb_queue_out().
ra8_err_t ra8_usb_rearm_out_pipe (ra8_usb_speed_t speed, uint8_t pipe_num)
 Implementation of ra8_usb_rearm_out_pipe().
ra8_err_t ra8_usb_park_out_pipe (ra8_usb_speed_t speed, uint8_t pipe_num)
 Implementation of ra8_usb_park_out_pipe().
ra8_err_t ra8_usb_read_setup_if_valid (ra8_usb_speed_t speed, ra8_usb_setup_t *out_setup)
 Implementation of ra8_usb_read_setup_if_valid().
ra8_err_t ra8_usb_read_setup_unconditional (ra8_usb_speed_t speed, ra8_usb_setup_t *out_setup)
 Implementation of ra8_usb_read_setup_unconditional (see header).
ra8_err_t ra8_usb_control_response (ra8_usb_speed_t speed, bool accept)
 Implementation of ra8_usb_control_response().

Variables

static const char * s_tag = "USB"
volatile uint32_t g_dcp_push_count = 0U
volatile uint16_t g_dcp_dcpctr_pre_push = 0U
volatile uint16_t g_dcp_dcpctr_post_push = 0U
volatile uint16_t g_dcp_cfifoctr_pre = 0U
volatile uint16_t g_dcp_cfifoctr_post = 0U
volatile uint16_t g_dcp_last_len = 0U
volatile uint8_t g_dcp_last_err = 0U

Detailed Description

USB device-mode data path: pipe queue, DCP control data, SETUP.

Tag
[Ring 3 / HAL] {World: NS}

Device-mode transfer entry points: ra8_usb_queue_in / ra8_usb_queue_out (pipe FIFO push / drain), the DCP control-IN data stage (ra8_usb_dcp_in_data and its chunk / ZLP helpers), the OUT pipe re-arm / park controls, the SETUP-packet drains (ra8_usb_read_setup_if_valid / ra8_usb_read_setup_unconditional), and ra8_usb_control_response. Split out of ra8_usb.c so every translation unit stays under the 1000-line cap; the shared register and FIFO helpers it calls live in ra8_usb.c (declared in ra8_usb_internal.h). Modelled on FSP r_usb_preg_abs.c / r_usb_plibusbip.c; no FSP source ships in this tree.

Since
0.1.0

Definition in file ra8_usb_xfer.c.

Function Documentation

◆ internal_check_queue_out_args()

ra8_err_t internal_check_queue_out_args ( uint8_t pipe_num,
const uint8_t * out_buf,
const uint16_t * inout_len )
static

Argument validation helper for ra8_usb_queue_out.

Read-only over the buffers; the caller mutates them on success. Marked const so clang-tidy's readability-non-const-parameter is satisfied.

Parameters
[in]pipe_numSee implementation.
[in]out_bufSee implementation.
[in]inout_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 277 of file ra8_usb_xfer.c.

References k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_usb_max_pipe_num, and k_ra8_usb_pipe_max_packet.

Referenced by ra8_usb_queue_out().

◆ internal_dcp_in_payload()

ra8_err_t internal_dcp_in_payload ( volatile r_usb_regs_t * reg,
const uint8_t * data,
uint16_t len )
static

Send the EP0 IN data-stage payload as one or more DCP chunks.

Drives the multi-chunk loop so ra8_usb_dcp_in_data stays under the clang-tidy statement-count threshold. Pushes at most DCPMAXP bytes per iteration via priv_dcp_push_chunk, then raises DCPCTR.PID to BUF after the first successful push. The controller services subsequent IN tokens automatically.

Parameters
[in,out]regSelected DCP register block (CFIFO already pointed at DCP / IN direction by the caller).
[in]dataSource payload; must hold at least len bytes.
[in]lenTotal payload length in bytes; must be > 0.
Returns
ra8_err_t Error code.
Return values
k_ra8_okPayload fully queued; PID set to BUF.
k_ra8_err_hw_timeoutFRDY never asserted for some chunk.
Precondition
reg is non-NULL and CFIFOSEL is already programmed for DCP IN.
data is non-NULL and len > 0.
Postcondition
On success, all 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 124 of file ra8_usb_xfer.c.

References k_ra8_ok, k_ra8_pid_buf, k_ra8_usb_dcp_max_packet, priv_dcp_pid(), priv_dcp_push_chunk(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by ra8_usb_dcp_in_data().

◆ internal_dcp_in_zlp()

ra8_err_t internal_dcp_in_zlp ( volatile r_usb_regs_t * reg)
static

Send a zero-length data stage on the DCP IN endpoint.

Waits for FRDY, pulses CFIFOCTR.BVAL on an empty buffer (producing a ZLP on the wire) and raises DCPCTR.PID to BUF. Extracted from ra8_usb_dcp_in_data so the top-level function fits under the clang-tidy statement-count threshold.

Parameters
[in,out]regSelected DCP register block (CFIFO already pointed at DCP / IN direction by the caller).
Returns
ra8_err_t Error code.
Return values
k_ra8_okZLP queued; PID set to BUF.
k_ra8_err_hw_timeoutFRDY never asserted.
Precondition
reg is non-NULL and CFIFOSEL is already programmed for DCP IN.
USB module clock and power are on.
Postcondition
On success, an empty buffer is 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 169 of file ra8_usb_xfer.c.

References r_usb_regs_t::CFIFOCTR, k_ra8_fifoctr_bval, k_ra8_ok, k_ra8_pid_buf, priv_dcp_pid(), priv_wait_frdy(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by ra8_usb_dcp_in_data().

◆ ra8_usb_control_response()

ra8_err_t ra8_usb_control_response ( ra8_usb_speed_t speed,
bool accept )
nodiscard

Implementation of ra8_usb_control_response().

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

Implementation of ra8_usb_dcp_in_data().

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

ra8_err_t ra8_usb_park_out_pipe ( ra8_usb_speed_t speed,
uint8_t pipe_num )
nodiscard

Implementation of ra8_usb_park_out_pipe().

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

Implementation of ra8_usb_queue_in().

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

Implementation of ra8_usb_queue_out().

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

Implementation of ra8_usb_read_setup_if_valid().

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

Implementation of ra8_usb_read_setup_unconditional (see header).

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

Implementation of ra8_usb_rearm_out_pipe().

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

Variable Documentation

◆ g_dcp_cfifoctr_post

volatile uint16_t g_dcp_cfifoctr_post = 0U

Definition at line 185 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_cfifoctr_pre

volatile uint16_t g_dcp_cfifoctr_pre = 0U

Definition at line 184 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_dcpctr_post_push

volatile uint16_t g_dcp_dcpctr_post_push = 0U

Definition at line 183 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_dcpctr_pre_push

volatile uint16_t g_dcp_dcpctr_pre_push = 0U

Definition at line 182 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_last_err

volatile uint8_t g_dcp_last_err = 0U

Definition at line 187 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_last_len

volatile uint16_t g_dcp_last_len = 0U

Definition at line 186 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ g_dcp_push_count

volatile uint32_t g_dcp_push_count = 0U

Definition at line 181 of file ra8_usb_xfer.c.

Referenced by ra8_usb_dcp_in_data().

◆ s_tag

const char* s_tag = "USB"
static

Definition at line 35 of file ra8_usb_xfer.c.