From 1e3ace2170b2b610c3e08d452aefe72f92bf898c Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 23 Sep 2023 12:26:21 -0400 Subject: [PATCH 1/4] stm32: Improve usbfs epr register handling Replace the set_stat_x_bits() functions with a single calc_epr_bits() function. This new function supports setting bits other than the stat field in the epr register. Signed-off-by: Kevin O'Connor --- src/stm32/usbfs.c | 81 ++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/stm32/usbfs.c b/src/stm32/usbfs.c index fda2ce9d299c..ffdfb07b0634 100644 --- a/src/stm32/usbfs.c +++ b/src/stm32/usbfs.c @@ -1,6 +1,6 @@ // Hardware interface to "fullspeed USB controller" // -// Copyright (C) 2018-2021 Kevin O'Connor +// Copyright (C) 2018-2023 Kevin O'Connor // // This file may be distributed under the terms of the GNU GPLv3 license. @@ -175,26 +175,19 @@ btable_write_packet(int ep, const uint8_t *src, int count) #define USB_EPR ((volatile uint32_t *)USB_BASE) +#define EPR_TBITS (USB_EP_DTOG_RX | USB_EPRX_STAT \ + | USB_EP_DTOG_TX | USB_EPTX_STAT) #define EPR_RWBITS (USB_EPADDR_FIELD | USB_EP_KIND | USB_EP_TYPE_MASK) #define EPR_RWCBITS (USB_EP_CTR_RX | USB_EP_CTR_TX) +// Calculate the memory update needed to set the epr register static uint32_t -set_stat_rx_bits(uint32_t epr, uint32_t bits) +calc_epr_bits(uint32_t epr, uint32_t mask, uint32_t value) { - return ((epr & (EPR_RWBITS | USB_EPRX_STAT)) ^ bits) | EPR_RWCBITS; -} - -static uint32_t -set_stat_tx_bits(uint32_t epr, uint32_t bits) -{ - return ((epr & (EPR_RWBITS | USB_EPTX_STAT)) ^ bits) | EPR_RWCBITS; -} - -static uint32_t -set_stat_rxtx_bits(uint32_t epr, uint32_t bits) -{ - uint32_t mask = EPR_RWBITS | USB_EPRX_STAT | USB_EPTX_STAT; - return ((epr & mask) ^ bits) | EPR_RWCBITS; + uint32_t tmask = mask & EPR_TBITS, tvalue = value & tmask; + uint32_t rwmask = mask & EPR_RWBITS, rwbits = value & rwmask; + uint32_t cbits = EPR_RWCBITS & ~mask; + return (((epr & (EPR_RWBITS | tmask)) ^ tvalue) & ~rwmask) | rwbits | cbits; } @@ -205,36 +198,37 @@ set_stat_rxtx_bits(uint32_t epr, uint32_t bits) int_fast8_t usb_read_bulk_out(void *data, uint_fast8_t max_len) { - uint32_t epr = USB_EPR[USB_CDC_EP_BULK_OUT]; + uint32_t ep = USB_CDC_EP_BULK_OUT, epr = USB_EPR[ep]; if ((epr & USB_EPRX_STAT) == USB_EP_RX_VALID) // No data ready return -1; - uint32_t count = btable_read_packet(USB_CDC_EP_BULK_OUT, data, max_len); - USB_EPR[USB_CDC_EP_BULK_OUT] = set_stat_rx_bits(epr, USB_EP_RX_VALID); + uint32_t count = btable_read_packet(ep, data, max_len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT, USB_EP_RX_VALID); return count; } int_fast8_t usb_send_bulk_in(void *data, uint_fast8_t len) { - uint32_t epr = USB_EPR[USB_CDC_EP_BULK_IN]; + uint32_t ep = USB_CDC_EP_BULK_IN, epr = USB_EPR[ep]; if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK) // No buffer space available return -1; - btable_write_packet(USB_CDC_EP_BULK_IN, data, len); - USB_EPR[USB_CDC_EP_BULK_IN] = set_stat_tx_bits(epr, USB_EP_TX_VALID); + btable_write_packet(ep, data, len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT, USB_EP_TX_VALID); return len; } int_fast8_t usb_read_ep0(void *data, uint_fast8_t max_len) { - uint32_t epr = USB_EPR[0]; + uint32_t ep = 0, epr = USB_EPR[ep]; if ((epr & USB_EPRX_STAT) != USB_EP_RX_NAK) // No data ready return -1; - uint32_t count = btable_read_packet(0, data, max_len); - USB_EPR[0] = set_stat_rxtx_bits(epr, USB_EP_RX_VALID | USB_EP_TX_NAK); + uint32_t count = btable_read_packet(ep, data, max_len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT | USB_EPTX_STAT + , USB_EP_RX_VALID | USB_EP_TX_NAK); return count; } @@ -247,23 +241,24 @@ usb_read_ep0_setup(void *data, uint_fast8_t max_len) int_fast8_t usb_send_ep0(const void *data, uint_fast8_t len) { - uint32_t epr = USB_EPR[0]; + uint32_t ep = 0, epr = USB_EPR[ep]; if ((epr & USB_EPRX_STAT) != USB_EP_RX_VALID) // Transfer interrupted return -2; if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK) // No buffer space available return -1; - btable_write_packet(0, data, len); - USB_EPR[0] = set_stat_tx_bits(epr, USB_EP_TX_VALID); + btable_write_packet(ep, data, len); + USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT, USB_EP_TX_VALID); return len; } void usb_stall_ep0(void) { - USB_EPR[0] = set_stat_rxtx_bits(USB_EPR[0] - , USB_EP_RX_STALL | USB_EP_TX_STALL); + uint32_t ep = 0, epr = USB_EPR[ep]; + USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT | USB_EPTX_STAT + , USB_EP_RX_STALL | USB_EP_TX_STALL); } static uint8_t set_address; @@ -289,13 +284,20 @@ usb_set_configure(void) static void usb_reset(void) { - USB_EPR[0] = 0 | USB_EP_CONTROL | USB_EP_RX_VALID | USB_EP_TX_NAK; - USB_EPR[USB_CDC_EP_ACM] = (USB_CDC_EP_ACM | USB_EP_INTERRUPT - | USB_EP_RX_NAK | USB_EP_TX_NAK); - USB_EPR[USB_CDC_EP_BULK_OUT] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK - | USB_EP_RX_VALID | USB_EP_TX_NAK); - USB_EPR[USB_CDC_EP_BULK_IN] = (USB_CDC_EP_BULK_IN | USB_EP_BULK - | USB_EP_RX_NAK | USB_EP_TX_NAK); + uint32_t ep = 0; + USB_EPR[ep] = 0 | USB_EP_CONTROL | USB_EP_RX_VALID | USB_EP_TX_NAK; + + ep = USB_CDC_EP_ACM; + USB_EPR[ep] = (USB_CDC_EP_ACM | USB_EP_INTERRUPT + | USB_EP_RX_NAK | USB_EP_TX_NAK); + + ep = USB_CDC_EP_BULK_OUT; + USB_EPR[ep] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK + | USB_EP_RX_VALID | USB_EP_TX_NAK); + + ep = USB_CDC_EP_BULK_IN; + USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK + | USB_EP_RX_NAK | USB_EP_TX_NAK); USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM; USB->DADDR = USB_DADDR_EF; @@ -308,9 +310,8 @@ USB_IRQHandler(void) uint32_t istr = USB->ISTR; if (istr & USB_ISTR_CTR) { // Endpoint activity - uint32_t ep = istr & USB_ISTR_EP_ID; - uint32_t epr = USB_EPR[ep]; - USB_EPR[ep] = epr & EPR_RWBITS; + uint32_t ep = istr & USB_ISTR_EP_ID, epr = USB_EPR[ep]; + USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); if (ep == 0) { usb_notify_ep0(); if (epr & USB_EP_CTR_TX && set_address) { From 01ac5334e90d5ba57636e1c56b8e2fee901d4585 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Thu, 21 Sep 2023 15:33:37 -0400 Subject: [PATCH 2/4] stm32: Update usbfs to support setting both buffers for each endpoint The usbfs device supports two buffers for each endpoint - typically one for rx and one for tx. Add support for explicit handling of both buffers. This is in preparation for improved "double buffering" support. Signed-off-by: Kevin O'Connor --- src/stm32/usbfs.c | 72 ++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/stm32/usbfs.c b/src/stm32/usbfs.c index ffdfb07b0634..3c96fd4ddbce 100644 --- a/src/stm32/usbfs.c +++ b/src/stm32/usbfs.c @@ -55,52 +55,50 @@ // Layout of the USB transfer memory #define EPM ((epmword_t*)USB_PMAADDR) -#define EPM_EP_DESC(ep) (&EPM[(ep) * (8 / WSIZE)]) +#define EPM_EP_DESC(ep, bufnum) (&EPM[((ep)*2 + (bufnum)) * (4 / WSIZE)]) #define EPM_BUF_OFFSET 0x10 #define EPM_EP_BUF_SIZE (64 / WSIZE + 1) -#define EPM_EP_TX_BUF(ep) (&EPM[EPM_BUF_OFFSET + (ep)*2*EPM_EP_BUF_SIZE]) -#define EPM_EP_RX_BUF(ep) (&EPM[EPM_BUF_OFFSET + (1+(ep)*2)*EPM_EP_BUF_SIZE]) +#define EPM_EP_BUF(ep, bufnum) \ + (&EPM[EPM_BUF_OFFSET + ((ep)*2 + (bufnum)) * EPM_EP_BUF_SIZE]) +#define BUFTX 0 +#define BUFRX 1 // Configure the usb descriptor for an endpoint static void -epm_ep_desc_setup(int ep, int rx_size) +epm_ep_desc_setup(int ep, int bufnum, int rx_size) { - uint32_t addr_tx = (EPM_EP_TX_BUF(ep) - EPM) * WSIZE, count_tx = 0; - uint32_t addr_rx = (EPM_EP_RX_BUF(ep) - EPM) * WSIZE; + uint32_t addr = (EPM_EP_BUF(ep, bufnum) - EPM) * WSIZE; uint32_t count_rx = (rx_size <= 30 ? DIV_ROUND_UP(rx_size, 2) << 10 : ((DIV_ROUND_UP(rx_size, 32) - 1) << 10) | 0x8000); - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) { - desc[0] = addr_tx; - desc[1] = count_tx; - desc[2] = addr_rx; - desc[3] = count_rx; + desc[0] = addr; + desc[1] = count_rx; } else { - desc[0] = addr_tx | (count_tx << 16); - desc[1] = addr_rx | (count_rx << 16); + *desc = addr | (count_rx << 16); } } // Return number of read bytes on an rx endpoint static uint32_t -epm_get_ep_count_rx(int ep) +epm_get_ep_count_rx(int ep, int bufnum) { - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) - return desc[3] & 0x3ff; - return (desc[1] >> 16) & 0x3ff; + return desc[1] & 0x3ff; + return (*desc >> 16) & 0x3ff; } // Set number of bytes ready to be transmitted on a tx endpoint static void -epm_set_ep_count_tx(int ep, uint32_t count) +epm_set_ep_count_tx(int ep, int bufnum, uint32_t count) { - epmword_t *desc = EPM_EP_DESC(ep); + epmword_t *desc = EPM_EP_DESC(ep, bufnum); if (WSIZE == 2) { desc[1] = count; } else { - uint32_t addr_tx = (EPM_EP_TX_BUF(ep) - EPM) * WSIZE; - desc[0] = addr_tx | (count << 16); + uint32_t addr_tx = (EPM_EP_BUF(ep, bufnum) - EPM) * WSIZE; + *desc = addr_tx | (count << 16); } } @@ -108,18 +106,22 @@ epm_set_ep_count_tx(int ep, uint32_t count) static void btable_configure(void) { - epm_ep_desc_setup(0, USB_CDC_EP0_SIZE); - epm_ep_desc_setup(USB_CDC_EP_ACM, 0); - epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, USB_CDC_EP_BULK_OUT_SIZE); - epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 0); + epm_ep_desc_setup(0, BUFTX, 0); + epm_ep_desc_setup(0, BUFRX, USB_CDC_EP0_SIZE); + epm_ep_desc_setup(USB_CDC_EP_ACM, BUFTX, 0); + epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, BUFTX, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, BUFRX, USB_CDC_EP_BULK_OUT_SIZE); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFTX, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFRX, 0); } // Read a packet stored in dedicated usb memory static uint32_t -btable_read_packet(int ep, uint8_t *dest, int max_len) +btable_read_packet(int ep, int bufnum, uint8_t *dest, int max_len) { - epmword_t *src = EPM_EP_RX_BUF(ep); - uint32_t count = epm_get_ep_count_rx(ep); + epmword_t *src = EPM_EP_BUF(ep, bufnum); + uint32_t count = epm_get_ep_count_rx(ep, bufnum); if (count > max_len) count = max_len; int i; @@ -145,9 +147,9 @@ btable_read_packet(int ep, uint8_t *dest, int max_len) // Write a packet to dedicated usb memory static void -btable_write_packet(int ep, const uint8_t *src, int count) +btable_write_packet(int ep, int bufnum, const uint8_t *src, int count) { - epmword_t *dest = EPM_EP_TX_BUF(ep); + epmword_t *dest = EPM_EP_BUF(ep, bufnum); int i; for (i=0; i Date: Sat, 23 Sep 2023 11:45:39 -0400 Subject: [PATCH 3/4] stm32: Add usbfs double buffer support for bulk rx messages Implement the usbfs fast buffer switching mechanism on the "bulk out" endpoint. This can improve the overall USB throughput and bus utilization. Signed-off-by: Kevin O'Connor --- src/stm32/usbfs.c | 63 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/src/stm32/usbfs.c b/src/stm32/usbfs.c index 3c96fd4ddbce..661aa1b1585d 100644 --- a/src/stm32/usbfs.c +++ b/src/stm32/usbfs.c @@ -48,6 +48,12 @@ #define USB_CNTR_FRES USB_CNTR_USBRST #endif +// Some chip variants do not define these fields +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos 6 +#define USB_EP_DTOG_RX_Pos 14 +#endif + /**************************************************************** * USB transfer memory @@ -110,8 +116,8 @@ btable_configure(void) epm_ep_desc_setup(0, BUFRX, USB_CDC_EP0_SIZE); epm_ep_desc_setup(USB_CDC_EP_ACM, BUFTX, 0); epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0); - epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, BUFTX, 0); - epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, BUFRX, USB_CDC_EP_BULK_OUT_SIZE); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 0, USB_CDC_EP_BULK_OUT_SIZE); + epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 1, USB_CDC_EP_BULK_OUT_SIZE); epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFTX, 0); epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFRX, 0); } @@ -192,20 +198,41 @@ calc_epr_bits(uint32_t epr, uint32_t mask, uint32_t value) return (((epr & (EPR_RWBITS | tmask)) ^ tvalue) & ~rwmask) | rwbits | cbits; } +// Check if double buffering endpoint hardware can no longer send/receive +static int +epr_is_dbuf_blocking(uint32_t epr) +{ + return !(((epr >> (USB_EP_DTOG_RX_Pos - USB_EP_DTOG_TX_Pos)) ^ epr) + & USB_EP_DTOG_TX); +} + /**************************************************************** * USB interface ****************************************************************/ +static uint32_t bulk_out_pop_count, bulk_out_push_flag; + int_fast8_t usb_read_bulk_out(void *data, uint_fast8_t max_len) { - uint32_t ep = USB_CDC_EP_BULK_OUT, epr = USB_EPR[ep]; - if ((epr & USB_EPRX_STAT) == USB_EP_RX_VALID) + if (readl(&bulk_out_push_flag)) // No data ready return -1; - uint32_t count = btable_read_packet(ep, BUFRX, data, max_len); - USB_EPR[ep] = calc_epr_bits(epr, USB_EPRX_STAT, USB_EP_RX_VALID); + uint32_t ep = USB_CDC_EP_BULK_OUT; + int bufnum = bulk_out_pop_count & 1; + bulk_out_pop_count++; + uint32_t count = btable_read_packet(ep, bufnum, data, max_len); + writel(&bulk_out_push_flag, USB_EP_DTOG_TX); + + // Check if irq handler pulled another packet before push flag update + uint32_t epr = USB_EPR[ep]; + if (epr_is_dbuf_blocking(epr) && readl(&bulk_out_push_flag)) { + // Second packet was already read - must notify hardware + writel(&bulk_out_push_flag, 0); + USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_TX; + } + return count; } @@ -275,6 +302,9 @@ usb_set_address(uint_fast8_t addr) void usb_set_configure(void) { + uint32_t ep = USB_CDC_EP_BULK_OUT; + bulk_out_pop_count = 0; + USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID); } @@ -294,8 +324,9 @@ usb_reset(void) | USB_EP_RX_NAK | USB_EP_TX_NAK); ep = USB_CDC_EP_BULK_OUT; - USB_EPR[ep] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK - | USB_EP_RX_VALID | USB_EP_TX_NAK); + USB_EPR[ep] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK | USB_EP_KIND + | USB_EP_RX_VALID | USB_EP_TX_NAK | USB_EP_DTOG_TX); + bulk_out_push_flag = USB_EP_DTOG_TX; ep = USB_CDC_EP_BULK_IN; USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK @@ -313,18 +344,22 @@ USB_IRQHandler(void) if (istr & USB_ISTR_CTR) { // Endpoint activity uint32_t ep = istr & USB_ISTR_EP_ID, epr = USB_EPR[ep]; - USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); - if (ep == 0) { + if (ep == USB_CDC_EP_BULK_OUT) { + USB_EPR[ep] = (calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0) + | bulk_out_push_flag); + bulk_out_push_flag = 0; + usb_notify_bulk_out(); + } else if (ep == USB_CDC_EP_BULK_IN) { + USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); + usb_notify_bulk_in(); + } else if (ep == 0) { + USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); usb_notify_ep0(); if (epr & USB_EP_CTR_TX && set_address) { // Apply address after last "in" message transmitted USB->DADDR = set_address; set_address = 0; } - } else if (ep == USB_CDC_EP_BULK_OUT) { - usb_notify_bulk_out(); - } else if (ep == USB_CDC_EP_BULK_IN) { - usb_notify_bulk_in(); } } if (istr & USB_ISTR_RESET) { From cd8d57c2c68049e8fbbeedd88eba01fe6495c7c5 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 23 Sep 2023 15:31:52 -0400 Subject: [PATCH 4/4] stm32: Add usbfs double buffer support for bulk tx messages Implement the usbfs fast buffer switching mechanism on the "bulk in" endpoint. This can improve the overall USB throughput and bus utilization. Signed-off-by: Kevin O'Connor --- src/stm32/usbfs.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/stm32/usbfs.c b/src/stm32/usbfs.c index 661aa1b1585d..d166fbb7ace9 100644 --- a/src/stm32/usbfs.c +++ b/src/stm32/usbfs.c @@ -118,8 +118,8 @@ btable_configure(void) epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0); epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 0, USB_CDC_EP_BULK_OUT_SIZE); epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 1, USB_CDC_EP_BULK_OUT_SIZE); - epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFTX, 0); - epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFRX, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 0, 0); + epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 1, 0); } // Read a packet stored in dedicated usb memory @@ -236,15 +236,27 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len) return count; } +static uint32_t bulk_in_push_count, bulk_in_pop_flag; + int_fast8_t usb_send_bulk_in(void *data, uint_fast8_t len) { - uint32_t ep = USB_CDC_EP_BULK_IN, epr = USB_EPR[ep]; - if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK) + if (readl(&bulk_in_pop_flag)) // No buffer space available return -1; - btable_write_packet(ep, BUFTX, data, len); - USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT, USB_EP_TX_VALID); + uint32_t ep = USB_CDC_EP_BULK_IN; + int bufnum = bulk_in_push_count & 1; + bulk_in_push_count++; + btable_write_packet(ep, bufnum, data, len); + writel(&bulk_in_pop_flag, USB_EP_DTOG_RX); + + // Check if hardware needs to be notified + uint32_t epr = USB_EPR[ep]; + if (epr_is_dbuf_blocking(epr) && readl(&bulk_in_pop_flag)) { + writel(&bulk_in_pop_flag, 0); + USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_RX; + } + return len; } @@ -305,6 +317,11 @@ usb_set_configure(void) uint32_t ep = USB_CDC_EP_BULK_OUT; bulk_out_pop_count = 0; USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID); + + ep = USB_CDC_EP_BULK_IN; + bulk_in_push_count = 0; + writel(&bulk_in_pop_flag, 0); + USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPTX_STAT, USB_EP_TX_VALID); } @@ -329,8 +346,9 @@ usb_reset(void) bulk_out_push_flag = USB_EP_DTOG_TX; ep = USB_CDC_EP_BULK_IN; - USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK + USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK | USB_EP_KIND | USB_EP_RX_NAK | USB_EP_TX_NAK); + bulk_in_pop_flag = USB_EP_DTOG_RX; USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM; USB->DADDR = USB_DADDR_EF; @@ -350,7 +368,9 @@ USB_IRQHandler(void) bulk_out_push_flag = 0; usb_notify_bulk_out(); } else if (ep == USB_CDC_EP_BULK_IN) { - USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); + USB_EPR[ep] = (calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0) + | bulk_in_pop_flag); + bulk_in_pop_flag = 0; usb_notify_bulk_in(); } else if (ep == 0) { USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0);