summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c114
1 files changed, 37 insertions, 77 deletions
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 41b5acbc6..f380355ae 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -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_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, 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 = 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)
+{
+ xfer_ctl_t * xfer = xfer_ctl_ptr(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)