|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
USBX device-controller-driver bridge to ra8_usb – transfer dispatch. More...
#include <stdint.h>#include <string.h>#include "ra8_check.h"#include "ra8_elc_regs.h"#include "ra8_isr.h"#include "ra8_log.h"#include "ra8_usb_regs.h"#include "tx_api.h"#include "ux_api.h"#include "ux_dcd_ra8_usb.h"#include "ux_dcd_ra8_usb_internal.h"#include "ux_device_stack.h"#include "ux_system.h"#include "ux_utility.h"Go to the source code of this file.
Macros | |
| #define | UX_SOURCE_CODE |
Functions | |
| uint8_t | priv_ep_to_pipe (uint8_t ep_addr) |
| Map a USB EP number (1..9) into our PIPE table index. | |
| static unsigned int | internal_ep0_transfer (struct UX_SLAVE_TRANSFER_STRUCT *tr) |
| Drive an EP0 / DCP control transfer (data or status stage). | |
| static unsigned int | internal_wait_completion (struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe) |
| Block on the USBX transfer semaphore until the IRQ posts completion. | |
| static unsigned int | internal_submit_consume_orphan (struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe) |
| Deliver a held orphan OUT packet to a freshly submitted transfer. | |
| static uint32_t | internal_fifo_lock (void) |
| Enter a CFIFO critical section: mask interrupts. | |
| static void | internal_fifo_unlock (uint32_t primask) |
| Leave a CFIFO critical section: restore the interrupt mask. | |
| static unsigned int | internal_submit_in_pipe (struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe) |
| Stage the first chunk of an IN transfer (plus single-packet ZLP). | |
| static unsigned int | internal_submit_pipe (struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe, uint8_t ep_addr) |
| Submit the stashed IN/OUT transfer on a non-EP0 pipe. | |
| unsigned int | priv_transfer_request (struct UX_SLAVE_TRANSFER_STRUCT *tr) |
| USBX UX_DCD_TRANSFER_REQUEST dispatcher entry point. | |
Variables | |
| uint8_t | g_orphan_buf [k_ra8_usb_orphan_bytes] |
| One held OUT packet. | |
| uint16_t | g_orphan_len = 0U |
| Held byte count; 0 = empty. | |
| uint8_t | g_orphan_pipe = 0U |
| Pipe the held packet is on. | |
USBX device-controller-driver bridge to ra8_usb – transfer dispatch.
Task-context transfer submission: EP0 control transfers, bulk/interrupt IN/OUT staging, the orphan-OUT consume path, and the CFIFO critical section helpers.
Split out of ux_dcd_ra8_usb.c to keep each translation unit under the maintainability line cap; the cross-translation-unit contract lives in ux_dcd_ra8_usb_internal.h.
Definition in file ux_dcd_ra8_usb_xfer.c.
| #define UX_SOURCE_CODE |
Definition at line 22 of file ux_dcd_ra8_usb_xfer.c.
|
static |
Drive an EP0 / DCP control transfer (data or status stage).
Split the IN-data and zero-length status paths apart so the outer dispatcher's MC/DC inventory stays small.
| [in,out] | tr | USBX EP0 transfer request. |
| UX_SUCCESS | Bytes / CCPL accepted by ra8_usb. |
| UX_TRANSFER_ERROR | Underlying DCP call failed. |
Definition at line 105 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, k_ra8_ok, RA8_INTERNAL, ra8_usb_control_response(), and ra8_usb_dcp_in_data().
Referenced by priv_transfer_request().
|
static |
Enter a CFIFO critical section: mask interrupts.
The CFIFO port (CFIFOSEL.CURPIPE + the FIFO window) is a single shared resource. The class thread stages the first chunk of every bulk-IN transfer through it while the USB ISR walk drains bulk-OUT packets and stages IN continuations through the same port. An ISR preempting the thread mid-FIFO-write retargets CURPIPE under it and the remaining bytes land in the wrong pipe – framing stays intact, the payload is garbage (observed against macOS as FAT sectors reading back zeroed during sustained sequential reads). Masking interrupts for the short stage (FRDY wait on an empty bank plus a <= MPS FIFO write, microseconds) closes the race.
| 0 | Interrupts were enabled on entry. |
Definition at line 289 of file ux_dcd_ra8_usb_xfer.c.
References RA8_INTERNAL.
Referenced by internal_submit_in_pipe().
|
static |
Leave a CFIFO critical section: restore the interrupt mask.
Re-enables interrupts only when they were enabled at the matching internal_fifo_lock, so nesting inside an already-masked region stays masked.
| [in] | primask | PRIMASK snapshot from internal_fifo_lock. |
primask came from the matching internal_fifo_lock call. Definition at line 314 of file ux_dcd_ra8_usb_xfer.c.
References RA8_INTERNAL.
Referenced by internal_submit_in_pipe().
|
static |
Deliver a held orphan OUT packet to a freshly submitted transfer.
Called by internal_submit_pipe when g_orphan_len is non-zero for the target pipe. Copies the held packet (captured by internal_irq_drain_orphan_out) into the transfer buffer as packet one. If the held packet fills the request, or is itself a short (< MPS) packet, it ends the transfer – completed synchronously here, with the semaphore posted so the task-side wait returns at once. Otherwise the pipe is armed to BUF and internal_irq_complete_out streams the remainder from the held byte offset.
| [in,out] | tr | USBX transfer request, already stashed on the pipe. |
| [in] | pipe | Pipe index (1..max_pipes-1); equals g_orphan_pipe. |
| UX_SUCCESS | Held packet delivered (transfer complete or armed). |
| UX_TRANSFER_ERROR | Re-arm of the OUT pipe failed. |
Definition at line 234 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, g_orphan_buf, g_orphan_len, k_dcd_trace_kind_ouse, k_ra8_ok, memcpy(), priv_trace_event(), RA8_INTERNAL, and ra8_usb_rearm_out_pipe().
Referenced by internal_submit_pipe().
|
static |
Stage the first chunk of an IN transfer (plus single-packet ZLP).
IN endpoint path of internal_submit_pipe: USBX hands the DCD the whole transfer, but ra8_usb_queue_in moves at most one max-packet bank – so a transfer longer than MPS is streamed: this pushes the first packet (atomically against the ISR walk's shared CFIFO use, see internal_fifo_lock) and internal_irq_complete_in pushes each subsequent packet as the host drains the previous one (BEMP). A single-packet MPS-exact transfer gets its trailing ZLP staged into the second bank.
| [in,out] | tr | USBX transfer request, already stashed. |
| [in] | pipe | Pipe index the transfer is bound to. |
| UX_SUCCESS | First chunk (and any ZLP) queued. |
| UX_TRANSFER_ERROR | Bridge rejected the queue; stash cleared. |
Definition at line 348 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, internal_fifo_lock(), internal_fifo_unlock(), k_ra8_ok, RA8_INTERNAL, and ra8_usb_queue_in().
Referenced by internal_submit_pipe().
|
static |
Submit the stashed IN/OUT transfer on a non-EP0 pipe.
Extracted from priv_transfer_request to keep the dispatcher under the NASA P10 Rule 4 60-line cap. For IN endpoints (bit-7 set in ep_addr) we push the buffer via ra8_usb_queue_in and record the actual length; for OUT endpoints we move PIPECTR.PID from NAK to BUF via ra8_usb_rearm_out_pipe so the controller ACKs the first host OUT token. HUM Ch 36.2.27 PIPECTR.PID.
| [in,out] | tr | USBX transfer request, already validated and stashed. |
| [in] | pipe | Pipe index the transfer is bound to (1..max_pipes-1). |
| [in] | ep_addr | Endpoint address byte (bit-7 = direction). |
| UX_SUCCESS | Buffer queued (IN) or PIPECTR.PID == BUF (OUT). |
| UX_TRANSFER_ERROR | Bridge layer rejected the submission; g_dcd.pipes[pipe].xfer has been cleared. |
Definition at line 409 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, g_orphan_len, g_orphan_pipe, internal_submit_consume_orphan(), internal_submit_in_pipe(), k_ra8_ok, k_ra8_usb_ep_addr_dir_in_bit, and ra8_usb_rearm_out_pipe().
Referenced by priv_transfer_request().
|
static |
Block on the USBX transfer semaphore until the IRQ posts completion.
Mirrors the sync contract of ux_dcd_sim_slave_transfer_request: for non-EP0 transfers the DCD must wait on ux_slave_transfer_request_semaphore until the IRQ path sets completion_code and tx_semaphore_puts the semaphore. Returning UX_SUCCESS immediately would let class drivers observe actual_length=0 and treat it as a short-packet completion – loopback consumers then busy-spin on (n == 0).
| [in,out] | tr | USBX transfer request being awaited. |
| [in] | pipe | Pipe index used for g_diag accounting (2 == loopback). |
| UX_SUCCESS | IRQ posted a successful completion. |
| UX_TRANSFER_ERROR | Timeout / abort / IRQ-side error. |
Block on the USBX transfer semaphore until the IRQ posts completion.
See the canonical block immediately above this #ifndef for the full contract. Mirrored here so the doxy auditor can find a block immediately preceding the function definition (no preprocessor directive between the block and the signature).
| [in,out] | tr | USBX transfer request being awaited. |
| [in] | pipe | Pipe index used for g_diag accounting (2 == loopback). |
| UX_SUCCESS | IRQ posted a successful completion. |
| UX_TRANSFER_ERROR | Timeout / abort / IRQ-side error. |
Definition at line 181 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, g_diag, RA8_INTERNAL, TX_SUCCESS, and TX_WAIT_FOREVER.
Referenced by priv_transfer_request().
| uint8_t priv_ep_to_pipe | ( | uint8_t | ep_addr | ) |
Map a USB EP number (1..9) into our PIPE table index.
Map a USB EP number (1..9) into the PIPE table index.
| [in] | ep_addr | Endpoint address (with dir bit in 0x80). |
See implementation for details.
| 0 | Success or default value. |
Definition at line 66 of file ux_dcd_ra8_usb_xfer.c.
References k_ra8_usb_ep_addr_num_mask, and k_ux_dcd_ra8_usb_max_pipes.
Referenced by internal_endpoint_create(), internal_endpoint_destroy(), internal_endpoint_stall(), and priv_transfer_request().
| unsigned int priv_transfer_request | ( | struct UX_SLAVE_TRANSFER_STRUCT * | tr | ) |
USBX UX_DCD_TRANSFER_REQUEST dispatcher entry point.
Validates the incoming transfer request, maps the endpoint address to a pipe index, and dispatches to either internal_ep0_transfer (EP0 control) or stashes the request and submits an IN/OUT data transfer via internal_submit_pipe through the ra8_usb_* register layer. Under non-standalone builds the request is then awaited via internal_wait_completion so USBX class drivers see synchronous completion with non-zero actual_length.
| [in,out] | tr | USBX transfer request to submit. ux_slave_transfer_request_endpoint must point at a configured endpoint; data pointer and requested length describe the buffer. |
| UX_SUCCESS | Transfer submitted (and, in non-standalone builds, completed by the IRQ path). |
| UX_TRANSFER_ERROR | tr was null, endpoint was null, pipe was out of range, or the bridge layer rejected the submission. |
Definition at line 465 of file ux_dcd_ra8_usb_xfer.c.
References g_dcd, g_diag, internal_ep0_transfer(), internal_submit_pipe(), internal_wait_completion(), k_ra8_usb_ep_addr_dir_in_bit, k_ux_dcd_ra8_usb_max_pipes, and priv_ep_to_pipe().
Referenced by _ux_dcd_ra8_usb_function().
| uint8_t g_orphan_buf[k_ra8_usb_orphan_bytes] |
One held OUT packet.
One held no-receiver bulk-OUT packet.
Definition at line 40 of file ux_dcd_ra8_usb_xfer.c.
Referenced by internal_irq_drain_orphan_out(), and internal_submit_consume_orphan().
| uint16_t g_orphan_len = 0U |
Held byte count; 0 = empty.
Held orphan byte count; 0 = empty.
Definition at line 42 of file ux_dcd_ra8_usb_xfer.c.
Referenced by internal_endpoint_arm_out_pid(), internal_irq_drain_orphan_out(), internal_submit_consume_orphan(), and internal_submit_pipe().
| uint8_t g_orphan_pipe = 0U |
Pipe the held packet is on.
Pipe the held orphan packet is on.
Definition at line 44 of file ux_dcd_ra8_usb_xfer.c.
Referenced by internal_irq_drain_orphan_out(), and internal_submit_pipe().