mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
STM32FSDEV: Rewrite transfer ISR
This commit is contained in:
parent
00eabbac35
commit
eaf767b0db
@ -185,10 +185,7 @@ void HardFault_Handler (void)
|
||||
*/
|
||||
void assert_failed(char *file, uint32_t line)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
TU_LOG1("Assertion failed (%s:%ld)\r\n", file, line);
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
|
@ -184,7 +184,7 @@ static void dcd_handle_bus_reset(void);
|
||||
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 void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix);
|
||||
static uint16_t dcd_ep_ctr_handler(void);
|
||||
static void dcd_ep_ctr_handler(void);
|
||||
|
||||
|
||||
// Using a function due to better type checks
|
||||
@ -363,66 +363,59 @@ static void dcd_handle_bus_reset(void)
|
||||
USB->DADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero.
|
||||
}
|
||||
|
||||
// FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed.
|
||||
static uint16_t dcd_ep_ctr_handler(void)
|
||||
// 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 count=0U;
|
||||
uint8_t EPindex;
|
||||
__IO uint16_t wIstr;
|
||||
__IO uint16_t wEPVal = 0U;
|
||||
uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
|
||||
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
|
||||
|
||||
// stack variables to pass to USBD
|
||||
|
||||
/* stay in loop while pending interrupts */
|
||||
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U)
|
||||
// Verify the CTR_TX bit is set. This was in the ST Micro code,
|
||||
// but I'm not sure it's actually necessary?
|
||||
if((wEPRegVal & USB_EP_CTR_TX) == 0U)
|
||||
{
|
||||
/* extract highest priority endpoint index */
|
||||
EPindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (EPindex == 0U)
|
||||
{
|
||||
/* Decode and service control endpoint interrupt */
|
||||
|
||||
/* DIR bit = origin of the interrupt */
|
||||
if ((wIstr & USB_ISTR_DIR) == 0U)
|
||||
{
|
||||
/* DIR = 0 => IN int */
|
||||
/* DIR = 0 implies that (EP_CTR_TX = 1) always */
|
||||
pcd_clear_tx_ep_ctr(USB, 0);
|
||||
/* clear int flag */
|
||||
pcd_clear_tx_ep_ctr(USB, EPindex);
|
||||
|
||||
xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN);
|
||||
|
||||
if((xfer->total_len == xfer->queued_len))
|
||||
{
|
||||
dcd_event_xfer_complete(0u, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
if(xfer->total_len == 0) // Probably a status message?
|
||||
{
|
||||
pcd_clear_rx_dtog(USB,EPindex);
|
||||
}
|
||||
}
|
||||
else
|
||||
if((xfer->total_len != xfer->queued_len)) /* TX not complete */
|
||||
{
|
||||
dcd_transmit_packet(xfer, EPindex);
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* TX Complete */
|
||||
{
|
||||
/* DIR = 1 & CTR_RX => SETUP or OUT int */
|
||||
/* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
|
||||
dcd_event_xfer_complete(0, (uint8_t)(0x80 + EPindex), 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)
|
||||
{
|
||||
uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
|
||||
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
|
||||
uint32_t count = pcd_get_ep_rx_cnt(USB,EPindex);
|
||||
|
||||
xfer_ctl_t *xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT);
|
||||
|
||||
//ep = &hpcd->OUT_ep[0];
|
||||
wEPVal = pcd_get_endpoint(USB, EPindex);
|
||||
// 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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wEPVal & USB_EP_SETUP) != 0U) // SETUP
|
||||
if((EPindex == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */
|
||||
{
|
||||
// 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.
|
||||
uint8_t userMemBuf[8];
|
||||
/* Get SETUP Packet*/
|
||||
count = pcd_get_ep_rx_cnt(USB, EPindex);
|
||||
if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again.
|
||||
{
|
||||
// Must reset EP to NAK (in case it had been stalling) (though, maybe too late here)
|
||||
@ -431,56 +424,21 @@ static uint16_t dcd_ep_ctr_handler(void)
|
||||
dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8);
|
||||
dcd_event_setup_received(0, (uint8_t*)userMemBuf, true);
|
||||
}
|
||||
/* SETUP bit kept frozen while CTR_RX = 1*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear RX CTR interrupt flag
|
||||
if(EPindex != 0u)
|
||||
{
|
||||
pcd_clear_rx_ep_ctr(USB, EPindex);
|
||||
}
|
||||
else if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT
|
||||
{
|
||||
|
||||
pcd_clear_rx_ep_ctr(USB, EPindex);
|
||||
|
||||
/* Get Control Data OUT Packet */
|
||||
count = pcd_get_ep_rx_cnt(USB,EPindex);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
dcd_read_packet_memory(xfer->buffer, *pcd_ep_rx_address_ptr(USB,EPindex), count);
|
||||
xfer->queued_len = (uint16_t)(xfer->queued_len + count);
|
||||
}
|
||||
|
||||
/* Process Control Data OUT status Packet*/
|
||||
dcd_event_xfer_complete(0, EPindex, xfer->total_len, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE);
|
||||
if(EPindex == 0u && xfer->total_len == 0u)
|
||||
{
|
||||
pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);// Await next SETUP
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Decode and service non control endpoints interrupt */
|
||||
{
|
||||
/* process related endpoint register */
|
||||
wEPVal = pcd_get_endpoint(USB, EPindex);
|
||||
if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT
|
||||
{
|
||||
/* clear int flag */
|
||||
pcd_clear_rx_ep_ctr(USB, EPindex);
|
||||
|
||||
xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT);
|
||||
|
||||
//ep = &hpcd->OUT_ep[EPindex];
|
||||
|
||||
count = pcd_get_ep_rx_cnt(USB, EPindex);
|
||||
if (count != 0U)
|
||||
{
|
||||
dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]),
|
||||
*pcd_ep_rx_address_ptr(USB,EPindex), count);
|
||||
}
|
||||
|
||||
/*multi-packet on the NON control OUT endpoint */
|
||||
xfer->queued_len = (uint16_t)(xfer->queued_len + count);
|
||||
}
|
||||
|
||||
if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len))
|
||||
{
|
||||
@ -497,30 +455,39 @@ static uint16_t dcd_ep_ctr_handler(void)
|
||||
} else {
|
||||
pcd_set_ep_rx_cnt(USB, EPindex,remaining);
|
||||
}
|
||||
|
||||
pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
} /* if((wEPVal & EP_CTR_RX) */
|
||||
|
||||
if ((wEPVal & USB_EP_CTR_TX) != 0U) // IN
|
||||
// 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(EPindex == 0u)
|
||||
{
|
||||
/* clear int flag */
|
||||
pcd_clear_tx_ep_ctr(USB, EPindex);
|
||||
// Always be prepared for a status packet...
|
||||
pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE);
|
||||
pcd_clear_rx_ep_ctr(USB, EPindex);
|
||||
}
|
||||
}
|
||||
|
||||
xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN);
|
||||
|
||||
if (xfer->queued_len != xfer->total_len) // data remaining in transfer?
|
||||
static void dcd_ep_ctr_handler(void)
|
||||
{
|
||||
dcd_transmit_packet(xfer, EPindex);
|
||||
} else {
|
||||
dcd_event_xfer_complete(0, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true);
|
||||
uint32_t wIstr;
|
||||
|
||||
/* stay in loop while pending interrupts */
|
||||
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U)
|
||||
{
|
||||
|
||||
if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */
|
||||
{
|
||||
dcd_ep_ctr_tx_handler(wIstr);
|
||||
}
|
||||
else /* RX/OUT*/
|
||||
{
|
||||
dcd_ep_ctr_rx_handler(wIstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dcd_fs_irqHandler(void) {
|
||||
|
||||
|
@ -310,6 +310,13 @@ static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpNum, ui
|
||||
pcd_set_endpoint(USBx, bEpNum, regVal);
|
||||
} /* pcd_set_ep_rx_status */
|
||||
|
||||
static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpNum)
|
||||
{
|
||||
uint32_t regVal = pcd_get_endpoint(USBx, bEpNum);
|
||||
return (regVal & USB_EPRX_STAT) >> (12u);
|
||||
} /* pcd_get_ep_rx_status */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register.
|
||||
* @param USBx USB peripheral instance register address.
|
||||
|
Loading…
x
Reference in New Issue
Block a user