diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index 67e793016..bf5696725 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -89,19 +89,20 @@
-
-
+
+
+
-
+
-
+
-
+
@@ -133,8 +134,8 @@
-
-
+
+
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index cd7410488..89697106d 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -147,6 +147,7 @@ typedef struct {
static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2];
static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT];
static uint8_t remoteWakeCountdown; // When wake is requested
+static uint8_t _setup_dir; // for detecting status OUT
//--------------------------------------------------------------------+
// Prototypes
@@ -311,6 +312,7 @@ static void handle_ctr_setup(uint32_t ep_id) {
// Setup packet should always be 8 bytes. If not, we probably missed the packet
if (rx_count == 8) {
+ _setup_dir = (setup_packet[0] & 0x80 ? TUSB_DIR_IN : TUSB_DIR_OUT);
dcd_event_setup_received(0, (uint8_t*) setup_packet, true);
// Hardware should reset EP0 RX/TX to NAK and both toggle to 1
} else {
@@ -323,8 +325,6 @@ static void handle_ctr_setup(uint32_t ep_id) {
// Handle CTR interrupt for the RX/OUT direction
static void handle_ctr_rx(uint32_t ep_id) {
uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
- ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits
-
uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD;
bool const is_iso = ep_is_iso(ep_reg);
xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT);
@@ -345,6 +345,13 @@ static void handle_ctr_rx(uint32_t ep_id) {
dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count);
}
xfer->queued_len += rx_count;
+ } else {
+ // ZLP Status OUT
+ if (ep_num == 0 && (ep_reg & USB_EP_KIND) ) {
+ ep_reg &= USB_EPREG_MASK;
+ ep_reg &= ~USB_EP_KIND; // clear kind bit
+ ep_write(ep_id, ep_reg, false);
+ }
}
if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) {
@@ -360,6 +367,7 @@ static void handle_ctr_rx(uint32_t ep_id) {
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);
}
+ ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits
ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID);
ep_write(ep_id, ep_reg, false);
}
@@ -367,9 +375,6 @@ static void handle_ctr_rx(uint32_t ep_id) {
void dcd_int_handler(uint8_t rhport) {
uint32_t int_status = FSDEV_REG->ISTR;
- // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP
- // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF;
- // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ )
/* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */
if (int_status & USB_ISTR_SOF) {
@@ -738,17 +743,22 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) {
uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR
ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir);
- uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size);
-
- if (ep_is_iso(ep_reg)) {
- btable_set_rx_bufsize(ep_idx, 0, cnt);
- btable_set_rx_bufsize(ep_idx, 1, cnt);
+ if ( ep_num == 0 && dir == TUSB_DIR_OUT && _setup_dir == TUSB_DIR_IN ) {
+ // use EP0 OUT status stage, otherwise OUT packet right after SETUP will be accepted without
+ // the usbd (software) consent
+ ep_reg |= USB_EP_KIND;
} else {
- btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt);
- }
+ uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size);
+ if (ep_is_iso(ep_reg)) {
+ btable_set_rx_bufsize(ep_idx, 0, cnt);
+ btable_set_rx_bufsize(ep_idx, 1, cnt);
+ } else {
+ btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt);
+ }
+ }
ep_change_status(&ep_reg, dir, EP_STAT_VALID);
- ep_write(ep_idx, ep_reg, false);
+ ep_write(ep_idx, ep_reg, true);
}
return true;
diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h
index 6c5ccae89..7ebc32255 100644
--- a/src/portable/st/stm32_fsdev/fsdev_type.h
+++ b/src/portable/st/stm32_fsdev/fsdev_type.h
@@ -277,8 +277,8 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10);
if (bl_nb == 0) {
- // 0 is invalid, set up blsize to 1
- bl_nb = 1 << 15;
+ // zlp but 0 is invalid value, set num_block to 1 (2 bytes)
+ bl_nb = 1 << 10;
}
#ifdef FSDEV_BUS_32BIT