read/write packet enhancement, merge 16-bit and 32-bit together

This commit is contained in:
hathach 2024-08-01 23:08:12 +07:00
parent af8609e96e
commit e180d915c6
No known key found for this signature in database
GPG Key ID: 26FAB84F615C3C52
2 changed files with 64 additions and 107 deletions

View File

@ -825,121 +825,76 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
ep_write(ep_idx, ep_reg);
}
#ifdef FSDEV_BUS_32BIT
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) {
const uint8_t *src8 = src;
volatile uint32_t *pma32 = (volatile uint32_t *)(USB_PMAADDR + dst);
for (uint32_t n = wNBytes / 4; n > 0; --n) {
*pma32++ = tu_unaligned_read32(src8);
src8 += 4;
}
uint16_t odd = wNBytes & 0x03;
if (odd) {
uint32_t wrVal = *src8;
odd--;
if (odd) {
wrVal |= *++src8 << 8;
odd--;
if (odd) {
wrVal |= *++src8 << 16;
}
}
*pma32 = wrVal;
}
return true;
}
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) {
uint8_t *dst8 = dst;
volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src);
for (uint32_t n = wNBytes / 4; n > 0; --n) {
tu_unaligned_write32(dst8, *src32++);
dst8 += 4;
}
uint16_t odd = wNBytes & 0x03;
if (odd) {
uint32_t rdVal = *src32;
*dst8 = tu_u32_byte0(rdVal);
odd--;
if (odd) {
*++dst8 = tu_u32_byte1(rdVal);
odd--;
if (odd) {
*++dst8 = tu_u32_byte2(rdVal);
}
}
}
return true;
}
#else
// Packet buffer access can only be 8- or 16-bit.
/**
* @brief Copy a buffer from user memory area to packet memory area (PMA).
* This uses un-aligned for user memory and 16-bit access for packet memory.
* @param dst, byte address in PMA; must be 16-bit aligned
* @param src pointer to user memory area.
* @param wPMABufAddr address into PMA.
* @param nbytes no. of bytes to be copied.
* @retval None
*/
// Write to packet memory area (PMA) from user memory
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
uint32_t n16 = (uint32_t)nbytes >> 1U;
const uint8_t *src8 = src;
fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * dst);
enum { BUS_SIZE = sizeof(fsdev_bus_t) };
uint32_t n_write = nbytes / BUS_SIZE;
while (n16--) {
pma16->u16 = tu_unaligned_read16(src8);
src8 += 2;
pma16++;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst);
const uint8_t *src8 = src;
while (n_write--) {
#ifdef FSDEV_BUS_32BIT
pma_buf->value = tu_unaligned_read32(src8);
#else
pma_buf->value = tu_unaligned_read16(src8);
#endif
src8 += BUS_SIZE;
pma_buf++;
}
if (nbytes & 0x01) {
pma16->u16 = (uint16_t) *src8;
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = 0;
for(uint16_t i = 0; i < odd; i++) {
temp |= *src8++ << (i * 8);
}
pma_buf->value = temp;
}
return true;
}
/**
* @brief Copy a buffer from packet memory area (PMA) to user memory area.
* Uses unaligned for system memory and 16-bit access of packet memory
* @param nbytes no. of bytes to be copied.
* @retval None
*/
// Read from packet memory area (PMA) to user memory.
// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
// - Uses unaligned for RAM (since M0 cannot access unaligned address)
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
uint32_t n16 = (uint32_t)nbytes >> 1U;
fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * src);
enum { BUS_SIZE = sizeof(fsdev_bus_t) };
uint32_t n_write = nbytes / BUS_SIZE;
fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src);
uint8_t *dst8 = (uint8_t *)dst;
while (n16--) {
uint16_t temp16 = pma16->u16;
tu_unaligned_write16(dst8, temp16);
dst8 += 2;
pma16++;
while (n_write--) {
fsdev_bus_t temp = pma_buf->value;
#ifdef FSDEV_BUS_32BIT
tu_unaligned_write32(dst8, temp);
#else
tu_unaligned_write16(dst8, temp);
#endif
dst8 += BUS_SIZE;
pma_buf++;
}
if (nbytes & 0x01) {
*dst8++ = tu_u16_low(pma16->u16);
// odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
uint16_t odd = nbytes & (BUS_SIZE - 1);
if (odd) {
fsdev_bus_t temp = pma_buf->value;
while (odd--) {
*dst8++ = (uint8_t) (temp & 0xfful);
temp >>= 8;
}
}
return true;
}
#endif
/**
* @brief Copy from FIFO to packet memory area (PMA).
* Uses byte-access of system memory and 16-bit access of packet memory

View File

@ -1,9 +1,8 @@
/*
* The MIT License (MIT)
*
* Copyright(c) 2016 STMicroelectronics
* Copyright(c) N Conrad
* Copyright (c) 2024, hathach (tinyusb.org)
* Copyright(c) 2024, hathach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef TUSB_FSDEV_TYPE_H
@ -62,6 +62,13 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b
#define pma_aligned
#endif
// The fsdev_bus_t type can be used for both register and PMA access necessities
#ifdef FSDEV_BUS_32BIT
typedef uint32_t fsdev_bus_t;
#else
typedef uint16_t fsdev_bus_t;
#endif
//--------------------------------------------------------------------+
// BTable Typedef
//--------------------------------------------------------------------+
@ -95,8 +102,10 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE
#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE))
typedef struct {
volatile pma_aligned uint16_t u16;
} fsdev_pma16_t;
volatile pma_aligned fsdev_bus_t value;
} fsdev_pma_buf_t;
#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE*(_addr)))
//--------------------------------------------------------------------+
// Registers Typedef
@ -105,13 +114,6 @@ typedef struct {
// volatile 32-bit aligned
#define _va32 volatile TU_ATTR_ALIGNED(4)
// The fsdev_bus_t type can be used for both register and PMA access necessities
#ifdef FSDEV_BUS_32BIT
typedef uint32_t fsdev_bus_t;
#else
typedef uint16_t fsdev_bus_t;
#endif
typedef struct {
struct {
_va32 fsdev_bus_t reg;