diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0e78c796e..17b5c7068 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -163,7 +163,7 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne typedef struct { uint8_t * buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API + tu_fifo_t * ff; uint16_t total_len; uint16_t queued_len; uint16_t pma_ptr; @@ -196,8 +196,8 @@ 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_read_packet_memory(void *__restrict dst, uint16_t 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_ff(tu_fifo_t * ff, uint16_t src, uint16_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_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 @@ -222,7 +222,7 @@ void dcd_init (uint8_t rhport) { asm("NOP"); } - // Perform USB peripheral reset + // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for(uint32_t i = 0; i<200; i++) // should be a few us { @@ -526,15 +526,15 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (count != 0U) { -#if 0 // TODO support dcd_edpt_xfer_fifo API + uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex); + if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, *pcd_ep_rx_address_ptr(USB,EPindex), count); + dcd_read_packet_memory_ff(xfer->ff, addr, count); } else -#endif { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), *pcd_ep_rx_address_ptr(USB,EPindex), count); + dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), addr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -683,6 +683,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re static void dcd_pma_alloc_reset(void) { + open_ep_count = 0; 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; ipma_alloc_size != 0U) { //TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr); @@ -771,9 +773,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc const uint16_t epMaxPktSize = tu_edpt_packet_size(p_endpoint_desc); uint16_t pma_addr; uint32_t wType; - + // Isochronous not supported (yet), and some other driver assumptions. - TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); // Set type @@ -781,12 +782,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc case TUSB_XFER_CONTROL: wType = USB_EP_CONTROL; break; -#if (0) - case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported + case TUSB_XFER_ISOCHRONOUS: wType = USB_EP_ISOCHRONOUS; break; -#endif - case TUSB_XFER_BULK: wType = USB_EP_CONTROL; break; @@ -805,21 +803,41 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc // or being double-buffered (bulk endpoints) pcd_clear_ep_kind(USB,0); + /* 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, epMaxPktSize); +#if defined(ISOCHRONOUS_DOUBLEBUFFER) + if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) ) +#else if(dir == TUSB_DIR_IN) +#endif { *pcd_ep_tx_address_ptr(USB, epnum) = pma_addr; pcd_set_ep_tx_cnt(USB, epnum, epMaxPktSize); pcd_clear_tx_dtog(USB, epnum); - pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK); + + if(wType == USB_EP_ISOCHRONOUS) { + pcd_set_ep_tx_status(USB, epnum, USB_EP_TX_DIS); + } else { + pcd_set_ep_tx_status(USB, epnum, USB_EP_TX_NAK); + } } +#if defined(ISOCHRONOUS_DOUBLEBUFFER) + if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) ) +#else else +#endif { *pcd_ep_rx_address_ptr(USB, epnum) = pma_addr; pcd_set_ep_rx_cnt(USB, epnum, epMaxPktSize); pcd_clear_rx_dtog(USB, epnum); - pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); + + if(wType == USB_EP_ISOCHRONOUS) { + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); + } else { + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); + } } xfer_ctl_ptr(epnum, dir)->max_packet_size = epMaxPktSize; @@ -845,10 +863,10 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) (void)rhport; uint32_t const epnum = tu_edpt_number(ep_addr); uint32_t const dir = tu_edpt_dir(ep_addr); - + if(dir == TUSB_DIR_IN) { - pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); + pcd_set_ep_tx_status(USB,epnum, USB_EP_TX_DIS); } else { @@ -868,15 +886,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); -#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { dcd_write_packet_memory_ff(xfer->ff, oldAddr, len); } else -#endif { dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); } @@ -896,7 +913,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; // TODO support dcd_edpt_xfer_fifo API + xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -908,6 +925,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { xfer->buffer = (uint8_t*)_setup_packet; } + if(total_bytes > xfer->max_packet_size) { pcd_set_ep_rx_cnt(USB,epnum,xfer->max_packet_size); @@ -923,7 +941,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -934,7 +951,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = NULL; - // xfer->ff = ff; // TODO support dcd_edpt_xfer_fifo API + xfer->ff = ff; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -954,7 +971,6 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } return true; } -#endif void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { @@ -978,7 +994,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { // IN ep_addr &= 0x7F; - pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_NAK); + uint8_t const epnum = tu_edpt_number(ep_addr); + if (pcd_get_eptype(USB, epnum) != USB_EP_ISOCHRONOUS) { + pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_NAK); + } /* Reset to DATA0 if clearing stall condition. */ pcd_clear_tx_dtog(USB,ep_addr); @@ -1029,7 +1048,6 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si return true; } -#if 0 // TODO support dcd_edpt_xfer_fifo API /** * @brief Copy from FIFO to packet memory area (PMA). * Uses byte-access of system memory and 16-bit access of packet memory @@ -1043,38 +1061,36 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN { // 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 * src; - uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO - THIS FUNCTION CHANGED!!! - TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA - tu_fifo_advance_read_pointer(ff, len); + tu_fifo_buffer_info_t info; + tu_fifo_get_read_info(ff, &info); // We want to read from the FIFO + TU_VERIFY(info.len_lin && dcd_write_packet_memory(dst, info.ptr_lin, info.len_lin)); // and write it into the PMA + tu_fifo_advance_read_pointer(ff, info.len_lin); // Check for wrapped part - if (len < wNBytes) + if (info.len_wrap) { - // 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; + dst += info.len_lin; + uint8_t* src = (uint8_t*)info.ptr_wrap; + uint16_t len2 = info.len_wrap; // 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 + if (info.len_lin % 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 - tu_fifo_read_n(ff, (void *) &pma[PMA_STRIDE*(dst>>1)], 2); // Since EP FIFOs must be of item size 1 this is safe to do - dst++; + TU_ASSERT(false); // TODO: Step through and check -> untested + + uint16_t temp = ((uint8_t *)info.ptr_lin)[info.len_lin-1] | src[0] << 16; // CHECK endianess + pma[PMA_STRIDE*(dst>>1)] = temp; + src++; len2--; } TU_VERIFY(dcd_write_packet_memory(dst, src, len2)); - tu_fifo_advance_write_pointer(ff, len2); + tu_fifo_advance_write_pointer(ff, info.len_wrap); } return true; } -#endif /** * @brief Copy a buffer from packet memory area (PMA) to user memory area. @@ -1111,7 +1127,6 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN return true; } -#if 0 // TODO support dcd_edpt_xfer_fifo API /** * @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 @@ -1125,32 +1140,31 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB { // 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 * dst; - uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); // THIS FUNCTION CHANGED!!!! - TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); - tu_fifo_advance_write_pointer(ff, len); + tu_fifo_buffer_info_t info; + tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO + + TU_VERIFY(info.len_lin && dcd_read_packet_memory(info.ptr_lin, src, info.len_lin)); + tu_fifo_advance_write_pointer(ff, info.len_lin); // Check for wrapped part - if (len < wNBytes) + if (info.len_wrap) { - // 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; + src += info.len_lin; // 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 + if (info.len_lin % 2) // If len is uneven there is a byte left to copy { + TU_ASSERT(false); //TODO: step through -> untested uint32_t temp = pma[PMA_STRIDE*(src>>1)]; - *((uint8_t *)dst++) = ((temp >> 8) & 0xFF); + *((uint8_t *)info.ptr_wrap++) = ((temp >> 8) & 0xFF); src++; - len2--; + tu_fifo_advance_write_pointer(ff, 1); + info.len_wrap--; } - TU_VERIFY(dcd_read_packet_memory(dst, src, len2)); - tu_fifo_advance_write_pointer(ff, len2); + TU_VERIFY(dcd_read_packet_memory(info.ptr_wrap, src, info.len_wrap)); + tu_fifo_advance_write_pointer(ff, info.len_wrap); } return true; @@ -1158,5 +1172,3 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB #endif -#endif - diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index bffae4500..40c4003c5 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -66,6 +66,7 @@ defined(STM32F373xC) #include "stm32f3xx.h" #define PMA_LENGTH (512u) + #define ISOCHRONOUS_DOUBLEBUFFER // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) @@ -75,6 +76,7 @@ defined(STM32F303xD) || defined(STM32F303xE) #include "stm32f3xx.h" #define PMA_LENGTH (1024u) + #define ISOCHRONOUS_DOUBLEBUFFER // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support // When CAN clock is enabled, USB can use first 768 bytes ONLY.