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

USB PAL implementation – ra8_usb wrapper. More...

#include "ra8_usb_pal.h"
#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_pal_internal.h"
Include dependency graph for ra8_usb_pal.c:

Go to the source code of this file.

Data Structures

struct  ra8_usb_pal_packet_t
 One packet on a per-endpoint ring. More...
struct  ra8_usb_pal_ep_slot_t
 Configuration + queue for one endpoint. More...
struct  ra8_usb_pal_state_inner_t
 Singleton PAL state. More...

Enumerations

enum  ra8_usb_pal_ring_dim_t : uint16_t {
  k_ra8_usb_pal_ep_table_len = 11U ,
  k_ra8_usb_pal_ring_slots = 4U ,
  k_ra8_usb_pal_pkt_max = 1024U
}

Functions

bool priv_usb_pal_should_dispatch_event (const void *event_fn, uint16_t mask, uint16_t none_value)
 Pure dispatch-event predicate – see header for full contract.
bool priv_usb_pal_ep_out_of_range (uint8_t ep_addr, uint8_t ep_max)
 Pure ep-out-of-range predicate – see header for full contract.
static void internal_copy_bytes (uint8_t *dst, const uint8_t *src, uint16_t len)
 Copy len bytes (string.h-free local memcpy substitute).
static void internal_reset_eps (void)
 Reset every endpoint slot to empty / unopened.
static uint16_t internal_translate (uint16_t usb_mask)
 Translate ra8_usb status mask -> PAL event mask.
static void internal_usb_event (void *ctx, ra8_usb_speed_t speed, uint16_t status_mask)
 ra8_usb event handler – translate + forward to the PAL callback.
ra8_err_t ra8_usb_pal_init (ra8_usb_speed_t speed)
 Bring up the USB PAL singleton at the requested speed.
ra8_err_t ra8_usb_pal_deinit (void)
 Tear down the USB PAL singleton.
ra8_err_t ra8_usb_pal_attach (bool attached)
 Drive the D+ pull-up to attach or detach the device.
ra8_err_t ra8_usb_pal_get_state (ra8_usb_pal_state_t *out_state)
 Read the current PAL state machine.
ra8_err_t ra8_usb_pal_ep_open (uint8_t ep_addr, ra8_usb_pal_ep_dir_t dir, ra8_usb_pal_ep_type_t type, uint16_t max_packet)
 Open one endpoint and reserve a per-EP packet ring.
ra8_err_t ra8_usb_pal_ep_send (uint8_t ep_addr, const uint8_t *data, uint16_t len)
 Queue a packet for transmit on an open IN endpoint.
ra8_err_t ra8_usb_pal_ep_recv (uint8_t ep_addr, uint8_t *out_buf, uint16_t *inout_len)
 Pull the next packet, if any, from an open OUT endpoint.
ra8_err_t ra8_usb_pal_set_event_handler (ra8_usb_pal_event_fn_t fn, void *ctx)
 Install a single event handler for bus and per-EP events.

Variables

static const char * s_tag = "USBPAL"
static ra8_usb_pal_state_inner_t s_state = {}

Detailed Description

USB PAL implementation – ra8_usb wrapper.

Tag
[Ring 4 / PAL] {World: NS}

PAL over the Ring-3 ra8_usb driver. Endpoints are backed by a small in-memory queue so the PAL is usable in host tests (and any future software-only transport) before the real ra8_usb pipe primitives land. On hardware the queue is backed by the controller's pipe FIFOs; the stack-facing contract is identical in either case.

Definition in file ra8_usb_pal.c.

Enumeration Type Documentation

◆ ra8_usb_pal_ring_dim_t

enum ra8_usb_pal_ring_dim_t : uint16_t
Enumerator
k_ra8_usb_pal_ep_table_len 

Index 0..ep_max, 1-based EPs.

k_ra8_usb_pal_ring_slots 

Per-EP queue depth.

k_ra8_usb_pal_pkt_max 

Per-packet capacity.

Definition at line 79 of file ra8_usb_pal.c.

Function Documentation

◆ internal_copy_bytes()

void internal_copy_bytes ( uint8_t * dst,
const uint8_t * src,
uint16_t len )
static

Copy len bytes (string.h-free local memcpy substitute).

The codebase avoids string.h to keep clang-tidy's insecureAPI.DeprecatedOrUnsafeBufferHandling check quiet; this loop fills the same role for small fixed buffers.

Parameters
[out]dstDestination buffer; must hold at least len bytes.
[in]srcSource buffer; must hold at least len bytes.
[in]lenNumber of bytes to copy.
Precondition
dst and src are non-NULL.
dst and src do not overlap.
Postcondition
dst[0..len-1] == src[0..len-1].
No other state is mutated.
Note
Pure helper; safe from any context.
Since
0.1.0

Definition at line 155 of file ra8_usb_pal.c.

Referenced by ra8_usb_pal_ep_recv(), and ra8_usb_pal_ep_send().

◆ internal_reset_eps()

void internal_reset_eps ( void )
static

Reset every endpoint slot to empty / unopened.

Walks the per-endpoint table, marks each slot opened == false, resets its OUT/control defaults, and zeroes the per-EP ring cursors and packet lengths.

Precondition
Caller holds the PAL single-thread lock (init/deinit context).
s_state storage is mapped and writable.
Postcondition
Every s_state.eps[i].opened == false.
Every per-EP ring is cursor-reset and length-zeroed.
Note
Not thread-safe; call only from init/deinit paths.
Since
0.1.0

Definition at line 179 of file ra8_usb_pal.c.

References ra8_usb_pal_ep_slot_t::count, ra8_usb_pal_ep_slot_t::dir, ra8_usb_pal_ep_slot_t::head, k_ra8_usb_pal_ep_dir_out, k_ra8_usb_pal_ep_table_len, k_ra8_usb_pal_ep_type_control, k_ra8_usb_pal_ring_slots, ra8_usb_pal_packet_t::len, ra8_usb_pal_ep_slot_t::max_packet, ra8_usb_pal_ep_slot_t::opened, ra8_usb_pal_ep_slot_t::ring, s_state, ra8_usb_pal_ep_slot_t::tail, and ra8_usb_pal_ep_slot_t::type.

Referenced by ra8_usb_pal_deinit(), and ra8_usb_pal_init().

◆ internal_translate()

uint16_t internal_translate ( uint16_t usb_mask)
static

Translate ra8_usb status mask -> PAL event mask.

Today the mapping is "any non-zero ra8_usb status bit becomes an error event"; later waves will fan the bits out into per-EP and bus-event masks.

Parameters
[in]usb_maskRaw status mask published by ra8_usb.
Returns
PAL-side event mask suitable for the stack callback.
Return values
k_ra8_usb_pal_event_noneusb_mask was zero.
k_ra8_usb_pal_event_errorusb_mask had any bit set.
Precondition
usb_mask may take any uint16_t value.
No global state is read.
Postcondition
No state is modified.
Return value reflects the translation only.
Note
Pure helper; safe from any context.
Since
0.1.0

Definition at line 219 of file ra8_usb_pal.c.

References k_ra8_usb_pal_event_error, and k_ra8_usb_pal_event_none.

Referenced by internal_usb_event().

◆ internal_usb_event()

void internal_usb_event ( void * ctx,
ra8_usb_speed_t speed,
uint16_t status_mask )
static

ra8_usb event handler – translate + forward to the PAL callback.

Installed via ra8_usb_attach_handler during ra8_usb_pal_init. Drops events while the PAL is uninitialized or arriving from a different speed than the one negotiated, then translates the raw status mask via internal_translate and forwards non-zero results to the stack callback.

Parameters
[in]ctxOpaque context (unused – PAL is a singleton).
[in]speedSpeed reported by the ra8_usb driver.
[in]status_maskRaw ra8_usb status bits.
Precondition
Invoked from ra8_usb ISR or task context.
s_state storage is mapped and readable.
Postcondition
No PAL state is mutated.
Stack callback is invoked at most once per call.
Note
Treat as not thread-safe; do not call back into the PAL from inside the callback.
Since
0.1.0

Definition at line 251 of file ra8_usb_pal.c.

References internal_translate(), k_ra8_usb_pal_event_none, priv_usb_pal_should_dispatch_event(), and s_state.

Referenced by ra8_usb_pal_init().

◆ priv_usb_pal_ep_out_of_range()

bool priv_usb_pal_ep_out_of_range ( uint8_t ep_addr,
uint8_t ep_max )

Pure ep-out-of-range predicate – see header for full contract.

Pure predicate: endpoint number is zero OR exceeds max.

Promoted helper so the line-559 OR can be driven under MC/DC.

Parameters
[in]ep_addrEndpoint number.
[in]ep_maxMaximum permitted endpoint number.
Returns
Boolean reject predicate.
Return values
trueCaller returns invalid-arg.
falseEndpoint is in range.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 67 of file ra8_usb_pal.c.

Referenced by ra8_usb_pal_ep_open(), ra8_usb_pal_ep_recv(), and ra8_usb_pal_ep_send().

◆ priv_usb_pal_should_dispatch_event()

bool priv_usb_pal_should_dispatch_event ( const void * event_fn,
uint16_t mask,
uint16_t none_value )

Pure dispatch-event predicate – see header for full contract.

Pure predicate: callback non-NULL AND mask non-zero.

Promoted helper so the line-218 AND can be driven under MC/DC.

Parameters
[in]event_fnApplication callback.
[in]maskTranslated event-mask bits.
[in]none_valueNumeric value of k_ra8_usb_pal_event_none.
Returns
Boolean predicate.
Return values
trueCaller invokes event_fn.
falseSkip the callback.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 47 of file ra8_usb_pal.c.

Referenced by internal_usb_event().

◆ ra8_usb_pal_attach()

ra8_err_t ra8_usb_pal_attach ( bool attached)
nodiscard

Drive the D+ pull-up to attach or detach the device.

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

Wraps ra8_usb_device_attach and updates the cached PAL state so subsequent ra8_usb_pal_get_state calls reflect the request.

Parameters
[in]attachedtrue to assert attach, false to detach.
Returns
ra8_err_t error code from the underlying driver.
Return values
k_ra8_okAttach state updated.
k_ra8_err_invalid_statePAL not initialized.
Precondition
PAL has been initialized.
Bus is in a stable enumeration state (host connected if attaching).
Postcondition
On success, s_state.state reflects attached.
On error, no PAL state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 381 of file ra8_usb_pal.c.

References k_ra8_err_invalid_state, k_ra8_ok, k_ra8_usb_pal_state_attached, k_ra8_usb_pal_state_detached, ra8_usb_device_attach(), and s_state.

◆ ra8_usb_pal_deinit()

ra8_err_t ra8_usb_pal_deinit ( void )
nodiscard

Tear down the USB PAL singleton.

Tear down the USB PAL.

Detaches the device, removes the ra8_usb event handler, deinits the underlying driver, clears stack callback state, marks the state as detached, and resets every endpoint slot.

Returns
ra8_err_t error code from ra8_usb_device_deinit.
Return values
k_ra8_okReleased cleanly.
k_ra8_err_invalid_statePAL was never initialized.
Precondition
IRQs masked or single-threaded shutdown context.
PAL was previously initialized (otherwise returns invalid_state).
Postcondition
s_state.initialized == false.
Subsequent EP calls return k_ra8_err_invalid_state.
Note
Not thread-safe.
See also
ra8_usb_pal_init
Since
0.1.0

Definition at line 344 of file ra8_usb_pal.c.

References internal_reset_eps(), k_ra8_err_invalid_state, k_ra8_usb_pal_state_detached, ra8_usb_attach_handler(), ra8_usb_device_attach(), ra8_usb_device_deinit(), and s_state.

◆ ra8_usb_pal_ep_open()

ra8_err_t ra8_usb_pal_ep_open ( uint8_t ep_addr,
ra8_usb_pal_ep_dir_t dir,
ra8_usb_pal_ep_type_t type,
uint16_t max_packet )
nodiscard

Open one endpoint and reserve a per-EP packet ring.

Open a non-control endpoint with a given type / direction / size.

Records direction, transfer type, and max packet size in the per-EP slot; resets the slot's queue cursors so subsequent ra8_usb_pal_ep_send / ra8_usb_pal_ep_recv start at slot 0.

Parameters
[in]ep_addrEndpoint address (1..k_ra8_usb_pal_ep_max).
[in]dirOUT or IN direction.
[in]typeControl / bulk / iso / intr transfer type.
[in]max_packetMaximum packet size; 1..k_ra8_usb_pal_xfer_max.
Returns
ra8_err_t error code.
Return values
k_ra8_okEndpoint opened.
k_ra8_err_invalid_statePAL not initialized.
k_ra8_err_invalid_argAddress, direction, type, or max_packet out of range.
Precondition
PAL has been initialized.
Endpoint is not currently opened (re-opens are allowed and reset state).
Postcondition
On success, the slot is opened and the per-EP ring is empty.
On error, no slot state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 434 of file ra8_usb_pal.c.

References ra8_usb_pal_ep_slot_t::count, ra8_usb_pal_ep_slot_t::dir, ra8_usb_pal_ep_slot_t::head, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_usb_pal_ep_addr_mask, k_ra8_usb_pal_ep_dir_in, k_ra8_usb_pal_ep_dir_out, k_ra8_usb_pal_ep_max, k_ra8_usb_pal_ep_type_intr, k_ra8_usb_pal_ring_slots, k_ra8_usb_pal_xfer_max, ra8_usb_pal_packet_t::len, ra8_usb_pal_ep_slot_t::max_packet, ra8_usb_pal_ep_slot_t::opened, priv_usb_pal_ep_out_of_range(), ra8_usb_pal_ep_slot_t::ring, s_state, ra8_usb_pal_ep_slot_t::tail, and ra8_usb_pal_ep_slot_t::type.

◆ ra8_usb_pal_ep_recv()

ra8_err_t ra8_usb_pal_ep_recv ( uint8_t ep_addr,
uint8_t * out_buf,
uint16_t * inout_len )
nodiscard

Pull the next packet, if any, from an open OUT endpoint.

Receive data from an OUT endpoint (host -> device).

Copies up to *inout_len bytes from the head of the per-EP ring into out_buf and updates *inout_len with the byte count actually written. When the ring is empty the call returns k_ra8_err_no_data so the stack can poll without blocking.

Parameters
[in]ep_addrEndpoint address (1..k_ra8_usb_pal_ep_max).
[out]out_bufDestination buffer.
[in,out]inout_lenOn entry: capacity of out_buf. On exit: bytes written.
Returns
ra8_err_t error code.
Return values
k_ra8_okPacket copied.
k_ra8_err_no_dataRing empty.
k_ra8_err_null_ptrout_buf or inout_len NULL.
k_ra8_err_invalid_statePAL not initialized or EP not opened.
k_ra8_err_invalid_argAddress out of range or capacity zero.
Precondition
PAL has been initialized.
Endpoint was opened via ra8_usb_pal_ep_open.
Postcondition
On success, the per-EP ring depth is decremented by one.
On error, no slot state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 563 of file ra8_usb_pal.c.

References ra8_usb_pal_ep_slot_t::count, ra8_usb_pal_packet_t::data, ra8_usb_pal_ep_slot_t::head, internal_copy_bytes(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_no_data, k_ra8_ok, k_ra8_usb_pal_ep_addr_mask, k_ra8_usb_pal_ep_max, k_ra8_usb_pal_ring_slots, ra8_usb_pal_packet_t::len, ra8_usb_pal_ep_slot_t::opened, priv_usb_pal_ep_out_of_range(), RA8_CHECK_NULL_PTR, ra8_usb_pal_ep_slot_t::ring, s_state, and s_tag.

◆ ra8_usb_pal_ep_send()

ra8_err_t ra8_usb_pal_ep_send ( uint8_t ep_addr,
const uint8_t * data,
uint16_t len )
nodiscard

Queue a packet for transmit on an open IN endpoint.

Submit data on an IN endpoint (device -> host).

Copies data[0..len-1] into the next free slot of the per-EP ring. Fires k_ra8_usb_pal_event_ep_in when an event handler is installed. len == 0 is allowed (zero-length packet); when len == 0 the data pointer may be NULL.

Parameters
[in]ep_addrEndpoint address (1..k_ra8_usb_pal_ep_max).
[in]dataPacket bytes; non-NULL when len > 0.
[in]lenPacket length in bytes (<= max_packet).
Returns
ra8_err_t error code.
Return values
k_ra8_okPacket queued.
k_ra8_err_invalid_statePAL not initialized or EP not opened.
k_ra8_err_null_ptrdata NULL with len > 0.
k_ra8_err_invalid_argAddress out of range or length above limit.
k_ra8_err_no_memPer-EP ring full; drain and retry.
Precondition
PAL has been initialized.
Endpoint was opened via ra8_usb_pal_ep_open.
Postcondition
On success, the per-EP ring depth is incremented by one.
On error, no slot state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 498 of file ra8_usb_pal.c.

References ra8_usb_pal_ep_slot_t::count, ra8_usb_pal_packet_t::data, internal_copy_bytes(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_no_mem, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_usb_pal_ep_addr_mask, k_ra8_usb_pal_ep_max, k_ra8_usb_pal_event_ep_in, k_ra8_usb_pal_ring_slots, k_ra8_usb_pal_xfer_max, ra8_usb_pal_packet_t::len, ra8_usb_pal_ep_slot_t::max_packet, ra8_usb_pal_ep_slot_t::opened, priv_usb_pal_ep_out_of_range(), ra8_usb_pal_ep_slot_t::ring, s_state, and ra8_usb_pal_ep_slot_t::tail.

Referenced by internal_usbcdc_write().

◆ ra8_usb_pal_get_state()

ra8_err_t ra8_usb_pal_get_state ( ra8_usb_pal_state_t * out_state)
nodiscard

Read the current PAL state machine.

Parameters
[out]out_stateReceives the state.
Returns
ra8_err_t error code.
Return values
k_ra8_okCopied.
k_ra8_err_null_ptrout_state was NULL.
k_ra8_err_invalid_statePAL not initialized.
Precondition
out_state is non-NULL.
PAL has been initialized.
Postcondition
No PAL state is modified.
Note
Thread safety: not thread-safe; the state can be updated from ra8_usb ISR context concurrently.
Since
0.1.0

Definition at line 397 of file ra8_usb_pal.c.

References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

◆ ra8_usb_pal_init()

ra8_err_t ra8_usb_pal_init ( ra8_usb_speed_t speed)
nodiscard

Bring up the USB PAL singleton at the requested speed.

Initialise the USB PAL on a specific controller speed.

Validates the speed, powers up the ra8_usb device-mode driver, resets every endpoint slot, and installs the internal event handler so the stack callback can fire.

Parameters
[in]speedFS or HS speed selector.
Returns
ra8_err_t error code.
Return values
k_ra8_okPAL ready, state = detached.
k_ra8_err_invalid_argspeed not FS or HS.
k_ra8_err_hw_init_failedra8_usb_device_init failed.
Precondition
ra8_mstp_init and ra8_pwr_init have been called.
IRQs masked or single-threaded init context.
Postcondition
On success, s_state.initialized == true and every EP slot is in the unopened state.
On failure, s_state.initialized == false and the underlying ra8_usb driver has been torn down.
Note
Not thread-safe; must run from boot init context.
See also
ra8_usb_pal_deinit
Since
0.1.0

Definition at line 299 of file ra8_usb_pal.c.

References internal_reset_eps(), internal_usb_event(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_pal_state_detached, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_log_error_val, ra8_log_info, ra8_usb_attach_handler(), ra8_usb_device_init(), s_state, and s_tag.

◆ ra8_usb_pal_set_event_handler()

ra8_err_t ra8_usb_pal_set_event_handler ( ra8_usb_pal_event_fn_t fn,
void * ctx )
nodiscard

Install a single event handler for bus and per-EP events.

Attach a single event handler for bus / endpoint events.

Replaces any previously installed callback. Pass fn == nullptr to detach. The callback is invoked from ra8_usb ISR/task context via internal_usb_event and from the per-EP send/recv hot path.

Parameters
[in]fnEvent callback, or NULL to detach.
[in]ctxOpaque context handed back to fn.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandler installed/cleared.
k_ra8_err_invalid_statePAL not initialized.
Precondition
PAL has been initialized.
fn is callable from ISR context if it is non-NULL.
Postcondition
s_state.event_fn == fn and s_state.event_ctx == ctx.
No other PAL state is mutated.
Note
Not thread-safe with respect to a concurrent event delivery.
Since
0.1.0

Definition at line 620 of file ra8_usb_pal.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

Variable Documentation

◆ s_state

ra8_usb_pal_state_inner_t s_state = {}
static

Definition at line 127 of file ra8_usb_pal.c.

◆ s_tag

const char* s_tag = "USBPAL"
static

Definition at line 72 of file ra8_usb_pal.c.