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

USB host-mode control-transfer engine (polled, synchronous). More...

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

Go to the source code of this file.

Enumerations

enum  ra8_usb_host_ctrl_lim_t : uint32_t { k_ra8_usb_ctrl_poll_limit = 2000000UL }
 Tunables for the polled host control-transfer engine. More...
enum  ra8_usb_host_ctrl_stage_code_t : uint8_t {
  k_ra8_usb_cs_begin = 0U ,
  k_ra8_usb_cs_setup = 1U ,
  k_ra8_usb_cs_data_in = 2U ,
  k_ra8_usb_cs_data_pkt = 3U ,
  k_ra8_usb_cs_data_done = 4U ,
  k_ra8_usb_cs_status = 5U ,
  k_ra8_usb_cs_done = 6U ,
  k_ra8_usb_cs_data_out = 7U
}
 Stage codes recorded by the host control-transfer engine. More...

Functions

uint8_t ra8_usb_host_ctrl_stage (void)
 Last stage reached by ra8_usb_host_control_xfer (bring-up diag).
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.
static ra8_err_t internal_host_wait_sts (volatile const uint16_t *sts, uint16_t mask)
 Spin until a W0C status bit asserts or the deadline elapses.
static ra8_err_t internal_host_dcp_in_wait (volatile r_usb_regs_t *reg)
 Wait for a DCP IN packet (BRDY), re-arming on NRDY give-ups.
static ra8_err_t internal_host_setup_wait (volatile r_usb_regs_t *reg)
 Clear the SETUP outcome flags, launch SUREQ, and await SACK/SIGN.
static ra8_err_t internal_host_ctrl_setup (volatile r_usb_regs_t *reg, const ra8_usb_setup_t *setup)
 Issue the SETUP stage of a host control transfer and wait for it.
static void internal_host_ctrl_data_arm (volatile r_usb_regs_t *reg)
 Arm the DCP to receive a control-read data stage.
static ra8_err_t internal_host_ctrl_data_in (volatile r_usb_regs_t *reg, uint8_t *data, uint16_t want, uint16_t mxps, uint16_t *out_rx)
 Run the DATA-IN stage of a host control read into data.
static ra8_err_t internal_host_ctrl_status (volatile r_usb_regs_t *reg, bool write_zlp)
 Run the zero-length STATUS stage and complete the control transfer.
static ra8_err_t internal_host_ctrl_data_out (volatile r_usb_regs_t *reg, const uint8_t *data, uint16_t want, uint16_t mxps)
 Run the DATA-OUT stage of a host control write from data.
ra8_err_t ra8_usb_dcp_out_arm (ra8_usb_speed_t speed)
 Implementation of ra8_usb_dcp_out_arm() – arm the DCP for control-OUT.
ra8_err_t ra8_usb_dcp_out_read (ra8_usb_speed_t speed, uint8_t *buf, uint16_t cap, uint16_t *out_rx)
 Implementation of ra8_usb_dcp_out_read() – drain an armed control-OUT.
static ra8_err_t internal_host_data_phase (volatile r_usb_regs_t *reg, const ra8_usb_setup_t *setup, uint8_t *data, uint16_t data_len, uint16_t *out_rx, bool *out_is_read)
 Classify and execute the optional DATA stage of a host control transfer.
ra8_err_t ra8_usb_host_control_xfer (ra8_usb_speed_t speed, const ra8_usb_setup_t *setup, uint8_t *data, uint16_t data_len, uint16_t *out_received)
 Run a complete host control transfer (SETUP, optional DATA, STATUS).

Variables

static const char * s_tag = "USB"
static volatile uint8_t s_host_ctrl_stage = (uint8_t)k_ra8_usb_cs_begin
 Last host control-transfer stage reached (bring-up diagnostic).

Detailed Description

USB host-mode control-transfer engine (polled, synchronous).

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

Host-mode control-transfer engine plus the device-address (DEVADDn) programmer it shares with the bulk engine. Composes the shared FIFO / PID helpers into a blocking GET / SET control transfer over the DCP (pipe 0): SETUP stage, optional DATA-IN / DATA-OUT stage, and the zero-length STATUS stage. Also hosts the non-blocking device-side control-OUT DCP arm / read helpers (ra8_usb_dcp_out_arm / ra8_usb_dcp_out_read). Split out of ra8_usb.c so every translation unit stays under the 1000-line cap; the shared register helpers and host addressing enums it uses are declared in ra8_usb_internal.h. Modelled on FSP r_usb_hreg_abs.c; no FSP source ships in this tree.

Since
0.1.0

Definition in file ra8_usb_host_ctrl.c.

Enumeration Type Documentation

◆ ra8_usb_host_ctrl_lim_t

enum ra8_usb_host_ctrl_lim_t : uint32_t

Tunables for the polled host control-transfer engine.

Enumerator
k_ra8_usb_ctrl_poll_limit 

Spin bound per control stage.

Definition at line 50 of file ra8_usb_host_ctrl.c.

◆ ra8_usb_host_ctrl_stage_code_t

Stage codes recorded by the host control-transfer engine.

Enumerator
k_ra8_usb_cs_begin 

Before the SETUP stage.

k_ra8_usb_cs_setup 

SETUP stage completed.

k_ra8_usb_cs_data_in 

DATA-IN stage entered.

k_ra8_usb_cs_data_pkt 

First DATA packet received.

k_ra8_usb_cs_data_done 

DATA stage completed.

k_ra8_usb_cs_status 

STATUS stage entered.

k_ra8_usb_cs_done 

STATUS done; transfer closed.

k_ra8_usb_cs_data_out 

DATA-OUT stage entered.

Definition at line 55 of file ra8_usb_host_ctrl.c.

Function Documentation

◆ internal_host_ctrl_data_arm()

void internal_host_ctrl_data_arm ( volatile r_usb_regs_t * reg)
static

Arm the DCP to receive a control-read data stage.

Selects the DCP read window, frees the receive buffer (BCLR), enables the BRDY/NRDY status latches, forces the receive toggle to DATA1 (FSP usb_hstd_ctrl_read_start: the first data packet after SETUP is always DATA1, and a stale SQMON makes the SIE silently discard it), then sets PID=BUF so IN tokens flow.

Parameters
[in]regSelected controller register block.
Precondition
The SETUP stage for an IN request has completed (SACK).
The DCP PID is NAK on entry.
Postcondition
The DCP is armed (PID=BUF) with a clean receive buffer.
BRDYENB/NRDYENB carry the DCP bit.
Note
Helper split out for the clang-tidy size/complexity gate.
Since
0.1.0

Definition at line 318 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BRDYENB, r_usb_regs_t::CFIFOCTR, r_usb_regs_t::DCPCTR, k_ra8_dcpctr_bit_sqset, k_ra8_fifoctr_bclr, k_ra8_pid_buf, k_ra8_usb_dcp_pipe0_bit, r_usb_regs_t::NRDYENB, priv_dcp_pid(), priv_rmw16(), and priv_select_cfifo().

Referenced by internal_host_ctrl_data_in().

◆ internal_host_ctrl_data_in()

ra8_err_t internal_host_ctrl_data_in ( volatile r_usb_regs_t * reg,
uint8_t * data,
uint16_t want,
uint16_t mxps,
uint16_t * out_rx )
static

Run the DATA-IN stage of a host control read into data.

Arms the DCP for IN (PID=BUF, BRDY/NRDY status enabled), then loops reading BRDY-gated CFIFO packets via priv_fifo_read until a short packet or want bytes, parking the pipe NAK on exit.

Parameters
[in]regSelected controller register block.
[out]dataDestination buffer.
[in]wantBytes the caller can accept.
[in]mxpsDCP max packet size (short-packet threshold).
[out]out_rxReceives the byte count read from the device.
Returns
k_ra8_ok on a complete/short-packet read, else a timeout code.
Return values
k_ra8_okA short packet or want bytes were read.
k_ra8_err_hw_timeoutNo DATA packet arrived before the deadline.
Precondition
The SETUP stage for an IN request has completed.
data holds at least want bytes.
Postcondition
out_rx holds the number of bytes the device returned.
The DCP PID is left NAK.
Note
Blocking; each packet is bounded by the poll limit.
Since
0.1.0

Definition at line 351 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BRDYSTS, r_usb_regs_t::CFIFOCTR, internal_host_ctrl_data_arm(), internal_host_dcp_in_wait(), k_ra8_err_hw_timeout, k_ra8_fifoctr_bclr, k_ra8_fifoctr_dtln, k_ra8_ok, k_ra8_pid_nak, k_ra8_usb_cs_data_pkt, k_ra8_usb_dcp_pipe0_bit, priv_dcp_pid(), priv_fifo_read(), priv_select_cfifo(), priv_wait_frdy(), and s_host_ctrl_stage.

Referenced by internal_host_data_phase().

◆ internal_host_ctrl_data_out()

ra8_err_t internal_host_ctrl_data_out ( volatile r_usb_regs_t * reg,
const uint8_t * data,
uint16_t want,
uint16_t mxps )
static

Run the DATA-OUT stage of a host control write from data.

The host-side mirror of internal_host_ctrl_data_in: selects the DCP write window, discards any stale bank, forces the DATA1 start toggle (the first data packet after a SETUP is always DATA1), then pushes the payload to the device in MPS-sized CFIFO packets via priv_dcp_push_chunk (BVAL) + PID=BUF, waiting for the buffer-empty (BEMP) event after each, and parks the DCP NAK on exit. This is what lets a class control write carry a data stage host -> device – e.g. a DFU_DNLOAD firmware block.

Parameters
[in]regSelected controller register block.
[in]dataSource payload (host -> device).
[in]wantBytes to send (the SETUP wLength, clamped to the buffer).
[in]mxpsDCP max packet size (per-packet chunk bound).
Returns
k_ra8_ok when the whole payload was transmitted, else a timeout code.
Return values
k_ra8_okAll want bytes were sent and the buffer drained.
k_ra8_err_hw_timeoutA packet never drained (BEMP) before the deadline.
Precondition
The SETUP stage for an OUT request with wLength > 0 completed (SACK).
data holds at least want bytes; the DCP PID is NAK on entry.
Postcondition
The whole payload was driven to the device; the DCP PID is left NAK.
BEMPENB carries the DCP bit; BEMPSTS is cleared.
Note
Blocking; each packet is bounded by the control poll limit.
Since
0.1.0

Definition at line 500 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BEMPENB, r_usb_regs_t::BEMPSTS, r_usb_regs_t::CFIFOCTR, r_usb_regs_t::DCPCFG, r_usb_regs_t::DCPCTR, internal_host_wait_sts(), k_ra8_dcpcfg_bit_dir, k_ra8_dcpctr_bit_sqset, 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_dcp_push_chunk(), priv_rmw16(), and priv_select_cfifo().

Referenced by internal_host_data_phase().

◆ internal_host_ctrl_setup()

ra8_err_t internal_host_ctrl_setup ( volatile r_usb_regs_t * reg,
const ra8_usb_setup_t * setup )
static

Issue the SETUP stage of a host control transfer and wait for it.

Parks the DCP NAK, programs the target device speed, loads the USBREQ/VAL/INDX/LENG mirror registers, asserts SUREQ and spins until the SIE self-clears it (the SETUP token has been delivered + handshaked).

Parameters
[in]regSelected controller register block.
[in]setupSetup packet to transmit.
Returns
k_ra8_ok once SUREQ clears, else k_ra8_err_busy / k_ra8_err_hw_timeout.
Return values
k_ra8_okSETUP delivered and SUREQ cleared.
k_ra8_err_busyA control transfer was already pending.
k_ra8_err_hw_timeoutSUREQ did not clear before the deadline.
Precondition
reg / setup are non-NULL; the bus is reset and UACT is on.
No control transfer is already pending (SUREQ clear).
Postcondition
The 8-byte SETUP token has been delivered to the device.
Stale DCP BRDY/BEMP status has been cleared.
Note
Blocking; bounded by k_ra8_usb_ctrl_poll_limit.
Since
0.1.0

Definition at line 248 of file ra8_usb_host_ctrl.c.

References ra8_usb_setup_t::b_request, r_usb_regs_t::BEMPSTS, ra8_usb_setup_t::bm_request_type, r_usb_regs_t::BRDYSTS, r_usb_regs_t::DCPCTR, r_usb_regs_t::DCPMAXP, r_usb_regs_t::INTENB1, internal_host_setup_wait(), k_ra8_dcpctr_bit_ccpl, k_ra8_dcpctr_bit_sureq, k_ra8_dcpctr_bit_sureqclr, k_ra8_err_busy, k_ra8_int1_bit_sack, k_ra8_int1_bit_sign, k_ra8_pid_nak, k_ra8_usb_byte_bits, k_ra8_usb_dcp_pipe0_bit, k_ra8_usb_devsel_field_mask, k_ra8_usb_devsel_shift, priv_dcp_pid(), priv_host_program_devadd(), priv_is_hs(), priv_rmw16(), 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 ra8_usb_host_control_xfer().

◆ internal_host_ctrl_status()

ra8_err_t internal_host_ctrl_status ( volatile r_usb_regs_t * reg,
bool write_zlp )
static

Run the zero-length STATUS stage and complete the control transfer.

Parks the DCP NAK, drains residual data-stage bytes, forces the DATA1 sequence bit, then asserts CCPL + PID=BUF so the SIE runs the opposite-direction zero-length status stage; completion is taken from CCPL self-clearing.

Parameters
[in]regSelected controller register block.
[in]write_zlptrue => status is OUT (after a data-IN read); false => status is IN (control write / no-data).
Returns
Always k_ra8_ok (the status stage is best-effort).
Return values
k_ra8_okThe status sequence was driven; the wire-level handshake is verified by the next transfer / the class protocol.
Precondition
The SETUP (and any DATA) stage has completed.
The DCP PID is NAK on entry.
Postcondition
CCPL has been asserted so the SIE closes the control transfer.
The DCP PID is NAK and CCPL is cleared on exit.
Note
Best-effort by design: hardware bring-up showed the device completes the status handshake (the SIE auto-ACKs its ZLP) while the DCP BRDY/BEMP completion indication is unreliable, so gating on it deadlocks transfers that actually succeeded. Real verification comes from the next SETUP (control) or the BOT/CSW exchange (bulk).
Since
0.1.0

Definition at line 422 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BEMPENB, r_usb_regs_t::BEMPSTS, r_usb_regs_t::BRDYENB, r_usb_regs_t::BRDYSTS, r_usb_regs_t::CFIFOCTR, r_usb_regs_t::DCPCFG, r_usb_regs_t::DCPCTR, internal_host_dcp_in_wait(), internal_host_wait_sts(), k_ra8_dcpcfg_bit_dir, k_ra8_dcpctr_bit_ccpl, k_ra8_dcpctr_bit_sqset, k_ra8_fifoctr_bclr, k_ra8_fifoctr_bval, k_ra8_ok, k_ra8_pid_buf, k_ra8_pid_nak, k_ra8_usb_dcp_pipe0_bit, r_usb_regs_t::NRDYSTS, priv_dcp_pid(), priv_rmw16(), and priv_select_cfifo().

Referenced by ra8_usb_host_control_xfer().

◆ internal_host_data_phase()

ra8_err_t internal_host_data_phase ( volatile r_usb_regs_t * reg,
const ra8_usb_setup_t * setup,
uint8_t * data,
uint16_t data_len,
uint16_t * out_rx,
bool * out_is_read )
static

Classify and execute the optional DATA stage of a host control transfer.

Inspects the SETUP packet to determine the data-stage direction: a non-zero wLength with bmRequestType bit 7 set (device-to-host) and a non-NULL destination buffer indicates a control-read DATA-IN stage; a non-zero wLength with bit 7 clear and a non-NULL source buffer indicates a control-write DATA-OUT stage; otherwise there is no data stage. For each case the function:

  1. Resolves the DCP max packet size from DCPMAXP.MXPS.
  2. Clamps the transfer size to min(setup->w_length, data_len).
  3. Dispatches to internal_host_ctrl_data_out (DATA-OUT) or internal_host_ctrl_data_in (DATA-IN) as appropriate, updating s_host_ctrl_stage before and after each.
  4. Records zero bytes received and out_is_read = false when no data stage runs (no-data control transfer), and returns k_ra8_ok.
Parameters
[in]regSelected USB controller register block; must have been returned by priv_pick (non-NULL).
[in]setupSETUP packet just delivered to the device; used for bmRequestType direction bit and wLength.
[in,out]dataBuffer for the data stage: source bytes for DATA-OUT, destination bytes for DATA-IN; may be NULL only when there is no data stage (w_length == 0 or no buffer).
[in]data_lenCapacity of data in bytes; clamps the transfer.
[out]out_rxReceives the byte count actually read from the device (DATA-IN only); set to 0 for DATA-OUT or no-data.
[out]out_is_readSet to true when a DATA-IN stage ran; false otherwise.
Returns
ra8_err_t Transfer outcome.
Return values
k_ra8_okNo data stage ran, or the DATA stage completed.
k_ra8_err_hw_timeoutA DATA-IN or DATA-OUT packet stalled before the deadline elapsed.
k_ra8_err_hw_errorThe device STALLed the endpoint during DATA-OUT.
Precondition
reg is non-NULL and points at a powered, host-mode controller.
The SETUP stage for setup has already completed (SUREQ self-cleared).
out_rx and out_is_read are non-NULL output pointers.
Postcondition
out_rx holds the DATA-IN byte count (0 if no IN stage ran).
out_is_read reflects whether a DATA-IN stage ran.
Note
Not thread-safe; caller (ra8_usb_host_control_xfer) serialises access.
Since
0.1.0

Definition at line 720 of file ra8_usb_host_ctrl.c.

References ra8_usb_setup_t::bm_request_type, r_usb_regs_t::DCPMAXP, internal_host_ctrl_data_in(), internal_host_ctrl_data_out(), k_ra8_ok, k_ra8_usb_cs_data_done, k_ra8_usb_cs_data_in, k_ra8_usb_cs_data_out, k_ra8_usb_dcpmaxp_mxps, k_ra8_usb_setup_dir_in, s_host_ctrl_stage, and ra8_usb_setup_t::w_length.

Referenced by ra8_usb_host_control_xfer().

◆ internal_host_dcp_in_wait()

ra8_err_t internal_host_dcp_in_wait ( volatile r_usb_regs_t * reg)
static

Wait for a DCP IN packet (BRDY), re-arming on NRDY give-ups.

In host mode the SIE retries a NAKed IN a few times, then latches NRDY and parks the DCP PID at NAK. A device that is still processing a request (e.g. applying SET_CONFIGURATION before its status ZLP) NAKs long enough to trip this, so treat NRDY as "retry": clear it and re-arm PID=BUF until BRDY or the time bound.

Parameters
[in]regSelected controller register block.
Returns
Wait outcome.
Return values
k_ra8_okA packet landed (BRDY).
k_ra8_err_hw_timeoutNo packet before the spin bound.
Precondition
The DCP receive buffer is free and PID is BUF.
BRDYENB/NRDYENB carry the DCP bit so the status can latch.
Postcondition
BRDY is left set for the caller to consume; NRDY is clear.
On timeout the DCP PID state is whatever the SIE parked.
Note
Blocking; bounded by k_ra8_usb_ctrl_poll_limit.
Since
0.1.0

Definition at line 151 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::BRDYSTS, r_usb_regs_t::DCPCTR, k_ra8_err_hw_error, k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_pid_buf, k_ra8_usb_ctrl_poll_limit, k_ra8_usb_dcp_pipe0_bit, k_ra8_usb_pid_stall_bit, r_usb_regs_t::NRDYSTS, and priv_dcp_pid().

Referenced by internal_host_ctrl_data_in(), and internal_host_ctrl_status().

◆ internal_host_setup_wait()

ra8_err_t internal_host_setup_wait ( volatile r_usb_regs_t * reg)
static

Clear the SETUP outcome flags, launch SUREQ, and await SACK/SIGN.

Split out of internal_host_ctrl_setup so the blocking wait keeps that function inside one page. This W0C-clears the stale SACK/SIGN latches, asserts SUREQ, and spins until the SIE latches SACK (device ACK), SIGN (three failed attempts), or the bound elapses. The host unit-test build runs this SAME bounded poll loop: only the pre-loop W0C clear is skipped there (its plain-RAM INTSTS1 cannot be re-latched after a clear, so wiping it would erase a test's pre-loaded outcome), and each SACK poll is routed through the ra8_fake_mmio host seam – transparent when a test pre-loads INTSTS1, or armable to force the timeout leg or step the loop for MC/DC. The SACK, SIGN, and timeout legs thus each execute against the real code path in host unit tests.

Parameters
[in]regSelected controller register block.
Returns
SETUP wait outcome.
Return values
k_ra8_okSACK latched – the device ACKed the SETUP.
k_ra8_err_hw_errorSIGN latched – three transmission attempts failed.
k_ra8_err_hw_timeoutNo SACK/SIGN before the spin bound.
Precondition
reg points at a live controller block with SUREQ armable.
INTENB1 already carries the SACK/SIGN enables.
Postcondition
On success SACK is cleared; on error SIGN is cleared.
SUREQ has been asserted exactly once.
Note
Blocking; bounded by k_ra8_usb_ctrl_poll_limit.
Since
0.1.0

Definition at line 195 of file ra8_usb_host_ctrl.c.

References r_usb_regs_t::DCPCTR, r_usb_regs_t::INTSTS1, k_ra8_dcpctr_bit_sureq, k_ra8_err_hw_error, k_ra8_err_hw_timeout, k_ra8_int1_bit_sack, k_ra8_int1_bit_sign, k_ra8_ok, k_ra8_usb_ctrl_poll_limit, and priv_rmw16().

Referenced by internal_host_ctrl_setup().

◆ internal_host_wait_sts()

ra8_err_t internal_host_wait_sts ( volatile const uint16_t * sts,
uint16_t mask )
static

Spin until a W0C status bit asserts or the deadline elapses.

Bounded busy-wait over a USB interrupt-status register; the polled host control engine uses it to gate on DCP BRDY/BEMP edges without arming the NVIC USB line.

Parameters
[in]stsPointer to the status register (BRDYSTS / BEMPSTS).
[in]maskBit to wait for.
Returns
k_ra8_ok on assertion, k_ra8_err_hw_timeout otherwise.
Return values
k_ra8_okThe masked bit asserted within the bound.
k_ra8_err_hw_timeoutThe bit never asserted before the deadline.
Precondition
sts points at a live USB status register.
Interrupts for this controller are quiescent (polled driver).
Postcondition
No register is modified.
On timeout the caller aborts the transfer.
Note
Bounded busy-wait; FS control stages settle well inside the bound.
Since
0.1.0

Definition at line 120 of file ra8_usb_host_ctrl.c.

References k_ra8_err_hw_timeout, k_ra8_ok, and k_ra8_usb_ctrl_poll_limit.

Referenced by internal_host_ctrl_data_out(), and internal_host_ctrl_status().

◆ 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.

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

◆ ra8_usb_dcp_out_arm()

ra8_err_t ra8_usb_dcp_out_arm ( ra8_usb_speed_t speed)
nodiscard

Implementation of ra8_usb_dcp_out_arm() – arm the DCP for control-OUT.

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

Implementation of ra8_usb_dcp_out_read() – drain an armed control-OUT.

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

ra8_err_t ra8_usb_host_control_xfer ( ra8_usb_speed_t speed,
const ra8_usb_setup_t * setup,
uint8_t * data,
uint16_t data_len,
uint16_t * out_received )
nodiscard

Run a complete host control transfer (SETUP, optional DATA, STATUS).

Polled, synchronous control transfer over the DCP (pipe 0). Drives the SETUP stage (SUREQ + wait for self-clear), an optional DATA-IN stage for device-to-host requests (BRDY-gated CFIFO reads), and the zero-length STATUS stage (CCPL). Completion is detected via SUREQ-clear / BRDY / BEMP – the host-mode signals – not CTRT, which only fires in device mode. This is the host counterpart of the device-mode control path and the primitive the host class drivers (MSC/HID/CDC) build enumeration on.

Parameters
[in]speedWhich controller (FS or HS).
[in]setupThe 8-byte SETUP packet.
[out]dataBuffer for the DATA-IN stage (may be NULL for no-data / control-write requests).
[in]data_lenCapacity of data in bytes.
[out]out_receivedOptional; receives DATA-IN bytes read (0 if none).
Returns
ra8_err_t error code.
Return values
k_ra8_okTransfer completed through the status stage.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_null_ptrsetup was NULL.
k_ra8_err_busyA control transfer was already pending.
k_ra8_err_hw_timeoutA stage did not complete within the bound.
Precondition
ra8_usb_host_init ran; the bus is reset and DVSTCTR0.UACT = 1.
setup is non-NULL; data holds at least data_len bytes if used.
Postcondition
On k_ra8_ok the device has seen the request and any IN data is in data with the count in out_received.
The DCP PID is left NAK.
Note
Blocking; each stage is bounded by an internal spin limit.
Since
0.1.0

Definition at line 763 of file ra8_usb_host_ctrl.c.

References internal_host_ctrl_setup(), internal_host_ctrl_status(), internal_host_data_phase(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_cs_begin, k_ra8_usb_cs_done, k_ra8_usb_cs_setup, k_ra8_usb_cs_status, priv_pick(), RA8_CHECK_NULL_PTR, s_host_ctrl_stage, and s_tag.

Referenced by cdc_ctrl_get_dev_desc(), cdc_enum_set_address(), cdc_enum_set_config(), dfu_ctrl_get_dev_desc(), dfu_dnload_block(), dfu_download_all(), dfu_enum_set_address(), dfu_enum_set_config(), dfu_getstatus(), dfu_upload_verify(), hid_ctrl_get_dev_desc(), hid_ctrl_get_dev_desc(), hid_enum_set_address(), hid_enum_set_address(), hid_enum_set_config(), hid_enum_set_config(), internal_dnload_block(), internal_download_all(), internal_download_manifest(), internal_enum_assign_addr(), internal_enum_configure(), internal_enum_read_config(), internal_enum_read_dev_desc(), internal_get_dev_desc(), internal_getstatus(), internal_set_address(), internal_set_config(), internal_upload_verify(), ns_host_get_dev_desc(), ns_host_set_address(), and ns_host_set_config().

◆ ra8_usb_host_ctrl_stage()

uint8_t ra8_usb_host_ctrl_stage ( void )

Last stage reached by ra8_usb_host_control_xfer (bring-up diag).

0=before SETUP, 1=SETUP done, 2=DATA-IN entered, 3=first packet received, 4=DATA done, 5=STATUS entered, 6=STATUS done. Lets a caller pinpoint where a timed-out control transfer stalled.

Returns
The stage code from the most recent control transfer.
Return values
0No control transfer has run since reset.
6The most recent control transfer closed cleanly.
Precondition
ra8_usb_host_init ran for the controller of interest.
At least one ra8_usb_host_control_xfer may have been attempted.
Postcondition
No state is modified.
The returned value reflects the last transfer only.
Note
Diagnostic only; not part of the transfer contract.
Since
0.1.0

Definition at line 69 of file ra8_usb_host_ctrl.c.

References s_host_ctrl_stage.

Variable Documentation

◆ s_host_ctrl_stage

volatile uint8_t s_host_ctrl_stage = (uint8_t)k_ra8_usb_cs_begin
static

Last host control-transfer stage reached (bring-up diagnostic).

Definition at line 67 of file ra8_usb_host_ctrl.c.

Referenced by internal_host_ctrl_data_in(), internal_host_data_phase(), ra8_usb_host_control_xfer(), and ra8_usb_host_ctrl_stage().

◆ s_tag

const char* s_tag = "USB"
static

Definition at line 36 of file ra8_usb_host_ctrl.c.