ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb.c
Go to the documentation of this file.
1
53
54#include "ra8_usb.h"
55
56#include <stdint.h>
57
58#include "ra8_attributes.h"
59#include "ra8_check.h"
60#include "ra8_err.h"
61#include "ra8_hw_err.h"
62#include "ra8_mstp.h"
63#include "ra8_usb_internal.h"
64#include "ra8_usb_regs.h"
65
66static const char* s_tag = "USB";
67
68/* =============================================================================
69 * Tunables / sizing
70 * =============================================================================
71 */
72
90typedef enum : uint32_t {
92 /* Short-bound FRDY poll used by queue_out's post-BCLR DBLB-second-
93 * bank check. Must be tight (we're typically on the IRQ-time
94 * drain path) but big enough to absorb the few cycles between BCLR
95 * and the FIFO pointer flipping to the other bank when DBLB is on.
96 * 256 iters x ~3 cycles == sub-microsecond at 1 GHz. */
98 /* CFIFOSEL CURPIPE/ISEL readback settle bound (a handful of bus
99 * clocks; generous to stay fake-safe). */
102/* =============================================================================
103 * Internal helpers
104 * =============================================================================
105 */
106
111{
112 if (speed == k_ra8_usb_speed_fs) {
113 return ra8_usb_fs();
114 }
115 if (speed == k_ra8_usb_speed_hs) {
116 return ra8_usb_hs();
117 }
118 return nullptr;
119}
120
139
154void priv_rmw16(volatile uint16_t* reg, uint16_t set_mask, uint16_t clr_mask)
155{
156 const uint16_t old = *reg;
157 uint16_t new_val = (uint16_t)(old & (uint16_t)~clr_mask);
158 new_val = (uint16_t)(new_val | set_mask);
159 *reg = new_val;
160}
161
179bool priv_is_hs(volatile const r_usb_regs_t* reg)
180{
181 return reg == ra8_usb_hs();
182}
183
199void priv_select_cfifo(volatile r_usb_regs_t* reg, uint16_t pipe_num, bool is_in_dir)
200{
201 /* HUM Ch 36.2.7 / 37.2.8 CFIFOSEL p 1976 / 2071. The USBHS module
202 * (IP1) requires MBW=32 -- FSP wires `USB1_CFIFO_MBW = USB_MBW_32`
203 * unconditionally for this controller. With MBW=16 the SIE refuses
204 * to arm an IN response (BSTS reads 0 and PID stays effectively
205 * NAK on the wire even though DCPCTR.PID=BUF), and the host sees
206 * unending NAKs / "device descriptor read/N, error -110". The
207 * USBFS module (IP0) keeps MBW=16. */
208 uint16_t sel = (uint16_t)(pipe_num & k_ra8_fifosel_curpipe);
209 if (priv_is_hs(reg)) {
210 sel = (uint16_t)(sel | k_ra8_fifosel_mbw_32);
211 } else {
212 sel = (uint16_t)(sel | k_ra8_fifosel_mbw_16);
213 }
214 if (is_in_dir) {
215 sel = (uint16_t)(sel | k_ra8_fifosel_isel);
216 }
217 reg->CFIFOSEL = sel;
218 /* FSP (usb_cstd_chg_curpipe) polls the CURPIPE/ISEL readback until the
219 * window switch takes effect; without this a FIFO access issued right
220 * after the select can land on the previous pipe's buffer (observed on
221 * hardware as a bulk-OUT payload stuck with INBUFM set, never sent). */
222 const uint16_t key = (uint16_t)(sel & (uint16_t)(k_ra8_fifosel_curpipe | k_ra8_fifosel_isel));
223 for (uint32_t i = 0U; i < (uint32_t)k_ra8_usb_fifosel_settle_limit; ++i) {
224 const uint16_t now =
225 (uint16_t)(reg->CFIFOSEL & (uint16_t)(k_ra8_fifosel_curpipe | k_ra8_fifosel_isel));
226 if (now == key) {
227 return;
228 }
229 }
230}
231
252{
253 /* HUM Ch 36.2.8 "CFIFOCTR : CFIFO Port Control Register", p 1979.
254 * Loop bound is large (~10 ms ceiling at 1 GHz) because the DCP
255 * is single-buffered: between consecutive EP0 IN chunks FRDY stays
256 * low until the host actually pulls the previous chunk off the
257 * wire. See ra8_usb_internal_lim32_t for the rationale. */
258 for (uint32_t i = 0U; i < (uint32_t)k_ra8_usb_frdy_poll_limit; ++i) {
259 const bool frdy = ((reg->CFIFOCTR & k_ra8_fifoctr_frdy) != 0U);
260#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
261 /* Host MMIO fault seam, keyed on CFIFOCTR (the polled register). */
262 if (ra8_fake_mmio_wait_eval(&reg->CFIFOCTR, i, frdy)) {
263 return k_ra8_ok;
264 }
265#else
266 if (frdy) {
267 return k_ra8_ok;
268 }
269#endif
270 }
272}
273
289{
290 /* HUM Ch 36.2.21 "DCPCTR : DCP Control Register", p 1999 */
291 priv_rmw16(&reg->DCPCTR, pid, k_ra8_pid_mask);
292}
293
308void priv_pipe_pid(volatile r_usb_regs_t* reg, uint8_t pipe_num, ra8_usb_pid_t pid)
309{
310 /* HUM Ch 36.2.27 "PIPEnCTR : PIPE n Control Register", p 2005 */
311 const uint8_t idx = (uint8_t)(pipe_num - 1U);
312 priv_rmw16(&reg->PIPECTR[idx], pid, k_ra8_pid_mask);
313}
314
315/* =============================================================================
316 * Pipe-config word packing + quiesce (shared device/host helpers)
317 * =============================================================================
318 */
319
353uint16_t priv_pipebuf_word(uint8_t pipe_num, uint16_t max_packet)
354{
355 const uint16_t mps_blocks = (uint16_t)(((uint32_t)max_packet + (k_ra8_pipebuf_block_bytes - 1U)) /
357 const uint16_t blocks_per_pipe = (uint16_t)(mps_blocks * 2U);
358 const uint16_t bufsize_field = (uint16_t)(blocks_per_pipe - 1U);
359 const uint16_t bufnmb_field =
360 (uint16_t)(8U + (uint16_t)((uint16_t)(pipe_num - 1U) * blocks_per_pipe));
361 return (uint16_t)((bufsize_field << k_ra8_pipebuf_bufsize_shift) |
362 (bufnmb_field & k_ra8_pipebuf_bufnmb_mask));
363}
364
400uint16_t
401priv_pipecfg_word(uint8_t ep_addr, ra8_usb_ep_dir_t dir, ra8_usb_ep_type_t type, bool dblb_in)
402{
403 uint16_t cfg = (uint16_t)((uint16_t)ep_addr & k_ra8_pipecfg_epnum_mask);
404 if (dir == k_ra8_usb_ep_dir_in) {
405 cfg = (uint16_t)(cfg | k_ra8_pipecfg_dir_in);
406 }
407 if (type == k_ra8_usb_ep_type_bulk) {
408 cfg = (uint16_t)(cfg | k_ra8_pipecfg_type_bulk);
409 cfg = (uint16_t)(cfg | k_ra8_pipecfg_shtnak);
410 /* Device OUT (receive): double-buffer so the host's next packet lands
411 * in bank B while the ISR drains bank A. Single-banked OUT NAKs (and
412 * wedges) the host's next packet during the per-packet re-arm of a
413 * sustained multi-packet WRITE data phase. PIPEBUF already reserves
414 * 2*MPS, and internal_irq_complete_out drains every ready bank per
415 * ISR. Device IN stays single-banked (the free-bank handshake after
416 * an MPS-exact fill is unreliable -- see header). HUM Ch 36.2.24. */
417 if (dir == k_ra8_usb_ep_dir_out) {
418 cfg = (uint16_t)(cfg | k_ra8_pipecfg_dblb);
419 }
420 /* DBLB on bulk IN only when the caller asks (host-mode IN). */
421 if (dblb_in) {
422 if (dir == k_ra8_usb_ep_dir_in) {
423 cfg = (uint16_t)(cfg | k_ra8_pipecfg_dblb);
424 }
425 }
426 } else if (type == k_ra8_usb_ep_type_intr) {
427 cfg = (uint16_t)(cfg | k_ra8_pipecfg_type_intr);
428 } else {
429 cfg = (uint16_t)(cfg | k_ra8_pipecfg_type_iso);
430 }
431 return cfg;
432}
433
447void priv_pipe_quiesce(volatile r_usb_regs_t* reg, uint8_t pipe_num)
448{
449 const uint16_t pipe_bit = (uint16_t)(1U << pipe_num);
450 reg->BRDYENB = (uint16_t)(reg->BRDYENB & (uint16_t)~pipe_bit);
451 reg->NRDYENB = (uint16_t)(reg->NRDYENB & (uint16_t)~pipe_bit);
452 reg->BEMPENB = (uint16_t)(reg->BEMPENB & (uint16_t)~pipe_bit);
453 priv_pipe_pid(reg, pipe_num, k_ra8_pid_nak);
454}
455
456/* =============================================================================
457 * CFIFO byte mover (shared device/host data path)
458 * =============================================================================
459 */
460
470
489typedef uint32_t __attribute__((may_alias)) /* ATTR-OK: cppcheck 2.13 rejects the C23 spelling */
491
507static void
508internal_fifo_write_hs_tail(volatile r_usb_regs_t* reg, const uint8_t* data, uint16_t len)
509{
510 const uint16_t tail = (uint16_t)(len & 0x3U);
511 if (tail == 0U) {
512 return;
513 }
514 const uint16_t sel_save = reg->CFIFOSEL;
515 const uint16_t sel_base = (uint16_t)(sel_save & (uint16_t)~(uint16_t)k_ra8_fifosel_mbw_msk);
516 uint16_t offset = (uint16_t)(len & (uint16_t)~(uint16_t)0x3U);
517 /* For USBHS in little-endian mode, FSP writes the 16-bit residual
518 * halfword to CFIFOH (CFIFO base + 0x02) and the 8-bit residual
519 * byte to CFIFOHH (CFIFO base + 0x03), NOT to CFIFO itself. See
520 * FSP r_usb_reg_access.h: USB1_CFIFO16=USB_M1->CFIFOH and
521 * USB1_CFIFO8=USB_M1->CFIFOHH (in USB_CFG_LITTLE branch). The
522 * chip uses these address aliases to commit the trailing 0..3
523 * bytes when MBW is narrowed; a write to CFIFO at offset +0x00
524 * in MBW=16/8 mode is silently dropped on USBHS, leaving DTLN
525 * unchanged at 4N (verified empirically: 18-byte push showed
526 * DTLN=16 instead of 18, and Linux saw -EOVERFLOW). */
527 volatile uint16_t* const cfifoh = (volatile uint16_t*)((uintptr_t)&reg->CFIFO + 2U);
528 volatile uint8_t* const cfifohh = (volatile uint8_t*)((uintptr_t)&reg->CFIFO + 3U);
529 if ((tail & 0x2U) != 0U) {
530 reg->CFIFOSEL = (uint16_t)(sel_base | k_ra8_fifosel_mbw_16);
531 const uint16_t lo = (uint16_t)data[offset + 0U];
532 const uint16_t hi = (uint16_t)data[offset + 1U];
533 *cfifoh = (uint16_t)(lo | (uint16_t)(hi << k_ra8_usb_byte_bits));
534 offset = (uint16_t)(offset + 2U);
535 }
536 if ((tail & 0x1U) != 0U) {
537 reg->CFIFOSEL = (uint16_t)(sel_base | k_ra8_fifosel_mbw_8);
538 *cfifohh = data[offset];
539 }
540 reg->CFIFOSEL = sel_save;
541}
542
559static void
560internal_fifo_write_hs_head(volatile r_usb_regs_t* reg, const uint8_t* data, uint16_t len)
561{
562 volatile ra8_usb_cfifo32_t* const cfifo32 = (volatile ra8_usb_cfifo32_t*)(uintptr_t)&reg->CFIFO;
563 const uint16_t quads = (uint16_t)(len >> 2U);
564 for (uint16_t i = 0U; i < quads; ++i) {
565 const uint32_t b0 = (uint32_t)data[(4U * i) + 0U];
566 const uint32_t b1 = (uint32_t)data[(4U * i) + 1U];
567 const uint32_t b2 = (uint32_t)data[(4U * i) + 2U];
568 const uint32_t b3 = (uint32_t)data[(4U * i) + 3U];
569 *cfifo32 =
570 b0 | (b1 << k_ra8_usb_shift_b1) | (b2 << k_ra8_usb_shift_b2) | (b3 << k_ra8_usb_shift_b3);
571 }
572}
573
592void priv_fifo_write(volatile r_usb_regs_t* reg, const uint8_t* data, uint16_t len)
593{
594 /* HUM Ch 36.2.5 / 37.2.7 CFIFO p 1973 / 2070. CFIFO access width
595 * must match CFIFOSEL.MBW. USBHS = 32-bit, USBFS = 16-bit. */
596 if (priv_is_hs(reg)) {
597 internal_fifo_write_hs_head(reg, data, len);
598 internal_fifo_write_hs_tail(reg, data, len);
599 return;
600 }
601 /* USBFS / MBW=16 path. */
602 const uint16_t even = (uint16_t)(len >> 1U);
603 for (uint16_t i = 0U; i < even; ++i) {
604 const uint16_t lo = (uint16_t)data[(2U * i) + 0U];
605 const uint16_t hi = (uint16_t)data[(2U * i) + 1U];
606 reg->CFIFO = (uint16_t)(lo | (uint16_t)(hi << k_ra8_usb_byte_bits));
607 }
608 if ((len & 1U) != 0U) {
609 /* Trailing odd byte: switch to MBW=8 and write one byte. A 16-bit
610 * write here adds a phantom zero byte to DTLN and the host sees
611 * EOVERFLOW on every odd-length descriptor. Mirrors FSP
612 * hw_usb_write_fifo8 for USBFS. HUM Ch 36.2.6 CFIFOSEL.MBW. */
613 const uint16_t sel_save = reg->CFIFOSEL;
614 const uint16_t sel_8 =
615 (uint16_t)((sel_save & (uint16_t)~(uint16_t)k_ra8_fifosel_mbw_msk) | k_ra8_fifosel_mbw_8);
616 volatile uint8_t* const cfifo8 = (volatile uint8_t*)(uintptr_t)&reg->CFIFO;
617 reg->CFIFOSEL = sel_8;
618 *cfifo8 = data[len - 1U];
619 reg->CFIFOSEL = sel_save;
620 }
621}
622
639static void internal_fifo_read_hs_head(volatile r_usb_regs_t* reg, uint8_t* data, uint16_t len)
640{
641 volatile const ra8_usb_cfifo32_t* const cfifo32 =
642 (volatile ra8_usb_cfifo32_t*)(uintptr_t)&reg->CFIFO;
643 const uint16_t quads = (uint16_t)(len >> 2U);
644 for (uint16_t i = 0U; i < quads; ++i) {
645 const uint32_t word = *cfifo32;
646 data[(4U * i) + 0U] = (uint8_t)(word & k_ra8_usb_byte_mask);
647 data[(4U * i) + 1U] = (uint8_t)((word >> k_ra8_usb_shift_b1) & k_ra8_usb_byte_mask);
648 data[(4U * i) + 2U] = (uint8_t)((word >> k_ra8_usb_shift_b2) & k_ra8_usb_byte_mask);
649 data[(4U * i) + 3U] = (uint8_t)((word >> k_ra8_usb_shift_b3) & k_ra8_usb_byte_mask);
650 }
651}
652
669static void internal_fifo_read_hs_tail(volatile r_usb_regs_t* reg, uint8_t* data, uint16_t len)
670{
671 const uint16_t tail = (uint16_t)(len & 0x3U);
672 if (tail == 0U) {
673 return;
674 }
675 /* HUM Ch 37.2.7 CFIFO: at MBW=32 the FIFO read pointer only advances
676 * on 32-bit reads at CFIFO+0. Narrow CFIFOH/CFIFOHH reads at MBW=16/8
677 * do not advance the pointer reliably (a 3-byte bulk-OUT packet drains
678 * as bytes [0],[1],[0] when mixed). For the trailing 1..3 bytes of a
679 * non-quadword packet we keep MBW=32 and consume one final 32-bit
680 * word, extracting only the `tail` low-order bytes (the FIFO presents
681 * unused-byte slots as don't-care). One read, one pointer advance,
682 * no MBW transition. */
683 const uint32_t word = *(volatile ra8_usb_cfifo32_t*)(uintptr_t)&reg->CFIFO;
684 const uint16_t off_base = (uint16_t)(len & (uint16_t)~(uint16_t)0x3U);
685 const uint8_t bytes[4] = {
686 (uint8_t)(word & k_ra8_usb_byte_mask),
687 (uint8_t)((word >> k_ra8_usb_shift_b1) & k_ra8_usb_byte_mask),
688 (uint8_t)((word >> k_ra8_usb_shift_b2) & k_ra8_usb_byte_mask),
689 (uint8_t)((word >> k_ra8_usb_shift_b3) & k_ra8_usb_byte_mask),
690 };
691 for (uint16_t i = 0U; i < tail; ++i) {
692 data[off_base + i] = bytes[i];
693 }
694}
695
712void priv_fifo_read(volatile r_usb_regs_t* reg, uint8_t* data, uint16_t len)
713{
714 /* HUM Ch 37.2.7 "CFIFO : CFIFO Port Register" p 2070 */
715 if (priv_is_hs(reg)) {
716 internal_fifo_read_hs_head(reg, data, len);
717 internal_fifo_read_hs_tail(reg, data, len);
718 return;
719 }
720 /* USBFS / MBW=16 path. */
721 const uint16_t even = (uint16_t)(len >> 1U);
722 for (uint16_t i = 0U; i < even; ++i) {
723 const uint16_t word = reg->CFIFO;
724 data[(2U * i) + 0U] = (uint8_t)(word & k_ra8_usb_byte_mask);
725 data[(2U * i) + 1U] = (uint8_t)((word >> k_ra8_usb_byte_bits) & k_ra8_usb_byte_mask);
726 }
727 if ((len & 1U) != 0U) {
728 /* Trailing odd byte: switch to MBW=8 and read one byte so DTLN
729 * advances by exactly 1. Mirrors FSP hw_usb_read_fifo8 for USBFS. */
730 const uint16_t sel_save = reg->CFIFOSEL;
731 const uint16_t sel_8 =
732 (uint16_t)((sel_save & (uint16_t)~(uint16_t)k_ra8_fifosel_mbw_msk) | k_ra8_fifosel_mbw_8);
733 volatile const uint8_t* const cfifo8 = (volatile uint8_t*)(uintptr_t)&reg->CFIFO;
734 reg->CFIFOSEL = sel_8;
735 data[len - 1U] = *cfifo8;
736 reg->CFIFOSEL = sel_save;
737 }
738}
739
740/* =============================================================================
741 * Shared DCP chunk push (device DCP-IN + host control-write data path)
742 * =============================================================================
743 */
744
770ra8_err_t priv_dcp_push_chunk(volatile r_usb_regs_t* reg, const uint8_t* p, uint16_t n)
771{
772 const ra8_err_t ready = priv_wait_frdy(reg);
773 RA8_RETURN_ON_ERROR(ready, s_tag, "dcp_in_data: FRDY timeout (chunk)");
774 priv_fifo_write(reg, p, n);
775 /* HUM Ch 36.2.8 "CFIFOCTR : CFIFO Port Control Register", p 1979.
776 *
777 * 2026-05-20 attempt: FSP r_usb_plibusbip.c only sets BVAL on the
778 * short last chunk (n < MPS), letting hardware auto-flag full-MPS
779 * chunks. Tried that here; usb_cdc_echo dropped off the bus and
780 * the chip didn't enumerate. Our synchronous multi-chunk push (vs
781 * FSP's BRDY-IRQ-per-chunk) apparently requires the explicit BVAL
782 * pulse on every chunk to commit each one before the next FRDY
783 * poll. Keep the unconditional write. */
785 return k_ra8_ok;
786}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Bounded wait-flag primitives for RA8D2 HAL drivers.
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_mstp_t
Packed (reg << 8) | bit module-stop identifier.
@ k_ra8_mstp_usbfs
MSTPB11 USBFS0.
@ k_ra8_mstp_usbhs
MSTPB12 USBHS.
static void internal_fifo_read_hs_tail(volatile r_usb_regs_t *reg, uint8_t *data, uint16_t len)
HS-only: read trailing 1..3 bytes from CFIFOH / CFIFOHH aliases.
Definition ra8_usb.c:669
static void internal_fifo_write_hs_tail(volatile r_usb_regs_t *reg, const uint8_t *data, uint16_t len)
HS-only: write the residual 0-3 bytes after 32-bit chunks.
Definition ra8_usb.c:508
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.
Definition ra8_usb.c:592
static void internal_fifo_read_hs_head(volatile r_usb_regs_t *reg, uint8_t *data, uint16_t len)
HS-only: 32-bit CFIFO read loop for the head bytes.
Definition ra8_usb.c:639
ra8_usb_internal_lim32_t
32-bit driver-wide bounds (don't fit in uint16_t).
Definition ra8_usb.c:90
@ k_ra8_usb_fifosel_settle_limit
RA8 USB fifosel settle limit.
Definition ra8_usb.c:100
@ k_ra8_usb_frdy_poll_limit
Spin-loops before timeout.
Definition ra8_usb.c:91
@ k_ra8_usb_dblb_frdy_poll_limit
RA8 USB dblb frdy poll limit.
Definition ra8_usb.c:97
void priv_dcp_pid(volatile r_usb_regs_t *reg, ra8_usb_pid_t pid)
Set DCPCTR PID field to a specific value while preserving the rest of the register.
Definition ra8_usb.c:288
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.
Definition ra8_usb.c:154
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.
Definition ra8_usb.c:199
ra8_err_t priv_wait_frdy(volatile r_usb_regs_t *reg)
Spin until CFIFOCTR.FRDY asserts or a deadline elapses.
Definition ra8_usb.c:251
ra8_mstp_t priv_mstp(ra8_usb_speed_t speed)
Resolve the per-speed MSTP id.
Definition ra8_usb.c:135
volatile r_usb_regs_t * priv_pick(ra8_usb_speed_t speed)
Resolve the per-speed register pointer.
Definition ra8_usb.c:110
uint32_t ra8_usb_cfifo32_t
32-bit view of the CFIFO data port, permitted to alias the 16-bit CFIFO register lane.
Definition ra8_usb.c:490
bool priv_is_hs(volatile const r_usb_regs_t *reg)
Detect whether reg points at the USBHS (IP1) register block.
Definition ra8_usb.c:179
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 for FRDY, write FIFO, pulse BVAL.
Definition ra8_usb.c:770
uint16_t priv_pipebuf_word(uint8_t pipe_num, uint16_t max_packet)
Compute the PIPEBUF word for a bulk pipe (2*MPS region).
Definition ra8_usb.c:353
void priv_pipe_pid(volatile r_usb_regs_t *reg, uint8_t pipe_num, ra8_usb_pid_t pid)
Set PIPECTR[idx] PID field.
Definition ra8_usb.c:308
void priv_pipe_quiesce(volatile r_usb_regs_t *reg, uint8_t pipe_num)
Quiesce the pipe so PIPECFG/PIPEMAXP/PIPEPERI become writable.
Definition ra8_usb.c:447
void priv_fifo_read(volatile r_usb_regs_t *reg, uint8_t *data, uint16_t len)
Drain the CFIFO data port into a buffer.
Definition ra8_usb.c:712
ra8_usb_fifo_shift_t
Byte-shift constants for packing CFIFO writes.
Definition ra8_usb.c:465
@ k_ra8_usb_shift_b1
Shift for byte 1.
Definition ra8_usb.c:466
@ k_ra8_usb_shift_b2
Shift for byte 2.
Definition ra8_usb.c:467
@ k_ra8_usb_shift_b3
Shift for byte 3.
Definition ra8_usb.c:468
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.
Definition ra8_usb.c:401
static void internal_fifo_write_hs_head(volatile r_usb_regs_t *reg, const uint8_t *data, uint16_t len)
HS-only: 32-bit CFIFO write loop for the head bytes.
Definition ra8_usb.c:560
Native USB controller driver public API (device + host modes).
ra8_usb_ep_type_t
Transfer type for a non-control endpoint.
@ k_ra8_usb_ep_type_bulk
Bulk transfer.
@ k_ra8_usb_ep_type_intr
Interrupt transfer.
ra8_usb_ep_dir_t
Endpoint direction.
@ k_ra8_usb_ep_dir_in
Device -> host.
@ k_ra8_usb_ep_dir_out
Host -> device.
ra8_usb_speed_t
Selects which controller instance the call targets.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
@ k_ra8_usb_speed_fs
Full-Speed controller (USBFS @ 0x40250000).
Cross-TU surface for the ra8_usb driver split.
@ k_ra8_usb_byte_mask
Low byte of a 16-bit FIFO word.
@ k_ra8_usb_byte_bits
Bits per byte (shift constant).
USB Full-Speed + High-Speed controller layout for the Renesas RA8D2.
ra8_usb_pid_t
Response PID values written into the low two bits of DCPCTR / PIPECTR.
@ k_ra8_pid_nak
NAK response.
@ k_ra8_pid_mask
PID[1:0] field mask.
@ k_ra8_fifoctr_frdy
FIFO ready.
@ k_ra8_fifoctr_bval
Buffer valid.
@ k_ra8_pipebuf_block_bytes
Each buffer block is 64 bytes.
@ k_ra8_pipebuf_bufsize_shift
RA8 pipebuf bufsize shift.
@ k_ra8_pipebuf_bufnmb_mask
RA8 pipebuf bufnmb mask.
@ k_ra8_fifosel_mbw_msk
MBW field mask.
@ k_ra8_fifosel_mbw_32
32-bit FIFO access width.
@ k_ra8_fifosel_mbw_8
8-bit FIFO access width.
@ k_ra8_fifosel_isel
CFIFO direction (DCP only).
@ k_ra8_fifosel_mbw_16
16-bit FIFO access width.
@ k_ra8_fifosel_curpipe
Current pipe select [3:0].
static volatile r_usb_regs_t * ra8_usb_hs(void)
Get pointer to the USB HS controller register block.
@ k_ra8_pipecfg_epnum_mask
Endpoint number [3:0].
@ k_ra8_pipecfg_dir_in
1 = IN, 0 = OUT (peri).
@ k_ra8_pipecfg_type_intr
Type = interrupt.
@ k_ra8_pipecfg_dblb
Double-buffer mode.
@ k_ra8_pipecfg_shtnak
Auto NAK on short pkt.
@ k_ra8_pipecfg_type_bulk
Type = bulk.
@ k_ra8_pipecfg_type_iso
Type = isochronous.
static volatile r_usb_regs_t * ra8_usb_fs(void)
Compile-time offset and size insurance for r_usb_regs_t.
USB FS / HS register window (device-mode subset).
volatile uint16_t NRDYENB
+0x038 NRDY Interrupt Enable.
volatile uint16_t DCPCTR
+0x060 DCP Control.
volatile uint16_t CFIFOCTR
+0x022 Control FIFO control.
volatile uint16_t CFIFOSEL
+0x020 Control FIFO select.
volatile uint16_t PIPECTR[k_ra8_usb_pipectr_count]
+0x070 PIPE1..9 ctrl.
volatile uint16_t CFIFO
+0x014 Control FIFO data port.
volatile uint16_t BRDYENB
+0x036 BRDY Interrupt Enable.
volatile uint16_t BEMPENB
+0x03A BEMP Interrupt Enable.