mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-15 12:39:50 +00:00
Refactor edpt_xfer(), support double buffering in dcd_pma_alloc().
This commit is contained in:
parent
68b973aa9f
commit
bf3e9b8653
@ -151,9 +151,7 @@ typedef struct
|
||||
tu_fifo_t * ff;
|
||||
uint16_t total_len;
|
||||
uint16_t queued_len;
|
||||
uint16_t pma_ptr;
|
||||
uint16_t max_packet_size;
|
||||
uint16_t pma_alloc_size;
|
||||
uint8_t ep_idx; // index for USB_EPnR register
|
||||
} xfer_ctl_t;
|
||||
|
||||
@ -180,12 +178,12 @@ static uint8_t remoteWakeCountdown; // When wake is requested
|
||||
// into the stack.
|
||||
static void dcd_handle_bus_reset(void);
|
||||
static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix);
|
||||
static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr);
|
||||
static void dcd_ep_ctr_handler(void);
|
||||
|
||||
// PMA allocation/access
|
||||
static uint16_t ep_buf_ptr; ///< Points to first free memory location
|
||||
static void dcd_pma_alloc_reset(void);
|
||||
static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length);
|
||||
static uint32_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length, bool dbuf);
|
||||
static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type);
|
||||
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes);
|
||||
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes);
|
||||
@ -491,7 +489,9 @@ static void dcd_handle_bus_reset(void)
|
||||
ep_alloc_status[i].allocated[1] = false;
|
||||
}
|
||||
|
||||
dcd_pma_alloc_reset();
|
||||
// Reset PMA allocation
|
||||
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT;
|
||||
|
||||
dcd_edpt_open (0, &ep0OUT_desc);
|
||||
dcd_edpt_open (0, &ep0IN_desc);
|
||||
|
||||
@ -760,40 +760,15 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
|
||||
}
|
||||
}
|
||||
|
||||
static void dcd_pma_alloc_reset(void)
|
||||
{
|
||||
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each)
|
||||
//TU_LOG2("dcd_pma_alloc_reset()\r\n");
|
||||
for(uint32_t i=0; i<MAX_EP_COUNT; i++)
|
||||
{
|
||||
xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_ptr = 0U;
|
||||
xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_ptr = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Allocate a section of PMA
|
||||
*
|
||||
* If the EP number has already been allocated, and the new allocation
|
||||
* is larger than the old allocation, then this will fail with a TU_ASSERT.
|
||||
* (This is done to simplify the code. More complicated algorithms could be used)
|
||||
*
|
||||
* In case of double buffering, high 16bit is the address of 2nd buffer
|
||||
* During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually.
|
||||
*/
|
||||
static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length)
|
||||
static uint32_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length, bool dbuf)
|
||||
{
|
||||
xfer_ctl_t* epXferCtl = xfer_ctl_ptr(ep_addr);
|
||||
|
||||
if(epXferCtl->pma_alloc_size != 0U)
|
||||
{
|
||||
//TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr);
|
||||
// Previously allocated
|
||||
TU_ASSERT(length <= epXferCtl->pma_alloc_size, 0xFFFF); // Verify no larger than previous alloc
|
||||
return epXferCtl->pma_ptr;
|
||||
}
|
||||
|
||||
// Ensure allocated buffer is aligned
|
||||
#ifdef FSDEV_BUS_32BIT
|
||||
length = (length + 3) & ~0x03;
|
||||
@ -801,15 +776,16 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length)
|
||||
length = (length + 1) & ~0x01;
|
||||
#endif
|
||||
|
||||
uint16_t addr = ep_buf_ptr;
|
||||
uint32_t addr = ep_buf_ptr;
|
||||
ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer
|
||||
|
||||
// Verify no overflow
|
||||
TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF);
|
||||
if(dbuf) {
|
||||
addr |= ((uint32_t)ep_buf_ptr) << 16;
|
||||
ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer
|
||||
}
|
||||
|
||||
epXferCtl->pma_ptr = addr;
|
||||
epXferCtl->pma_alloc_size = length;
|
||||
//TU_LOG1("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr);
|
||||
// Verify packet buffer is not overflowed
|
||||
TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF);
|
||||
|
||||
return addr;
|
||||
}
|
||||
@ -898,9 +874,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
|
||||
pcd_set_eptype(USB, ep_idx, wType);
|
||||
pcd_set_ep_address(USB, ep_idx, tu_edpt_number(p_endpoint_desc->bEndpointAddress));
|
||||
|
||||
/* Create a packet memory buffer area. For isochronous endpoints,
|
||||
* use the same buffer as the double buffer, essentially disabling double buffering */
|
||||
pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, buffer_size);
|
||||
/* Create a packet memory buffer area. */
|
||||
pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, buffer_size, false);
|
||||
|
||||
if(dir == TUSB_DIR_IN)
|
||||
{
|
||||
@ -966,7 +941,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
|
||||
|
||||
/* Create a packet memory buffer area. For isochronous endpoints,
|
||||
* use the same buffer as the double buffer, essentially disabling double buffering */
|
||||
uint16_t pma_addr = dcd_pma_alloc(ep_addr, buffer_size);
|
||||
uint16_t pma_addr = dcd_pma_alloc(ep_addr, buffer_size, false);
|
||||
|
||||
xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx;
|
||||
|
||||
@ -1036,7 +1011,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
|
||||
xfer->queued_len = (uint16_t)(xfer->queued_len + len);
|
||||
|
||||
/* Write into correct register when ISOCHRONOUS (double buffered) */
|
||||
if ( (ep_reg & USB_EP_DTOG_TX) && ( (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) ) {
|
||||
if ((ep_reg & USB_EP_DTOG_TX) && ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS)) {
|
||||
pcd_set_ep_rx_cnt(USB, ep_ix, len);
|
||||
} else {
|
||||
pcd_set_ep_tx_cnt(USB, ep_ix, len);
|
||||
@ -1045,7 +1020,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
|
||||
pcd_set_ep_tx_status(USB, ep_ix, USB_EP_TX_VALID);
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
@ -1053,26 +1028,18 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||
uint8_t const ep_idx = xfer->ep_idx;
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
xfer->buffer = buffer;
|
||||
xfer->ff = NULL;
|
||||
xfer->total_len = total_bytes;
|
||||
xfer->queued_len = 0;
|
||||
|
||||
if ( dir == TUSB_DIR_OUT )
|
||||
{
|
||||
// A setup token can occur immediately after an OUT STATUS packet so make sure we have a valid
|
||||
// buffer for the control endpoint.
|
||||
if (ep_idx == 0 && buffer == NULL)
|
||||
if (ep_idx == 0 && xfer->buffer == NULL)
|
||||
{
|
||||
xfer->buffer = (uint8_t*)_setup_packet;
|
||||
xfer->buffer = (uint8_t*)_setup_packet;
|
||||
}
|
||||
|
||||
if(total_bytes > xfer->max_packet_size)
|
||||
{
|
||||
pcd_set_ep_rx_bufsize(USB,ep_idx,xfer->max_packet_size);
|
||||
} else {
|
||||
pcd_set_ep_rx_bufsize(USB,ep_idx,total_bytes);
|
||||
}
|
||||
uint32_t bufsize = xfer->total_len > xfer->max_packet_size ? xfer->max_packet_size : xfer->total_len;
|
||||
pcd_set_ep_rx_bufsize(USB, ep_idx, bufsize);
|
||||
|
||||
pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_VALID);
|
||||
}
|
||||
else // IN
|
||||
@ -1082,34 +1049,27 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr);
|
||||
|
||||
xfer->buffer = buffer;
|
||||
xfer->ff = NULL;
|
||||
xfer->total_len = total_bytes;
|
||||
xfer->queued_len = 0;
|
||||
|
||||
return edpt_xfer(rhport, ep_addr);
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr);
|
||||
uint8_t const epnum = xfer->ep_idx;
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
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_bufsize(USB,epnum,xfer->max_packet_size);
|
||||
} else {
|
||||
pcd_set_ep_rx_bufsize(USB,epnum,total_bytes);
|
||||
}
|
||||
pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID);
|
||||
}
|
||||
else // IN
|
||||
{
|
||||
dcd_transmit_packet(xfer,epnum);
|
||||
}
|
||||
return true;
|
||||
return edpt_xfer(rhport, ep_addr);
|
||||
}
|
||||
|
||||
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
|
Loading…
x
Reference in New Issue
Block a user