Implement dcd_edpt_iso_xfer() for dcd_stm32_fsdev

Implemented a special copy strategy to copy directly from the FIFO. This
function, however, is untested and should be regarded as unreliable
until somebody was able to test it
This commit is contained in:
Reinhard Panhuber 2021-02-17 20:46:31 +01:00
parent c87357c025
commit 2d7b61972c
1 changed files with 144 additions and 4 deletions

View File

@ -102,6 +102,7 @@
*/
#include "tusb_option.h"
#include "common/tusb_fifo.h"
#if defined(STM32F102x6) || defined(STM32F102xB) || \
defined(STM32F103x6) || defined(STM32F103xB) || \
@ -165,6 +166,7 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne
typedef struct
{
uint8_t * buffer;
tu_fifo_t * ff;
uint16_t total_len;
uint16_t queued_len;
uint16_t pma_ptr;
@ -195,7 +197,9 @@ static void dcd_pma_alloc_reset(void);
static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length);
static void dcd_pma_free(uint8_t ep_addr);
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes);
static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes);
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes);
static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes);
// Using a function due to better type checks
// This seems better than having to do type casts everywhere else
@ -476,8 +480,16 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
if (count != 0U)
{
dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]),
*pcd_ep_rx_address_ptr(USB,EPindex), count);
if (xfer->ff)
{
dcd_read_packet_memory_ff(xfer->ff, *pcd_ep_rx_address_ptr(USB,EPindex), count);
}
else
{
dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]),
*pcd_ep_rx_address_ptr(USB,EPindex), count);
}
xfer->queued_len = (uint16_t)(xfer->queued_len + count);
}
@ -804,7 +816,14 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
len = xfer->max_packet_size;
}
uint16_t oldAddr = *pcd_ep_tx_address_ptr(USB,ep_ix);
dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len);
if (xfer->ff)
{
dcd_write_packet_memory_ff(xfer->ff, oldAddr, len);
}
else
{
dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len);
}
xfer->queued_len = (uint16_t)(xfer->queued_len + len);
pcd_set_ep_tx_cnt(USB,ep_ix,len);
@ -821,6 +840,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir);
xfer->buffer = buffer;
xfer->ff = NULL;
xfer->total_len = total_bytes;
xfer->queued_len = 0;
@ -847,6 +867,37 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
return true;
}
bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
{
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir);
xfer->buffer = NULL;
xfer->ff = ff;
xfer->total_len = total_bytes;
xfer->queued_len = 0;
if ( dir == TUSB_DIR_OUT )
{
if(total_bytes > xfer->max_packet_size)
{
pcd_set_ep_rx_cnt(USB,epnum,xfer->max_packet_size);
} else {
pcd_set_ep_rx_cnt(USB,epnum,total_bytes);
}
pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID);
}
else // IN
{
dcd_transmit_packet(xfer,epnum);
}
return true;
}
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
{
(void)rhport;
@ -921,7 +972,52 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
}
/**
* @brief Copy a buffer from user memory area to packet memory area (PMA).
* @brief Copy from FIFO to packet memory area (PMA).
* Uses byte-access of system memory and 16-bit access of packet memory
* @param wNBytes no. of bytes to be copied.
* @retval None
*/
// THIS FUNCTION IS UNTESTED
static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes)
{
// Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
// Check for first linear part
void *__restrict src;
uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO
TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA
tu_fifo_advance_read_pointer(ff, len);
// Check for wrapped part
if (len < wNBytes)
{
// Get remaining wrapped length
uint16_t len2 = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes - len);
TU_VERIFY(len2);
// Update destination pointer
dst += len;
// Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split
if (len % 2) // If len is uneven there is a byte left to copy
{
// Since PMA can accessed only 16 bit-wise we copy the last byte again
tu_fifo_backward_read_pointer(ff, 1); // Move one byte back and copy two bytes for the PMA
pma[PMA_STRIDE*(dst>>1)] = tu_fifo_read_n(ff, 2); // Since EP FIFOs must be of item size 1 this is safe to do
dst++;
len2--;
}
TU_VERIFY(dcd_write_packet_memory(dst, src, len2));
tu_fifo_advance_write_pointer(ff, len2);
}
return true;
}
/**
* @brief Copy a buffer from packet memory area (PMA) to user memory area.
* Uses byte-access of system memory and 16-bit access of packet memory
* @param wNBytes no. of bytes to be copied.
* @retval None
@ -955,5 +1051,49 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN
return true;
}
/**
* @brief Copy a buffer from user packet memory area (PMA) to FIFO.
* Uses byte-access of system memory and 16-bit access of packet memory
* @param wNBytes no. of bytes to be copied.
* @retval None
*/
// THIS FUNCTION IS UNTESTED
static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes)
{
// Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
// Check for first linear part
void *__restrict dst;
uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes);
TU_VERIFY(len && dcd_read_packet_memory(dst, src, len));
tu_fifo_advance_write_pointer(ff, len);
// Check for wrapped part
if (len < wNBytes)
{
// Get remaining wrapped length
uint16_t len2 = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes - len);
TU_VERIFY(len2);
// Update source pointer
src += len;
// Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split
if (len % 2) // If len is uneven there is a byte left to copy
{
uint32_t temp = pma[PMA_STRIDE*(src>>1)];
*((uint8_t *)dst++) = ((temp >> 8) & 0xFF);
src++;
len2--;
}
TU_VERIFY(dcd_read_packet_memory(dst, src, len2));
tu_fifo_advance_write_pointer(ff, len2);
}
return true;
}
#endif