summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-07-31 11:35:09 +0700
committerhathach <[email protected]>2024-07-31 11:35:09 +0700
commit126778298e6ab23f2117b60d479d31e4de7d276f (patch)
tree5d27f80c57423336b4cdb340f91e98ec1ea1eaa7
parent0c8d41e25ec3f691f3125f634659f52d084e8995 (diff)
enhance dcd_ep_ctr_rx_handler()
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c128
1 files changed, 58 insertions, 70 deletions
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 5cba9ca40..c7a25ba5e 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -178,7 +178,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t
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);
-TU_ATTR_UNUSED static void edpt0_open(uint8_t rhport);
+static void edpt0_open(uint8_t rhport);
//--------------------------------------------------------------------+
// Inline helper
@@ -285,10 +285,8 @@ static void handle_bus_reset(uint8_t rhport) {
}
// Handle CTR interrupt for the TX/IN direction
-// Upon call, (wIstr & USB_ISTR_DIR) == 0U
-static void dcd_ep_ctr_tx_handler(uint32_t wIstr) {
- uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
- uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
+static void dcd_ep_ctr_tx_handler(uint32_t ep_id) {
+ uint32_t wEPRegVal = pcd_get_endpoint(USB, ep_id);
uint8_t ep_addr = (wEPRegVal & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK;
// Verify the CTR_TX bit is set. This was in the ST Micro code,
@@ -298,7 +296,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) {
}
/* clear int flag */
- pcd_clear_tx_ep_ctr(USB, EPindex);
+ pcd_clear_tx_ep_ctr(USB, ep_id);
xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr);
@@ -311,20 +309,18 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) {
}
xfer->iso_in_sending = false;
uint8_t buf_id = (wEPRegVal & USB_EP_DTOG_TX) ? 0 : 1;
- btable_set_count(EPindex, buf_id, 0);
+ btable_set_count(ep_id, buf_id, 0);
}
if ((xfer->total_len != xfer->queued_len)) {
- dcd_transmit_packet(xfer, EPindex);
+ dcd_transmit_packet(xfer, ep_id);
} else {
dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
}
// Handle CTR interrupt for the RX/OUT direction
-// Upon call, (wIstr & USB_ISTR_DIR) == 0U
-static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
-{
+static void dcd_ep_ctr_rx_handler(uint32_t ep_id) {
#ifdef FSDEV_BUS_32BIT
/* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
* From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers
@@ -346,103 +342,92 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
}
#endif
- uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
- uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
- uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD;
+ uint32_t ep_reg = pcd_get_endpoint(USB, ep_id);
+ uint8_t ep_addr = ep_reg & USB_EPADDR_FIELD;
// Verify the CTR_RX bit is set. This was in the ST Micro code,
// but I'm not sure it's actually necessary?
- if ((wEPRegVal & USB_EP_CTR_RX) == 0U) {
+ if ((ep_reg & USB_EP_CTR_RX) == 0U) {
return;
}
- if (wEPRegVal & USB_EP_SETUP) {
- uint32_t count = btable_get_count(EPindex, BTABLE_BUF_RX);
+ // Clear RX CTR and reserved TX CTR
+ ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX;
+
+ if (ep_reg & USB_EP_SETUP) {
+ uint32_t count = btable_get_count(ep_id, BTABLE_BUF_RX);
// Setup packet should always be 8 bytes. If not, ignore it, and try again.
if (count == 8) {
- uint16_t rx_addr = btable_get_addr(EPindex, BTABLE_BUF_RX);
-#ifdef FSDEV_BUS_32BIT
- dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + rx_addr), true);
-#else
- // The setup_received function uses memcpy, so this must first copy the setup data into
- // user memory, to allow for the 32-bit access that memcpy performs.
- uint32_t userMemBuf[2];
- dcd_read_packet_memory(userMemBuf, rx_addr, 8);
- dcd_event_setup_received(0, (uint8_t*) userMemBuf, true);
-#endif
+ uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX);
+ uint32_t setup_packet[2];
+ dcd_read_packet_memory(setup_packet, rx_addr, 8);
+ dcd_event_setup_received(0, (uint8_t*) setup_packet, true);
// Reset EP to NAK (in case it had been stalling)
- wEPRegVal = ep_add_tx_status(wEPRegVal, USB_EP_TX_NAK);
- wEPRegVal = ep_add_rx_status(wEPRegVal, USB_EP_RX_NAK);
- wEPRegVal = ep_add_tx_dtog(wEPRegVal, 1);
- wEPRegVal = ep_add_rx_dtog(wEPRegVal, 1);
- pcd_set_endpoint(USB, 0, wEPRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX);
+ ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK);
+ ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK);
+ ep_reg = ep_add_tx_dtog(ep_reg, 1);
+ ep_reg = ep_add_rx_dtog(ep_reg, 1);
+ } else {
+ ep_reg &= USB_EPREG_MASK; // reversed all toggle
}
} else {
- // Clear RX CTR interrupt flag
- if (ep_addr != 0u) {
- pcd_clear_rx_ep_ctr(USB, EPindex);
- }
+ ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status
+ bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS;
xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr);
uint8_t buf_id;
- if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) {
- // ISO endpoints are double buffered
- buf_id = (wEPRegVal & USB_EP_DTOG_RX) ? 0 : 1;
+ if (is_iso) {
+ buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered
} else {
- buf_id = 1;
+ buf_id = BTABLE_BUF_RX;
}
- uint32_t count = btable_get_count(EPindex, buf_id);
- uint16_t addr = (uint16_t) btable_get_addr(EPindex, buf_id);
+ uint32_t rx_count = btable_get_count(ep_id, buf_id);
+ uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id);
- if (count != 0U) {
+ if (rx_count != 0) {
if (xfer->ff) {
- dcd_read_packet_memory_ff(xfer->ff, addr, count);
+ dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count);
} else {
- dcd_read_packet_memory(xfer->buffer + xfer->queued_len, addr, count);
+ dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count);
}
- xfer->queued_len = (uint16_t)(xfer->queued_len + count);
+ xfer->queued_len = (uint16_t)(xfer->queued_len + rx_count);
}
- if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) {
+ if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) {
// all bytes received or short packet
dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+
+ if (ep_addr == 0u) {
+ // prepared for status packet
+ btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE);
+ }
+
+ ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK);
} else {
- /* Set endpoint active again for receiving more data.
- * Note that isochronous endpoints stay active always */
- if ((wEPRegVal & USB_EP_TYPE_MASK) != USB_EP_ISOCHRONOUS) {
- uint16_t remaining = xfer->total_len - xfer->queued_len;
- uint16_t cnt = tu_min16(remaining, xfer->max_packet_size);
- btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, cnt);
+ // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always
+ if (!is_iso) {
+ uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size);
+ btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt);
}
- pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);
+ ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_VALID);
}
}
- // For EP0, prepare to receive another SETUP packet.
- // Clear CTR last so that a new packet does not overwrite the packing being read.
- // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared)
- if (ep_addr == 0u) {
- // Always be prepared for a status packet...
- btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE);
- pcd_clear_rx_ep_ctr(USB, EPindex);
- }
+ pcd_set_endpoint(USB, ep_id, ep_reg);
}
-static void dcd_ep_ctr_handler(void)
-{
+static void dcd_ep_ctr_handler(void) {
uint32_t wIstr;
-
/* stay in loop while pending interrupts */
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) {
+ uint32_t ep_id = wIstr & USB_ISTR_EP_ID;
if ((wIstr & USB_ISTR_DIR) == 0U) {
- /* TX/IN */
- dcd_ep_ctr_tx_handler(wIstr);
+ dcd_ep_ctr_tx_handler(ep_id); // TX/IN
} else {
- /* RX/OUT*/
- dcd_ep_ctr_rx_handler(wIstr);
+ dcd_ep_ctr_rx_handler(ep_id); // RX/OUT
}
}
}
@@ -609,11 +594,14 @@ void edpt0_open(uint8_t rhport) {
btable_set_addr(0, BTABLE_BUF_TX, pma_addr1);
uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK;
- ep_reg |= USB_EP_CONTROL | USB_EP_CTR_RX | USB_EP_CTR_TX;
+ ep_reg |= USB_EP_CONTROL; // | USB_EP_CTR_RX | USB_EP_CTR_TX;
ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK);
ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK);
// no need to explicitly set DTOG bits since we aren't masked DTOG bit
+ // prepare for setup packet
+ btable_set_rx_bufsize(0, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE);
+
pcd_set_endpoint(USB, 0, ep_reg);
}