summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-01-03 12:49:01 +0700
committerhathach <[email protected]>2026-01-03 15:06:54 +0700
commite158a3dd38fccd99169a3e5b8cecf7a1ac45915e (patch)
treea69d34c82bfac42f0a9ab04821a0d7e9216d12ea /src
parentc87f0db45978b6b1f11f151bf5c061b926dba245 (diff)
hwfifo support custom write/read
rusb use custom write enable all hil test for ra4m1
Diffstat (limited to 'src')
-rw-r--r--src/common/tusb_fifo.c45
-rw-r--r--src/portable/renesas/rusb2/dcd_rusb2.c226
-rw-r--r--src/tusb_option.h9
3 files changed, 196 insertions, 84 deletions
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index e34494c84..f6963a98d 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -121,6 +121,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) {
#define HWFIFO_ADDR_NEXT(_const, _hwfifo)
#endif
+#ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE
static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) {
#if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4
if (data_stride == 4) {
@@ -134,6 +135,28 @@ static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_st
#endif
}
+// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode
+void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) {
+ // Write full available 16/32 bit words to dest
+ const uint8_t data_stride = access_mode->data_stride;
+ while (len >= data_stride) {
+ stride_write(hwfifo, src, data_stride);
+ src += data_stride;
+ len -= data_stride;
+
+ HWFIFO_ADDR_NEXT(, hwfifo);
+ }
+
+ // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit
+ if (len > 0) {
+ uint32_t tmp = 0u;
+ memcpy(&tmp, src, len);
+ stride_write(hwfifo, &tmp, data_stride);
+ }
+}
+ #endif
+
+ #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ
static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) {
#if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4
if (data_stride == 4) {
@@ -165,26 +188,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co
memcpy(dest, &tmp, len);
}
}
-
-// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode
-void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) {
- // Write full available 16/32 bit words to dest
- const uint8_t data_stride = access_mode->data_stride;
- while (len >= data_stride) {
- stride_write(hwfifo, src, data_stride);
- src += data_stride;
- len -= data_stride;
-
- HWFIFO_ADDR_NEXT(, hwfifo);
- }
-
- // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit
- if (len > 0) {
- uint32_t tmp = 0u;
- memcpy(&tmp, src, len);
- stride_write(hwfifo, &tmp, data_stride);
- }
-}
+ #endif
static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr,
const tu_hwfifo_access_t *access_mode) {
@@ -390,6 +394,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui
} else
#endif
{
+ (void)access_mode;
ff_pull_n(f, p_buffer, n, rd_ptr);
}
diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c
index 6c6406dcf..f8fc7a643 100644
--- a/src/portable/renesas/rusb2/dcd_rusb2.c
+++ b/src/portable/renesas/rusb2/dcd_rusb2.c
@@ -57,6 +57,10 @@ enum {
PIPE_COUNT = 10,
};
+enum {
+ FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0)
+};
+
typedef struct {
void *buf; /* the start address of a transfer data buffer */
uint16_t length; /* the number of bytes in the buffer */
@@ -163,7 +167,8 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) {
//--------------------------------------------------------------------+
// Pipe FIFO
//--------------------------------------------------------------------+
-#if 0
+#define USE_HWFIFO 1
+ #if !USE_HWFIFO
// Write data buffer --> hw fifo
static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len)
{
@@ -172,27 +177,48 @@ static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo
volatile uint16_t *ff16;
volatile uint8_t *ff8;
+ const uint8_t *buf8 = (const uint8_t *)buf;
+
// Highspeed FIFO is 32-bit
if ( rusb2_is_highspeed_reg(rusb) ) {
// TODO 32-bit access for better performance
+ volatile uint32_t *ff32 = (volatile uint32_t *)fifo;
ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2);
ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3);
- }else {
- ff16 = (volatile uint16_t*) fifo;
- ff8 = ((volatile uint8_t*) fifo);
- }
- uint8_t const* buf8 = (uint8_t const*) buf;
+ while (len >= 4) {
+ *ff32 = tu_unaligned_read32(buf8);
+ buf8 += 4;
+ len -= 4;
+ }
- while (len >= 2) {
- *ff16 = tu_unaligned_read16(buf8);
- buf8 += 2;
- len -= 2;
- }
+ if (len >= 2) {
+ // switch to 16-bit access
+ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
+ (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
+ *ff16 = tu_unaligned_read16(buf8);
+ buf8 += 2;
+ len -= 2;
+ }
- if (len > 0) {
- *ff8 = *buf8;
- ++buf8;
+ if (len > 0) {
+ *ff8 = *buf8;
+ ++buf8;
+ }
+ } else {
+ ff16 = (volatile uint16_t*) fifo;
+ ff8 = ((volatile uint8_t *)fifo);
+
+ while (len >= 2) {
+ *ff16 = tu_unaligned_read16(buf8);
+ buf8 += 2;
+ len -= 2;
+ }
+
+ if (len > 0) {
+ *ff8 = *buf8;
+ ++buf8;
+ }
}
}
@@ -255,6 +281,66 @@ static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *
}
#endif
+static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) {
+ volatile uint16_t *fifo_sel;
+ if (hwfifo == (uintptr_t)&rusb->CFIFO) {
+ fifo_sel = &rusb->CFIFOSEL;
+ } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) {
+ fifo_sel = &rusb->D0FIFOSEL;
+ } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) {
+ fifo_sel = &rusb->D1FIFOSEL;
+ } else {
+ return;
+ }
+
+ *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw;
+}
+
+// write to hwfifo from buffer with access mode
+void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) {
+ rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param;
+ const uint8_t *buf8 = (const uint8_t *)src;
+
+ volatile uint16_t *ff16;
+ volatile uint8_t *ff8;
+ const bool is_highspeed = rusb2_is_highspeed_reg(rusb);
+ if (is_highspeed) {
+ ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2);
+ ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3);
+ } else {
+ ff16 = (volatile uint16_t *)hwfifo;
+ ff8 = ((volatile uint8_t *)hwfifo);
+ }
+
+ // 32-bit access for highspeed
+ if (is_highspeed) {
+ volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo;
+ while (len >= 4) {
+ *ff32 = tu_unaligned_read32(buf8);
+ buf8 += 4;
+ len -= 4;
+ }
+
+ if (len >= 2) {
+ // switch to 16-bit access
+ hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT);
+ }
+ }
+
+ // 16-bit access
+ while (len >= 2) {
+ *ff16 = tu_unaligned_read16(buf8);
+ buf8 += 2;
+ len -= 2;
+ }
+
+ // 8-bit access does not need to change MBW
+ if (len > 0) {
+ *ff8 = *buf8;
+ ++buf8;
+ }
+}
+
//--------------------------------------------------------------------+
// Pipe Transfer
//--------------------------------------------------------------------+
@@ -273,13 +359,12 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) {
void *buf = pipe->buf;
if (len) {
+ tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u),
+ .param = (uintptr_t)rusb};
if (pipe->ff) {
- // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len);
- tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len);
+ tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode);
} else {
- // pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len);
- // TODO check highspeed for 32-bit access
- tu_hwfifo_write(&rusb->CFIFO, buf, len);
+ tu_hwfifo_write(&rusb->CFIFO, buf, len, &access_mode);
pipe->buf = (uint8_t *)buf + len;
}
}
@@ -302,12 +387,13 @@ static bool pipe0_xfer_out(rusb2_reg_t *rusb) {
void *buf = pipe->buf;
if (len) {
+ tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u),
+ .param = (uintptr_t)rusb};
+
if (pipe->ff) {
- // pipe_read_packet_ff(rusb, (tu_fifo_t *)buf, (volatile void *)&rusb->CFIFO, len);
- tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len);
+ tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode);
} else {
- // pipe_read_packet(rusb, buf, (volatile void *)&rusb->CFIFO, len);
- tu_hwfifo_read(&rusb->CFIFO, buf, len);
+ tu_hwfifo_read(&rusb->CFIFO, buf, len, &access_mode);
pipe->buf = (uint8_t *)buf + len;
}
}
@@ -335,21 +421,27 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
return true;
}
- rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- const uint16_t mps = edpt_max_packet_size(rusb, num);
+ const uint16_t fifo_sel = num | FIFOSEL_BIGEND;
+ const bool is_highspeed = rusb2_is_highspeed_reg(rusb);
+ if (is_highspeed) {
+ rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_32BIT;
+ } else {
+ rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_16BIT;
+ }
+
+ const uint16_t mps = edpt_max_packet_size(rusb, num);
pipe_wait_for_ready(rusb, num);
- const uint16_t len = tu_min16(rem, mps);
- void *buf = pipe->buf;
+ uint16_t len = tu_min16(rem, mps);
+ void *buf = pipe->buf;
if (len) {
+ tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u),
+ .param = (uintptr_t)rusb};
if (pipe->ff) {
- // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
- tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len);
+ tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode);
} else {
- // pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
- // TODO check highspeed for 32-bit access
- tu_hwfifo_write(&rusb->D0FIFO, buf, len);
- pipe->buf = (uint8_t*)buf + len;
+ tu_hwfifo_write(&rusb->D0FIFO, buf, len, &access_mode);
+ pipe->buf = (uint8_t *)buf + len;
}
}
@@ -370,7 +462,14 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
pipe_state_t *pipe = &_dcd.pipe[num];
const uint16_t rem = pipe->remaining;
- rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT;
+ uint16_t fifo_sel = num | FIFOSEL_BIGEND;
+ if (rusb2_is_highspeed_reg(rusb)) {
+ fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT;
+ } else {
+ fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT;
+ }
+ rusb->D0FIFOSEL = fifo_sel;
+
const uint16_t mps = edpt_max_packet_size(rusb, num);
pipe_wait_for_ready(rusb, num);
@@ -379,13 +478,13 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
void *buf = pipe->buf;
if (len) {
+ tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u),
+ .param = (uintptr_t)rusb};
if (pipe->ff) {
- // pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
- tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len);
+ tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode);
} else {
- // pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
- tu_hwfifo_read(&rusb->D0FIFO, buf, len);
- pipe->buf = (uint8_t*)buf + len;
+ tu_hwfifo_read(&rusb->D0FIFO, buf, len, &access_mode);
+ pipe->buf = (uint8_t *)buf + len;
}
}
@@ -438,28 +537,33 @@ static void process_status_completion(uint8_t rhport)
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
}
-static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
-{
+static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer,
+ uint16_t total_bytes) {
+ uint16_t fifo_sel = FIFOSEL_BIGEND;
+ if (rusb2_is_highspeed_reg(rusb)) {
+ fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT;
+ } else {
+ fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT;
+ }
+
/* configure fifo direction and access unit settings */
if (ep_addr != 0) {
- /* IN, 2 bytes */
- rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
- (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {}
+ /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | fifo_sel;
+ while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {}
} else {
/* OUT, 2 bytes */
- rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT;
- while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {}
+ rusb->CFIFOSEL = fifo_sel;
+ while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {}
}
pipe_state_t *pipe = &_dcd.pipe[0];
- pipe->ff = buffer_type;
- pipe->length = total_bytes;
- pipe->remaining = total_bytes;
+ pipe->ff = buffer_type;
+ pipe->length = total_bytes;
+ pipe->remaining = total_bytes;
- if ( total_bytes ) {
+ if (total_bytes) {
pipe->buf = buffer;
- if ( ep_addr ) {
+ if (ep_addr) {
/* IN */
TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
pipe0_xfer_in(rusb);
@@ -631,18 +735,20 @@ static void process_set_address(uint8_t rhport)
{
rusb2_reg_t* rusb = RUSB2_REG(rhport);
const uint16_t addr = rusb->USBADDR_b.USBADDR;
- if (!addr) return;
+ if (!addr) {
+ return;
+ }
const tusb_control_request_t setup_packet = {
#if defined(__CCRX__)
.bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */
-#else
- .bmRequestType = 0,
-#endif
- .bRequest = TUSB_REQ_SET_ADDRESS,
- .wValue = addr,
- .wIndex = 0,
- .wLength = 0,
+ #else
+ .bmRequestType = 0,
+ #endif
+ .bRequest = TUSB_REQ_SET_ADDRESS,
+ .wValue = addr,
+ .wIndex = 0,
+ .wLength = 0,
};
dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true);
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 8e147707a..0abae6116 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -375,10 +375,11 @@
//------------ RUSB2 --------------//
#if defined(TUP_USBIP_RUSB2)
- #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
- #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data
- #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // support odd byte access
- #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0
+ #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
+ #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 + (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed
+ #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0
+ #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write
+ // odd byte with byte access
#endif
//--------------------------------------------------------------------