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

Cross-TU surface for the ra8_usb driver split. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_err.h"
#include "ra8_mstp.h"
#include "ra8_usb.h"
#include "ra8_usb_regs.h"
Include dependency graph for ra8_usb_internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ra8_usb_internal_lim_t : uint16_t {
  k_ra8_usb_max_pipe_num = 9U ,
  k_ra8_usb_max_ep_addr = 15U ,
  k_ra8_usb_max_address = 127U ,
  k_ra8_usb_dcp_max_packet = 64U ,
  k_ra8_usb_pipe_max_packet = 1024U
}
 Driver-wide bounds that aren't part of the public API. More...
enum  ra8_usb_byte_mask_t : uint16_t {
  k_ra8_usb_byte_mask = 0x00FFU ,
  k_ra8_usb_byte_bits = 8U
}
 Byte-extraction masks shared across the FIFO byte path. More...
enum  ra8_usb_host_ctrl_bits_t : uint16_t {
  k_ra8_usb_dcp_pipe0_bit = 0x0001U ,
  k_ra8_usb_setup_dir_in = 0x0080U ,
  k_ra8_usb_dcpmaxp_mxps = 0x007FU ,
  k_ra8_usb_rhst_mask = 0x0007U ,
  k_ra8_usb_lnst_mask = 0x0003U
}
 Bit masks used by the host control-transfer engine. More...
enum  ra8_usb_host_devadd_t : uint32_t {
  k_ra8_usb_devadd0_off = 0x00D0U ,
  k_ra8_usb_usbspd_shift = 6U ,
  k_ra8_usb_devadd_stride = 2U ,
  k_ra8_usb_dev_addr_max = 10U
}
 Offsets / shifts for the device-address (DEVADDn) registers. More...
enum  ra8_usb_host_addr_bits_t : uint16_t {
  k_ra8_usb_devsel_shift = 12U ,
  k_ra8_usb_devsel_field_mask = 0x000FU ,
  k_ra8_usb_pipemaxp_mxps = 0x07FFU ,
  k_ra8_usb_pid_stall_bit = 0x0002U
}
 Field layout helpers for host-mode device addressing. More...

Functions

volatile r_usb_regs_tpriv_pick (ra8_usb_speed_t speed)
 Resolve the per-speed register pointer.
ra8_mstp_t priv_mstp (ra8_usb_speed_t speed)
 Resolve the per-speed MSTP id.
void priv_rmw16 (volatile uint16_t *reg, uint16_t set_mask, uint16_t clr_mask)
 Apply a generic read-modify-write to a 16-bit register.
bool priv_is_hs (volatile const r_usb_regs_t *reg)
 Detect whether reg points at the USBHS (IP1) register block.
void priv_select_cfifo (volatile r_usb_regs_t *reg, uint16_t pipe_num, bool is_in_dir)
 Set CFIFOSEL.MBW + CURPIPE + ISEL for the given pipe / direction.
ra8_err_t priv_wait_frdy (volatile r_usb_regs_t *reg)
 Spin until CFIFOCTR.FRDY asserts or a deadline elapses.
void priv_dcp_pid (volatile r_usb_regs_t *reg, ra8_usb_pid_t pid)
 Set DCPCTR PID field while preserving the rest of the register.
void priv_pipe_pid (volatile r_usb_regs_t *reg, uint8_t pipe_num, ra8_usb_pid_t pid)
 Set PIPECTR[idx] PID field.
void priv_fifo_write (volatile r_usb_regs_t *reg, const uint8_t *data, uint16_t len)
 Push a byte buffer into the CFIFO data port.
void priv_fifo_read (volatile r_usb_regs_t *reg, uint8_t *data, uint16_t len)
 Drain the CFIFO data port into a buffer.
ra8_err_t priv_dcp_push_chunk (volatile r_usb_regs_t *reg, const uint8_t *p, uint16_t n)
 Push a single DCP IN chunk: wait FRDY, write FIFO, pulse BVAL.
uint16_t priv_pipebuf_word (uint8_t pipe_num, uint16_t max_packet)
 Compute the PIPEBUF word for a bulk pipe (2*MPS region).
uint16_t priv_pipecfg_word (uint8_t ep_addr, ra8_usb_ep_dir_t dir, ra8_usb_ep_type_t type, bool dblb_in)
 Pack PIPECFG fields for a configured non-control pipe.
void priv_pipe_quiesce (volatile r_usb_regs_t *reg, uint8_t pipe_num)
 Quiesce the pipe so PIPECFG/PIPEMAXP/PIPEPERI become writable.
ra8_err_t priv_usbhs_phy_bringup (volatile r_usb_regs_t *reg)
 USBHS embedded-PHY bring-up (HUM Figure 37.2 p 2121).
void priv_usb_init_common (volatile r_usb_regs_t *reg)
 Programme the post-SYSCFG common registers (FIFO, DCP, INTENB).
ra8_err_t priv_usbfs_module_bringup (volatile r_usb_regs_t *reg)
 USBFS module bring-up (FSP hw_usb_pmodule_init IP0 branch).
void priv_host_program_devadd (volatile r_usb_regs_t *reg, uint8_t dev_addr)
 Program DEVADDn.USBSPD with the connected device's link speed.

Detailed Description

Cross-TU surface for the ra8_usb driver split.

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

Not part of the public API. The native USB controller driver (HUM Ch 36 USBFS, Ch 37 USBHS) was partitioned across several translation units so every file stays under the 1000-line cap:

  • ra8_usb.c – shared low-level register helpers (the symbols promoted below) plus the CFIFO byte-mover.
  • ra8_usb_phy.c – USBHS embedded-PHY bring-up sequence.
  • ra8_usb_device.c – device-mode lifecycle, status and the endpoint/pipe configuration entry points.
  • ra8_usb_xfer.c – device-mode data path (queue IN/OUT, DCP control data, SETUP drain, control resp).
  • ra8_usb_irq.c – IRQ dispatch / callbacks / power + host-mode bring-up.
  • ra8_usb_host_ctrl.c – host-mode control-transfer engine.
  • ra8_usb_host_bulk.c – host-mode bulk-transfer engine.

This header declares every symbol referenced by more than one of those TUs: the shared bound enums, the byte-mask helpers, the host addressing-field enums, and the promoted register helpers (which were TU-private statics before the split). Production code keeps calling the public ra8_usb_* API in ra8_usb.h; the symbols here are an implementation detail of the driver split only. See CLAUDE.md "Test access to internal symbols (MC/DC scope)".

Since
0.1.0

Definition in file ra8_usb_internal.h.

Enumeration Type Documentation

◆ ra8_usb_byte_mask_t

enum ra8_usb_byte_mask_t : uint16_t

Byte-extraction masks shared across the FIFO byte path.

Enumerator
k_ra8_usb_byte_mask 

Low byte of a 16-bit FIFO word.

k_ra8_usb_byte_bits 

Bits per byte (shift constant).

Definition at line 70 of file ra8_usb_internal.h.

◆ ra8_usb_host_addr_bits_t

enum ra8_usb_host_addr_bits_t : uint16_t

Field layout helpers for host-mode device addressing.

Enumerator
k_ra8_usb_devsel_shift 

DCPMAXP/PIPEMAXP DEVSEL pos.

k_ra8_usb_devsel_field_mask 

DEVSEL width once shifted.

k_ra8_usb_pipemaxp_mxps 

PIPEMAXP MXPS field (the USBHS instance carries 11 bits, HUM Ch 37.2.36; FS uses the low 9).

k_ra8_usb_pid_stall_bit 

PID[1]: set for either STALL.

Definition at line 93 of file ra8_usb_internal.h.

◆ ra8_usb_host_ctrl_bits_t

enum ra8_usb_host_ctrl_bits_t : uint16_t

Bit masks used by the host control-transfer engine.

Enumerator
k_ra8_usb_dcp_pipe0_bit 

BRDYSTS/BEMPSTS DCP (pipe 0) bit.

k_ra8_usb_setup_dir_in 

bmRequestType device-to-host bit.

k_ra8_usb_dcpmaxp_mxps 

DCPMAXP MXPS (max packet) field.

k_ra8_usb_rhst_mask 

DVSTCTR0.RHST connected-speed.

k_ra8_usb_lnst_mask 

SYSSTS0.LNST line-state field.

Definition at line 76 of file ra8_usb_internal.h.

◆ ra8_usb_host_devadd_t

enum ra8_usb_host_devadd_t : uint32_t

Offsets / shifts for the device-address (DEVADDn) registers.

Enumerator
k_ra8_usb_devadd0_off 

DEVADD0 byte offset from base.

k_ra8_usb_usbspd_shift 

DEVADDn.USBSPD field position.

k_ra8_usb_devadd_stride 

Bytes between DEVADDn slots.

k_ra8_usb_dev_addr_max 

Highest DEVADDn slot (DEVADDA).

Definition at line 85 of file ra8_usb_internal.h.

◆ ra8_usb_internal_lim_t

enum ra8_usb_internal_lim_t : uint16_t

Driver-wide bounds that aren't part of the public API.

Enumerator
k_ra8_usb_max_pipe_num 

PIPE1..PIPE9 + DCP at 0.

k_ra8_usb_max_ep_addr 

USB EP number is 4 bits.

k_ra8_usb_max_address 

7-bit USB address.

k_ra8_usb_dcp_max_packet 

EP0 default packet size.

k_ra8_usb_pipe_max_packet 

Max packet ceiling for pipes.

Definition at line 58 of file ra8_usb_internal.h.

Function Documentation

◆ priv_dcp_pid()

void priv_dcp_pid ( volatile r_usb_regs_t * reg,
ra8_usb_pid_t pid )

Set DCPCTR PID field while preserving the rest of the register.

Promoted from a TU-private static so the device, control, and host engines drive the DCP PID through one accessor.

Parameters
[in,out]regDCP register block.
[in]pidPID encoding to write (NAK / BUF / STALL).
Precondition
Module state is consistent.
reg is non-null and points at a powered controller.
Postcondition
DCPCTR.PID == pid; the other DCPCTR fields are unchanged.
No other register is touched.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Set DCPCTR PID field while preserving the rest of the register.

See implementation.

Parameters
[in]regSee implementation.
[in]pidSee 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 288 of file ra8_usb.c.

References r_usb_regs_t::DCPCTR, k_ra8_pid_mask, and priv_rmw16().

Referenced by internal_dcp_in_payload(), internal_dcp_in_zlp(), internal_host_ctrl_data_arm(), internal_host_ctrl_data_in(), internal_host_ctrl_data_out(), internal_host_ctrl_setup(), internal_host_ctrl_status(), internal_host_dcp_in_wait(), ra8_usb_control_response(), ra8_usb_dcp_out_arm(), ra8_usb_dcp_out_read(), and ra8_usb_stall_endpoint().

◆ priv_dcp_push_chunk()

ra8_err_t priv_dcp_push_chunk ( volatile r_usb_regs_t * reg,
const uint8_t * p,
uint16_t n )

Push a single DCP IN chunk: wait FRDY, write FIFO, pulse BVAL.

Promoted from a TU-private static so both the device DCP-IN data path and the host control-write data path share one chunk push.

Parameters
[in,out]regDCP register block (chip or host shim).
[in]pSource byte pointer; must hold at least n bytes.
[in]nChunk size in bytes; must be > 0 and <= the DCP MPS.
Returns
ra8_err_t Error code.
Return values
k_ra8_okChunk queued; BVAL pulsed.
k_ra8_err_hw_timeoutFRDY never asserted within the bound.
Precondition
reg was returned by priv_pick() and is non-NULL.
CFIFO is already selected on DCP (CURPIPE=0) in IN direction.
Postcondition
On success, the controller buffer holds the new chunk and BVAL pulsed.
On error, no PID transition has been performed.
Note
Not thread-safe; the caller holds the DCP lock.
Since
0.1.0

Push a single DCP IN chunk: wait FRDY, write FIFO, pulse BVAL.

Bounded helper extracted from ra8_usb_dcp_in_data so the top-level function stays under the clang-tidy readability-function-size threshold. Performs exactly one controller-buffer transfer cycle.

Parameters
[in,out]regDCP register block (chip or host shim).
[in]pSource byte pointer; must hold at least n bytes.
[in]nChunk size in bytes; must be > 0 and <= the DCP MPS.
Returns
ra8_err_t Error code.
Return values
k_ra8_okChunk queued; BVAL pulsed.
k_ra8_err_timeoutFRDY never asserted within the bound.
Precondition
reg was returned by priv_pick() and is non-NULL.
CFIFO is already selected on DCP (CURPIPE=0) in IN direction.
Postcondition
On success, the controller buffer holds the new chunk and BVAL has been pulsed.
On error, no PID transition has been performed.
Note
Not thread-safe; the parent function holds the DCP lock.
Since
0.1.0

Definition at line 770 of file ra8_usb.c.

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

Referenced by internal_dcp_in_payload(), and internal_host_ctrl_data_out().

◆ priv_fifo_read()

void priv_fifo_read ( volatile r_usb_regs_t * reg,
uint8_t * data,
uint16_t len )

Drain the CFIFO data port into a buffer.

Promoted from a TU-private static. Dispatches to the speed-appropriate access width (USBHS 32-bit, USBFS 16-bit).

Parameters
[in]regUSB instance register block.
[out]dataDestination byte pointer (may be NULL when len == 0).
[in]lenNumber of bytes to drain.
Precondition
Caller selected DCP / pipe with priv_select_cfifo and FRDY=1.
data != NULL when len > 0.
Postcondition
DTLN advanced by len bytes.
data[0..len-1] holds the received payload bytes.
Note
Not thread-safe.
Since
0.1.0

Dispatches to the speed-appropriate access width: USBHS requires 32-bit reads (MBW=32) – a 16-bit read does not advance the FIFO read pointer (HUM Ch 37.2.7 p 2070, FSP hw_usb_read_fifo32). USBFS keeps MBW=16. Mirrors FSP usb_pstd_read_fifo for IP1/IP0.

Parameters
[in]regUSB instance register block.
[out]dataDestination byte pointer (may be NULL when len == 0).
[in]lenNumber of bytes to drain.
Precondition
Caller selected DCP / pipe with priv_select_cfifo and FRDY=1.
data != NULL when len > 0.
Postcondition
DTLN advanced by len bytes.
data[0..len-1] holds the received payload bytes.
Note
Not thread-safe.
Since
0.1.0

Definition at line 712 of file ra8_usb.c.

References r_usb_regs_t::CFIFO, r_usb_regs_t::CFIFOSEL, internal_fifo_read_hs_head(), internal_fifo_read_hs_tail(), k_ra8_fifosel_mbw_8, k_ra8_fifosel_mbw_msk, k_ra8_usb_byte_bits, k_ra8_usb_byte_mask, and priv_is_hs().

Referenced by internal_host_bulk_rx_packet(), internal_host_ctrl_data_in(), ra8_usb_dcp_out_read(), and ra8_usb_queue_out().

◆ priv_fifo_write()

void priv_fifo_write ( volatile r_usb_regs_t * reg,
const uint8_t * data,
uint16_t len )

Push a byte buffer into the CFIFO data port.

Promoted from a TU-private static. Dispatches to the speed-appropriate access width (USBHS 32-bit, USBFS 16-bit).

Parameters
[in]regUSB instance register block.
[in]dataSource byte pointer (may be NULL when len == 0).
[in]lenNumber of bytes to push.
Precondition
Caller selected DCP / pipe with priv_select_cfifo and FRDY=1.
data != NULL when len > 0.
Postcondition
DTLN advanced by len bytes.
FIFO ready for caller's BVAL commit.
Note
Not thread-safe.
Since
0.1.0

Dispatches to the speed-appropriate access width: USBHS uses 32-bit writes (with FSP-style 16/8 narrowing for the trailing 0..3 bytes), USBFS uses 16-bit writes with a single-byte tail. Mirrors FSP usb_pstd_write_fifo for IP1 / IP0 respectively.

Parameters
[in]regUSB instance register block.
[in]dataSource byte pointer (may be NULL when len == 0).
[in]lenNumber of bytes to push.
Precondition
Caller selected DCP / pipe with priv_select_cfifo and observed FRDY=1.
data != NULL when len > 0.
Postcondition
DTLN advanced by len bytes.
FIFO ready for caller's BVAL commit.
Note
Not thread-safe.
Since
0.1.0

Definition at line 592 of file ra8_usb.c.

References r_usb_regs_t::CFIFO, r_usb_regs_t::CFIFOSEL, internal_fifo_write_hs_head(), internal_fifo_write_hs_tail(), k_ra8_fifosel_mbw_8, k_ra8_fifosel_mbw_msk, k_ra8_usb_byte_bits, and priv_is_hs().

Referenced by priv_dcp_push_chunk(), and ra8_usb_queue_in().

◆ priv_host_program_devadd()

void priv_host_program_devadd ( volatile r_usb_regs_t * reg,
uint8_t dev_addr )

Program DEVADDn.USBSPD with the connected device's link speed.

Promoted from a TU-private static so the host control engine (ra8_usb_host_ctrl.c) and the host bulk engine (ra8_usb_host_bulk.c) share one DEVADDn programmer. The DEVADDn registers sit past the modelled register window, so this addresses the slot by raw offset (0xD0 + 2n) and copies DVSTCTR0.RHST into USBSPD[7:6].

Parameters
[in]regSelected controller register block (its base address).
[in]dev_addrAddress slot to program (0..k_ra8_usb_dev_addr_max).
Precondition
The bus reset has completed so RHST reflects the device speed.
reg is non-NULL and dev_addr is within the DEVADD range.
Postcondition
DEVADDn.USBSPD matches the connected speed; the address is usable.
No other DEVADDn field is changed.
Note
Single-device bring-up: no hub fields (UPPHUB/HUBPORT) are set.
Since
0.1.0

The RA host SIE will not run transactions to a device address until that address's DEVADDn slot carries the link speed. The DEVADDn registers sit past the modelled register window, so this addresses the slot by raw offset (0xD0 + 2n) and copies DVSTCTR0.RHST (01=LS, 10=FS, 11=HS) into USBSPD[7:6].

Parameters
[in]regSelected controller register block (its base address).
[in]dev_addrAddress slot to program (0..k_ra8_usb_dev_addr_max).
Precondition
The bus reset has completed so RHST reflects the device speed.
reg is non-NULL and dev_addr is within the DEVADD range.
Postcondition
DEVADDn.USBSPD matches the connected speed; the address is usable.
No other DEVADDn field is changed (the rest are reserved/zero).
Note
Single-device bring-up: no hub fields (UPPHUB/HUBPORT) are set.
Since
0.1.0

Definition at line 91 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::DVSTCTR0, k_ra8_usb_devadd0_off, k_ra8_usb_devadd_stride, k_ra8_usb_rhst_mask, and k_ra8_usb_usbspd_shift.

Referenced by internal_host_ctrl_setup(), and ra8_usb_host_set_target().

◆ priv_is_hs()

bool priv_is_hs ( volatile const r_usb_regs_t * reg)

Detect whether reg points at the USBHS (IP1) register block.

Promoted from a TU-private static so the FIFO byte-mover, the host control engine, and the bulk engine share one IP predicate.

Parameters
[in]regUSB instance register block pointer.
Returns
true if reg is the HS instance, false for FS.
Return values
trueUSBHS (IP1) – caller should use MBW=32 + 32-bit FIFO.
falseUSBFS (IP0) – caller should use MBW=16 + 16-bit FIFO.
Precondition
reg is a pointer returned by ra8_usb_fs() or ra8_usb_hs().
USB module pointers are populated.
Postcondition
No state mutated.
Returned value reflects controller identity.
Note
Pure function.
Since
0.1.0

FSP gates USB1_CFIFO_MBW = USB_MBW_32 on the same predicate (p_utr->ip == USB_CFG_IP1), and the FIFO write helpers below mirror that to keep CFIFOSEL.MBW and the CFIFO write width in agreement on each controller.

Parameters
[in]regUSB instance register block pointer.
Returns
true if reg is the HS instance, false for FS.
Return values
trueUSBHS (IP1) – caller should use MBW=32 + 32-bit FIFO.
falseUSBFS (IP0) – caller should use MBW=16 + 16-bit FIFO.
Precondition
reg is a pointer returned by ra8_usb_fs() or ra8_usb_hs().
USB module pointers are populated.
Postcondition
No state mutated.
Returned value reflects controller identity.
Note
Pure function.
Since
0.1.0

Definition at line 179 of file ra8_usb.c.

References ra8_usb_hs().

Referenced by internal_host_ctrl_setup(), priv_fifo_read(), priv_fifo_write(), and priv_select_cfifo().

◆ priv_mstp()

ra8_mstp_t priv_mstp ( ra8_usb_speed_t speed)

Resolve the per-speed MSTP id.

Promoted from a TU-private static so the lifecycle and power TUs share one speed-to-MSTP mapping.

Parameters
[in]speedController selector (FS / HS).
Returns
Module-stop id for the selected controller.
Return values
k_ra8_mstp_usbhsspeed == k_ra8_usb_speed_hs.
k_ra8_mstp_usbfsAny other speed value.
Precondition
Module state is consistent.
speed is a ra8_usb_speed_t value.
Postcondition
No state mutated; the helper is pure.
Returned id matches the requested controller.
Note
Pure / thread-safe.
Since
0.1.0

See implementation.

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 135 of file ra8_usb.c.

References k_ra8_mstp_usbfs, k_ra8_mstp_usbhs, and k_ra8_usb_speed_hs.

Referenced by ra8_usb_device_deinit(), ra8_usb_device_init(), ra8_usb_enter_stop(), ra8_usb_exit_stop(), ra8_usb_host_deinit(), and ra8_usb_host_init().

◆ priv_pick()

volatile r_usb_regs_t * priv_pick ( ra8_usb_speed_t speed)

Resolve the per-speed register pointer.

Promoted from a TU-private static so every TU in the driver split can map a ra8_usb_speed_t to its controller register block.

Parameters
[in]speedController selector (FS / HS).
Returns
The selected register block, or nullptr for an unknown speed.
Return values
nullptrspeed is neither FS nor HS.
Precondition
USB module pointers are populated.
speed is a ra8_usb_speed_t value.
Postcondition
No state mutated; the helper is pure.
Returned pointer identifies the requested controller.
Note
Pure / thread-safe.
Since
0.1.0

Definition at line 110 of file ra8_usb.c.

References k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_usb_fs(), and ra8_usb_hs().

Referenced by ra8_usb_clear_status(), ra8_usb_configure_endpoint(), ra8_usb_control_response(), ra8_usb_dcp_in_data(), ra8_usb_dcp_out_arm(), ra8_usb_dcp_out_read(), ra8_usb_device_attach(), ra8_usb_device_busreset_rearm(), ra8_usb_device_deinit(), ra8_usb_device_init(), ra8_usb_dispatch(), ra8_usb_get_device_state(), ra8_usb_get_status(), ra8_usb_host_bulk_in(), ra8_usb_host_bulk_out(), ra8_usb_host_bus_reset(), ra8_usb_host_control_xfer(), ra8_usb_host_deinit(), ra8_usb_host_init(), ra8_usb_host_line_state(), ra8_usb_host_pipe_setup(), ra8_usb_host_set_target(), ra8_usb_host_set_uact(), ra8_usb_host_setup_request(), ra8_usb_intsts0_snapshot(), ra8_usb_park_out_pipe(), ra8_usb_queue_in(), ra8_usb_queue_out(), ra8_usb_read_setup_if_valid(), ra8_usb_read_setup_unconditional(), ra8_usb_rearm_out_pipe(), ra8_usb_set_address(), and ra8_usb_stall_endpoint().

◆ priv_pipe_pid()

void priv_pipe_pid ( volatile r_usb_regs_t * reg,
uint8_t pipe_num,
ra8_usb_pid_t pid )

Set PIPECTR[idx] PID field.

Promoted from a TU-private static so the pipe-config, device-data, and host engines share one pipe PID accessor.

Parameters
[in,out]regController register block.
[in]pipe_numPipe index 1..9.
[in]pidPID encoding to write (NAK / BUF / STALL).
Precondition
Module state is consistent.
pipe_num in [1,9].
Postcondition
PIPECTR[pipe_num-1].PID == pid.
No other register is touched.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

See implementation.

Parameters
[in]regSee implementation.
[in]pipe_numSee implementation.
[in]pidSee 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 308 of file ra8_usb.c.

References k_ra8_pid_mask, r_usb_regs_t::PIPECTR, and priv_rmw16().

Referenced by internal_pipe_finalize(), priv_pipe_quiesce(), ra8_usb_host_bulk_in(), ra8_usb_host_bulk_out(), ra8_usb_park_out_pipe(), ra8_usb_queue_in(), ra8_usb_queue_out(), ra8_usb_rearm_out_pipe(), and ra8_usb_stall_endpoint().

◆ priv_pipe_quiesce()

void priv_pipe_quiesce ( volatile r_usb_regs_t * reg,
uint8_t pipe_num )

Quiesce the pipe so PIPECFG/PIPEMAXP/PIPEPERI become writable.

Promoted from a TU-private static so both the device-side and host-side pipe configurators park a pipe at PID=NAK before re-programming.

Parameters
[in,out]regController register window.
[in]pipe_numPipe index 1..9.
Precondition
reg is non-null and points at a powered controller.
pipe_num in [1,9].
Postcondition
BRDY/NRDY/BEMPENB bit for pipe_num is cleared.
PIPECTR PID for pipe_num == NAK.
Note
Not thread-safe.
Since
0.1.0

Clears BRDYENB/NRDYENB/BEMPENB for this pipe and forces PID=NAK (HUM Ch 36.2.24 NOTE 1, p 1996; mirrors STAR rx_usb_hw.c::internal_usb_quiesce_pipe).

Parameters
[in,out]regController register window.
[in]pipe_numPipe index 1..9.
Precondition
reg is non-null and points at a powered controller.
pipe_num in [1,9].
Postcondition
BRDY/NRDY/BEMPENB bit for pipe_num is cleared.
PIPECTR PID for pipe_num == NAK.
Note
Not thread-safe.
Since
0.1.0

Definition at line 447 of file ra8_usb.c.

References r_usb_regs_t::BEMPENB, r_usb_regs_t::BRDYENB, k_ra8_pid_nak, r_usb_regs_t::NRDYENB, and priv_pipe_pid().

Referenced by ra8_usb_configure_endpoint(), and ra8_usb_host_pipe_setup().

◆ priv_pipebuf_word()

uint16_t priv_pipebuf_word ( uint8_t pipe_num,
uint16_t max_packet )

Compute the PIPEBUF word for a bulk pipe (2*MPS region).

Promoted from a TU-private static so the device-side and host-side pipe configurators pack PIPEBUF the same way.

Parameters
[in]pipe_numPIPE number 1..9.
[in]max_packetPipe MPS (bytes).
Returns
PIPEBUF word ready to be written to register PIPEBUF.
Return values
0..0xFFFFPacked BUFNMB/BUFSIZE word (no error condition).
Precondition
pipe_num is in the 1..9 range (caller-checked).
max_packet is the pipe's MPS (caller validated <= 1024).
Postcondition
No global state is touched; the helper is pure.
Returned word satisfies HUM Ch 37.2.35 PIPEBUF layout.
Note
Pure / thread-safe.
Since
0.1.0

Statically partition the controller's internal FIFO RAM among the bulk pipes. Reserve blocks 0..7 (64-byte units) for the DCP (per FSP/Renesas examples), then pack user pipes in pipe-number order with 2*MPS per pipe – IN bulk pipes use both as a double-buffer (PIPECFG.DBLB set), OUT bulk pipes use only the first block (DBLB clear). Uniform 2*MPS keeps the BUFNMB arithmetic simple and wastes at most one block per OUT pipe.

BUFNMB = 8 + (pipe_num - 1) * (2 * mps_blocks) BUFSIZE = (2 * mps_blocks) - 1

HS MPS=512 -> 2*mps_blocks = 16, BUFSIZE = 15 FS MPS=64 -> 2*mps_blocks = 2, BUFSIZE = 1

Parameters
[in]pipe_numPIPE number 1..9.
[in]max_packetPipe MPS (bytes).
Returns
PIPEBUF word ready to be written to register PIPEBUF.
Return values
0..0xFFFFPacked BUFNMB/BUFSIZE word (no error condition; the helper is total over its enum-checked inputs).
Precondition
pipe_num is in the 1..9 range (caller-checked).
max_packet is the pipe's MPS (caller validated <= 1024).
Postcondition
No global state is touched; the helper is pure.
Returned word satisfies HUM Ch 37.2.35 PIPEBUF layout.
Note
Pure / thread-safe.
Since
0.1.0

Definition at line 353 of file ra8_usb.c.

References k_ra8_pipebuf_block_bytes, k_ra8_pipebuf_bufnmb_mask, and k_ra8_pipebuf_bufsize_shift.

Referenced by ra8_usb_configure_endpoint(), and ra8_usb_host_pipe_setup().

◆ priv_pipecfg_word()

uint16_t priv_pipecfg_word ( uint8_t ep_addr,
ra8_usb_ep_dir_t dir,
ra8_usb_ep_type_t type,
bool dblb_in )

Pack PIPECFG fields for a configured non-control pipe.

Promoted from a TU-private static so the device-side and host-side pipe configurators encode PIPECFG the same way.

Parameters
[in]ep_addrEndpoint address (low nibble = EP number).
[in]dirPipe direction (k_ra8_usb_ep_dir_in or _out).
[in]typePipe type (bulk / interrupt / iso).
[in]dblb_inDouble-bank bulk IN pipes (host mode true, device mode false; ignored for OUT / non-bulk).
Returns
PIPECFG word ready to write to PIPECFG.
Return values
0..0xFFFFPacked configuration word; no error condition.
Precondition
ep_addr low nibble is the EP number (caller validated 1..15).
dir / type are valid enum values.
Postcondition
No global state is touched; the helper is pure.
For bulk pipes SHTNAK is set; DBLB only when dblb_in is true with dir == IN.
Note
Pure / thread-safe.
Since
0.1.0

Encodes endpoint number, direction (DIR), pipe type (TYPE), and for bulk pipes the SHTNAK flag plus (optionally, IN only) the DBLB flag into the PIPECFG word. HUM Ch 36.2.24 PIPECFG. Bulk OUT is always single-buffered, otherwise the controller fills both banks with host data and the one-bank-per-call ra8_usb_queue_out drainer wedges the data phase (GitHub issue #6). Bulk IN double-banking is the caller's choice: HOST mode wants it so queue_in can push a data + ZLP pair back-to-back without the second push hitting a full-bank FRDY stall; DEVICE mode must run single-banked because the free-bank handshake after an MPS-exact fill is unreliable (staging the BOT CSW behind a 512-byte data phase on a 512-MPS HS pipe FRDY-times-out and the transport wedges, observed live vs macOS).

Parameters
[in]ep_addrEndpoint address (low nibble = EP number; bit 7 direction; the helper reads only the EP number).
[in]dirPipe direction (k_ra8_usb_ep_dir_in or _out).
[in]typePipe type (bulk / interrupt / iso).
[in]dblb_inDouble-bank bulk IN pipes (host mode true, device mode false; ignored for OUT / non-bulk).
Returns
PIPECFG word ready to write to PIPECFG.
Return values
0..0xFFFFPacked configuration word; no error condition.
Precondition
ep_addr low nibble is the EP number (caller validated 1..15).
dir / type are valid enum values.
Postcondition
No global state is touched; the helper is pure.
For bulk pipes SHTNAK is set; DBLB only when dblb_in is true with dir == IN (nested ifs, no compound decision).
Note
Pure / thread-safe.
Since
0.1.0

Definition at line 401 of file ra8_usb.c.

References k_ra8_pipecfg_dblb, k_ra8_pipecfg_dir_in, k_ra8_pipecfg_epnum_mask, k_ra8_pipecfg_shtnak, k_ra8_pipecfg_type_bulk, k_ra8_pipecfg_type_intr, k_ra8_pipecfg_type_iso, k_ra8_usb_ep_dir_in, k_ra8_usb_ep_dir_out, k_ra8_usb_ep_type_bulk, and k_ra8_usb_ep_type_intr.

Referenced by ra8_usb_configure_endpoint(), and ra8_usb_host_pipe_setup().

◆ priv_rmw16()

void priv_rmw16 ( volatile uint16_t * reg,
uint16_t set_mask,
uint16_t clr_mask )

Apply a generic read-modify-write to a 16-bit register.

Promoted from a TU-private static. Clears clr_mask then sets set_mask in one read / modify / store cycle.

Parameters
[in,out]regTarget register pointer; must not be nullptr.
[in]set_maskBits to set.
[in]clr_maskBits to clear (applied before the set).
Precondition
reg is non-null and points at a live register.
Caller serialises access to the register.
Postcondition
*reg reflects (old & ~clr_mask) | set_mask.
No other register is touched.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

See implementation.

Parameters
[in]regSee implementation.
[in]set_maskSee implementation.
[in]clr_maskSee 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 154 of file ra8_usb.c.

Referenced by internal_host_ctrl_data_arm(), internal_host_ctrl_data_out(), internal_host_ctrl_setup(), internal_host_ctrl_status(), internal_host_hs_bringup(), internal_host_setup_wait(), internal_pipe_finalize(), priv_dcp_pid(), priv_pipe_pid(), ra8_usb_control_response(), ra8_usb_dcp_out_arm(), ra8_usb_device_attach(), ra8_usb_host_bus_reset(), ra8_usb_host_init(), ra8_usb_host_pipe_setup(), ra8_usb_host_set_uact(), and ra8_usb_host_setup_request().

◆ priv_select_cfifo()

void priv_select_cfifo ( volatile r_usb_regs_t * reg,
uint16_t pipe_num,
bool is_in_dir )

Set CFIFOSEL.MBW + CURPIPE + ISEL for the given pipe / direction.

Promoted from a TU-private static. Picks MBW=32 for USBHS (FSP USB1_CFIFO_MBW) and MBW=16 for USBFS, then waits for the CURPIPE/ISEL readback to settle.

Parameters
[in]regUSB instance register block.
[in]pipe_numCURPIPE value (0 = DCP, 1..n = data pipe).
[in]is_in_dirtrue = device-to-host (write), false = the other way.
Precondition
reg != NULL.
Caller holds the DCP / pipe lock.
Postcondition
CFIFOSEL = MBW(speed) | (is_in_dir ? ISEL : 0) | pipe_num.
Subsequent CFIFO accesses must use the matching width.
Note
Not thread-safe.
Since
0.1.0

Picks MBW=32 for USBHS (FSP USB1_CFIFO_MBW) and MBW=16 for USBFS (FSP USB0_CFIFO_MBW). The CFIFO data-port access width must match the MBW field on subsequent CFIFO accesses.

Parameters
[in]regUSB instance register block.
[in]pipe_numCURPIPE value (0 = DCP, 1..n = data pipe).
[in]is_in_dirtrue = device-to-host (write), false = host-to-device.
Precondition
reg != NULL.
Caller holds the DCP / pipe lock.
Postcondition
CFIFOSEL = MBW(speed) | (is_in_dir ? ISEL : 0) | pipe_num.
Subsequent CFIFO accesses must use the matching width.
Note
Not thread-safe.
Since
0.1.0

Definition at line 199 of file ra8_usb.c.

References r_usb_regs_t::CFIFOSEL, k_ra8_fifosel_curpipe, k_ra8_fifosel_isel, k_ra8_fifosel_mbw_16, k_ra8_fifosel_mbw_32, k_ra8_usb_fifosel_settle_limit, and priv_is_hs().

Referenced by internal_dcp_reset_defaults(), internal_host_bulk_rx_packet(), internal_host_ctrl_data_arm(), internal_host_ctrl_data_in(), internal_host_ctrl_data_out(), internal_host_ctrl_status(), ra8_usb_dcp_in_data(), ra8_usb_dcp_out_arm(), ra8_usb_dcp_out_read(), ra8_usb_queue_in(), and ra8_usb_queue_out().

◆ priv_usb_init_common()

void priv_usb_init_common ( volatile r_usb_regs_t * reg)

Programme the post-SYSCFG common registers (FIFO, DCP, INTENB).

Promoted from a TU-private static in ra8_usb_phy.c so the device-mode init (ra8_usb_device.c) can apply the shared FS/HS tail of device bring-up.

Parameters
[in]regSelected USB instance register block.
Precondition
Caller has already enabled SYSCFG.USBE.
reg is non-null.
Postcondition
All listed registers carry deterministic device-mode defaults.
INTENB1 / BRDYENB / NRDYENB / BEMPENB are cleared.
Note
Not thread-safe; init context only.
Since
0.1.0

Shared tail of FS and HS device-mode bring-up: CFIFOSEL, DCP defaults, and the device-mode INTENB0 interrupt mask.

Parameters
[in]regSelected USB instance register block.
Precondition
Caller has already enabled SYSCFG.USBE.
reg is non-null.
Postcondition
All listed registers carry deterministic device-mode defaults.
INTENB1 / BRDYENB / NRDYENB / BEMPENB are cleared.
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 495 of file ra8_usb_phy.c.

References r_usb_regs_t::BEMPENB, r_usb_regs_t::BRDYENB, r_usb_regs_t::CFIFOSEL, r_usb_regs_t::D0FIFOSEL, r_usb_regs_t::D1FIFOSEL, r_usb_regs_t::DCPCFG, r_usb_regs_t::DCPCTR, r_usb_regs_t::DCPMAXP, r_usb_regs_t::INTENB0, r_usb_regs_t::INTENB1, r_usb_regs_t::INTSTS0, k_ra8_fifosel_mbw_16, 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_usb_dcp_max_packet, and r_usb_regs_t::NRDYENB.

Referenced by ra8_usb_device_init().

◆ priv_usbfs_module_bringup()

ra8_err_t priv_usbfs_module_bringup ( volatile r_usb_regs_t * reg)

USBFS module bring-up (FSP hw_usb_pmodule_init IP0 branch).

Promoted from a TU-private static in ra8_usb_phy.c so the device-mode init (ra8_usb_device.c) can run the FS SYSCFG sequence.

Parameters
[in]regFS register block pointer (must be ra8_usb_fs()).
Returns
ra8_err_t
Return values
k_ra8_okUSBE asserted.
k_ra8_err_hw_timeoutSCKE did not acknowledge within the bounded wait.
Precondition
MSTPB11 ungated; USB48CLK fed from PLL2P/5 = 48 MHz.
Caller is single-threaded init context.
Postcondition
SYSCFG: SCKE=1, DRPD=0, USBE=1.
Loop iteration count is bounded.
Note
Not thread-safe; init context only.
Since
0.1.0

Sets SCKE, polls SCKE-readback, clears DRPD, sets USBE. The FS instance has no PHY-side registers (PHYSET / LPSTS / PLLSTA are HS-only) so this is a pure SYSCFG-driven sequence.

Parameters
[in]regFS register block pointer (must be ra8_usb_fs()).
Returns
ra8_err_t
Return values
k_ra8_okUSBE asserted.
Precondition
MSTPB11 ungated; USB48CLK fed from PLL2P/5 = 48 MHz.
Caller is single-threaded init context.
Postcondition
SYSCFG: SCKE=1, DRPD=0, USBE=1.
Loop iteration count is bounded.
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 566 of file ra8_usb_phy.c.

References k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_syscfg_bit_drpd, k_ra8_syscfg_bit_scke, k_ra8_syscfg_bit_usbe, k_ra8_usbhs_scke_poll_limit, and r_usb_regs_t::SYSCFG.

Referenced by ra8_usb_device_init().

◆ priv_usbhs_phy_bringup()

ra8_err_t priv_usbhs_phy_bringup ( volatile r_usb_regs_t * reg)

USBHS embedded-PHY bring-up (HUM Figure 37.2 p 2121).

Promoted from a TU-private static in ra8_usb_phy.c so both the device-mode init (ra8_usb_device.c) and the host-mode init (ra8_usb_irq.c) can run the UTMI PHY bring-up. Implements the device-mode PHY bring-up flow from HUM Ch 37.3.3 + Figure 37.2.

Parameters
[in]regHS register block pointer (must be ra8_usb_hs()).
Returns
ra8_err_t
Return values
k_ra8_okHS PHY locked and ready for DPRPU attach.
k_ra8_err_hw_timeoutPLLSTA.PLLLOCK never asserted.
Precondition
MSTPB12 ungated; USB60CLK = PLL2P / 4 = 60 MHz.
Caller is single-threaded init context.
Postcondition
On success: PHY powered, PLL locked, USBE=1, SUSPENDM=1.
BUSWAIT programmed.
Note
Not thread-safe; init context only.
Since
0.1.0

Implements the device-mode PHY bring-up flow exactly as documented in HUM Ch 37.3.3 + Figure 37.2. The PHY UTMI internal PLL takes EXTAL directly (24 MHz on EK-RA8D2); USB60CLK = 60 MHz is the separate LINK domain clock supplied by ra8_cgc_usbhs_pll_enable.

  1. SYSCFG |= HSE (high-speed enable, before PHY)
  2. PHYSET |= DIRPD | PLLRESET; CLKSEL = 11b (24 MHz)
  3. delay 1 us (HUM "Wait 1 us" after CLKSEL)
  4. PHYSET &= ~DIRPD (release PHY analog power-down)
  5. delay 1 ms (HUM "Wait 1 ms" after DIRPD)
  6. PHYSET &= ~PLLRESET (release UTMI PHY PLL reset)
  7. LPSTS |= SUSPENDM (start the PHY clock)
  8. wait PLLSTA.PLLLOCK = 1 (UTMI PLL lock confirmation)
  9. SYSCFG &= ~DRPD; |= USBE (enable module operation)

BUSWAIT = 0x0F04 (4-wait + reserved b11-b8)

  1. PHYSET |= REPSEL_16 (terminator adjust cycle)

The HS instance has no SCKE bit (HUM Ch 37.2.1 "SYSCFG" register layout, p 2060); writing bit 10 there is a no-op.

Parameters
[in]regHS register block pointer (must be ra8_usb_hs()).
Returns
ra8_err_t
Return values
k_ra8_okHS PHY locked and ready for DPRPU attach.
k_ra8_err_hw_timeoutPLLSTA.PLLLOCK never asserted.
Precondition
MSTPB12 ungated; USB60CLK = PLL2P / 4 = 60 MHz.
Caller is single-threaded init context.
Postcondition
On success: PHY powered, PLL locked, USBE=1, SUSPENDM=1.
BUSWAIT programmed.
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 427 of file ra8_usb_phy.c.

References r_usb_regs_t::BUSWAIT, internal_usbhs_enable_syscfg(), internal_usbhs_try_clksel(), k_ra8_buswait_default, k_ra8_ok, k_ra8_physet_clksel_24, k_ra8_physet_repsel_16, k_ra8_syscfg_bit_hse, k_ra8_usbhs_clksel_no_winner, k_ra8_usbhs_phy_step_clksel_12, k_ra8_usbhs_phy_step_hse_set, k_ra8_usbhs_phy_step_pll_locked, k_ra8_usbhs_phy_step_usbe_set, ra8_log_error, ra8_usbhs_lpsts(), ra8_usbhs_physet(), s_clksel_attempt_pllsta, s_clksel_winner, s_phy_step_probe, s_tag, s_usbhs_init_probe, s_usbhs_pllsta_probe, and r_usb_regs_t::SYSCFG.

Referenced by internal_host_hs_bringup(), and ra8_usb_device_init().

◆ priv_wait_frdy()

ra8_err_t priv_wait_frdy ( volatile r_usb_regs_t * reg)

Spin until CFIFOCTR.FRDY asserts or a deadline elapses.

Promoted from a TU-private static. Bounded busy-wait shared by every CFIFO read / write path.

Parameters
[in]regUSB instance register block.
Returns
ra8_ok on FRDY, k_ra8_err_hw_timeout otherwise.
Return values
k_ra8_okFRDY asserted within the bound.
k_ra8_err_hw_timeoutFRDY never asserted.
Precondition
Module state is consistent.
CFIFOSEL has been programmed for the target pipe.
Postcondition
No register is modified.
On timeout the caller aborts the transfer.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0
Returns
ra8_ok on FRDY, k_ra8_err_hw_timeout otherwise.

Runs the real bounded FRDY poll on every build. On the host unit-test build each poll's loop-exit decision is routed through the ra8_fake_mmio fault seam keyed on CFIFOCTR: first-poll success when no fault is armed, or a test-armed retry / timeout leg (T1-01).

Parameters
[in]regSelected controller register block (non-NULL).
Return values
k_ra8_okFRDY observed before the deadline.
k_ra8_err_hw_timeoutFRDY never asserted within the budget.
Precondition
The CFIFO window is selected on the intended pipe.
reg points at a live controller register block.
Postcondition
On k_ra8_ok the CFIFO port is ready for a read/write access.
No register is modified by this function.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 251 of file ra8_usb.c.

References r_usb_regs_t::CFIFOCTR, k_ra8_err_hw_timeout, k_ra8_fifoctr_frdy, k_ra8_ok, and k_ra8_usb_frdy_poll_limit.

Referenced by internal_dcp_in_zlp(), internal_host_bulk_rx_packet(), internal_host_ctrl_data_in(), priv_dcp_push_chunk(), ra8_usb_dcp_out_read(), ra8_usb_queue_in(), and ra8_usb_queue_out().