summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon McNab <[email protected]>2022-11-28 17:41:00 +0000
committerGordon McNab <[email protected]>2022-11-28 17:41:00 +0000
commit1fce76ad472fe1936eedea0688960c76bd42fd40 (patch)
tree7824a995bb5d45979c34e6b7a8f5cca1dba471f3
parent9ccfb384e8dcbed314c25af698969bb5a17f3810 (diff)
Fix issue with the CDC SetLineCoding request
The SetLineCoding would fail as host would send the SETUP OUT phase before tinyUSB had setup a transaction for it. ft9xx port would ignore the transfer since there was no valid transaction setup for it. One SETUP data phase packet is cached now.
-rw-r--r--examples/device/cdc_dual_ports/src/usb_descriptors.c2
-rw-r--r--hw/bsp/brtmm90x/family.c17
-rw-r--r--hw/bsp/brtmm90x/family.mk10
m---------hw/mcu/bridgetek/ft9xx/ft90x-sdk0
-rw-r--r--src/portable/bridgetek/ft9xx/dcd_ft9xx.c82
5 files changed, 86 insertions, 25 deletions
diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c
index cda1b63b6..9f212c78f 100644
--- a/examples/device/cdc_dual_ports/src/usb_descriptors.c
+++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c
@@ -97,7 +97,7 @@ enum
#define EPNUM_CDC_1_OUT 0x05
#define EPNUM_CDC_1_IN 0x85
-#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
+#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X || CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_0_NOTIF 0x81
diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c
index 6b3c1f56c..77a03e909 100644
--- a/hw/bsp/brtmm90x/family.c
+++ b/hw/bsp/brtmm90x/family.c
@@ -27,8 +27,8 @@
#include "bsp/board.h"
#include "board.h"
-#include <registers/ft900_registers.h>
#include <ft900.h>
+#include <registers/ft900_registers.h>
#if CFG_TUD_ENABLED
int8_t board_ft90x_vbus(void); // Board specific implementation of VBUS detection for USB device.
@@ -213,3 +213,18 @@ uint32_t board_millis(void)
return safe_ms;
}
+
+// Restart the program
+// Called in the event of a watchdog timeout
+void chip_reboot(void)
+{
+ // SOFT reset
+ __asm__("call 0");
+ #if 0
+ // HARD reset
+ // Initiates data transfer from Flash Memory to Data Memory (DBG_CMDF2D3)
+ // followed by a system reboot
+ dbg_memory_copy(0xfe, 0, 0, 255);
+#endif
+}
+
diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk
index 3933f15cc..a476cfc06 100644
--- a/hw/bsp/brtmm90x/family.mk
+++ b/hw/bsp/brtmm90x/family.mk
@@ -21,7 +21,7 @@ endif
# Add include files which are within the TinyUSB directory structure.
INC += \
- $(TOP)/$(BOARD_PATH)
+ $(TOP)/$(BOARD_PATH)
# Add required C Compiler flags for FT90X.
CFLAGS += \
@@ -30,14 +30,14 @@ CFLAGS += \
-fvar-tracking-assignments \
-fmessage-length=0 \
-ffunction-sections \
- -DCFG_TUSB_MCU=OPT_MCU_FT90X
+ -DCFG_TUSB_MCU=OPT_MCU_FT90X
+
+# Maximum USB device speed supported by the board
+CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration
CFLAGS += -Wno-error=shadow
-# Add include files outside the TinyUSB structure that are added manually.
-CFLAGS += -I"$(FT9XX_SDK)/include"
-
# Set Linker flags.
LD_FILE = hw/mcu/bridgetek/ft9xx/scripts/ldscript.ld
LDFLAGS += $(addprefix -L,$(LDINC)) \
diff --git a/hw/mcu/bridgetek/ft9xx/ft90x-sdk b/hw/mcu/bridgetek/ft9xx/ft90x-sdk
-Subproject c810d1312ded923c3c2ed9035c97bd0db4f35b5
+Subproject 0ea80ceafdf32e4e496cacc94178417e2ef4bf9
diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
index 2445593fe..080d633fa 100644
--- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
+++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
@@ -38,9 +38,6 @@
#include <ft900.h>
#include <registers/ft900_registers.h>
-#include "board.h"
-#include "bsp/board.h"
-
#define USBD_USE_STREAMS
#include "device/dcd.h"
@@ -53,14 +50,20 @@
extern int8_t board_ft90x_vbus(void);
// Static array to store an incoming SETUP request for processing by tinyusb.
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
static uint8_t _ft90x_setup_packet[8];
+// Static array to store one SETUP DATA packet until required by dcd_edpt_xfer.
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
+static uint8_t _ft90x_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE];
+static uint8_t _ft90x_ctrl_buf_complete;
+
struct ft90x_xfer_state
{
volatile uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid.
- volatile int16_t total_size; // Total transfer size in bytes for this transfer.
- volatile int16_t remain_size; // Total remaining in transfer.
- volatile uint8_t *buff_ptr; // Pointer to buffer to transmit from or receive to.
+ int16_t total_size; // Total transfer size in bytes for this transfer.
+ int16_t remain_size; // Total remaining in transfer.
+ uint8_t *buff_ptr; // Pointer to buffer to transmit from or receive to.
uint8_t type; // Endpoint type. Of type USBD_ENDPOINT_TYPE from endpoint descriptor.
uint8_t dir; // Endpoint direction. TUSB_DIR_OUT or TUSB_DIR_IN. For control endpoint this is the current direction.
@@ -766,13 +769,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
USBD_EP_CR_REG(USBD_EP_0) = (ep_reg_size << BIT_USBD_EP0_MAX_SIZE);
}
+ CRITICAL_SECTION_BEGIN
// Store the endpoint characteristics for later reference.
ep_xfer[ep_number].dir = ep_dir;
ep_xfer[ep_number].type = ep_type;
ep_xfer[ep_number].size = ep_size;
ep_xfer[ep_number].buff_size = ep_buff_size;
- CRITICAL_SECTION_BEGIN
// Clear register transaction continuation and signalling state.
ep_xfer[ep_number].valid = 0;
ep_xfer[ep_number].buff_ptr = NULL;
@@ -809,12 +812,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
// Transfer currently in progress.
if (ep_xfer[ep_number].valid == 0)
{
- status = true;
-
ep_xfer[ep_number].total_size = total_bytes;
ep_xfer[ep_number].remain_size = total_bytes;
ep_xfer[ep_number].buff_ptr = buffer;
- ep_xfer[ep_number].valid = 1;
if (ep_number == USBD_EP_0)
{
@@ -835,10 +835,33 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
ep_xfer[ep_number].buff_ptr += xfer_bytes;
ep_xfer[ep_number].remain_size -= xfer_bytes;
+
+ // Tell the interrupt handler to signal dcd_event_xfer_complete on completion.
+ ep_xfer[ep_number].valid = 1;
}
+ else
+ {
+ // For OUT transfers on the control endpoint.
+ // The host may already have performed the first data transfer after the SETUP packet
+ // before the transfer is setup for it.
+ if ((ep_number == USBD_EP_0) && (_ft90x_ctrl_buf_complete))
+ {
+ // Pull the received data packet from the packet cache and complete the transfer
+ // immediately.
+ memcpy(buffer, _ft90x_ctrl_buf, _ft90x_ctrl_buf_complete);
+ dcd_event_xfer_complete(BOARD_TUD_RHPORT, TUSB_DIR_OUT, _ft90x_ctrl_buf_complete, XFER_RESULT_SUCCESS, false);
+ }
+ else
+ {
+ // Tell the interrupt handler to wait for the packet to be received.
+ ep_xfer[ep_number].valid = 1;
+ }
+ }
+ status = true;
}
+
CRITICAL_SECTION_END
-
+
return status;
}
@@ -899,7 +922,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
void _ft90x_usbd_ISR(void)
{
- tud_int_handler(BOARD_TUD_RHPORT); // Resolves to dcd_int_handler().
+ dcd_int_handler(BOARD_TUD_RHPORT);
}
void dcd_int_handler(uint8_t rhport)
@@ -962,7 +985,6 @@ void dcd_int_handler(uint8_t rhport)
{
// Clear interrupt register.
USBD_REG(epif) = MASK_USBD_EPIF_EP0IRQ;
-
// Test for an incoming SETUP request on the control endpoint.
if (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_SETUP)
{
@@ -976,7 +998,7 @@ void dcd_int_handler(uint8_t rhport)
USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_STALL;
}
- // Host has sent a SETUP packet. Recieve this into the setup packet store.
+ // Host has sent a SETUP packet. Recieve this into the SETUP packet store.
_ft90x_dusb_out(USBD_EP_0, (uint8_t *)_ft90x_setup_packet, sizeof(USB_device_request));
// Send the packet to tinyusb.
@@ -985,6 +1007,9 @@ void dcd_int_handler(uint8_t rhport)
// Clear the interrupt that signals a SETUP packet is received.
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP);
+ // Invalidate cache packet.
+ _ft90x_ctrl_buf_complete = 0;
+
// Allow new transfers on the control endpoint.
ep_xfer[USBD_EP_0].valid = 0;
return;
@@ -998,15 +1023,36 @@ void dcd_int_handler(uint8_t rhport)
// Transfer incoming data from an OUT packet to the buffer supplied.
if (ep_xfer[USBD_EP_0].dir == TUSB_DIR_OUT)
- {
- xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, (uint8_t *)ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes);
+ {
+ xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes);
}
// Now signal completion of data packet.
dcd_event_xfer_complete(BOARD_TUD_RHPORT, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true);
+ // Invalidate cache packet.
+ _ft90x_ctrl_buf_complete = 0;
+
// Allow new transfers on the control endpoint.
ep_xfer[USBD_EP_0].valid = 0;
}
+ else
+ {
+ // We have received a data packet on the control endpoint without a transfer
+ // being initialised. This can be because the host has sent this packet before
+ // a new transfer has been initiated on the control endpoint.
+ // We will cache upto the maximum packet size for the control endpoint and
+ // use it later in dcd_edpt_xfer.
+ xfer_bytes = CFG_TUD_ENDPOINT0_SIZE;
+
+ // Transfer incoming data from an OUT packet to the cache packet.
+ xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, _ft90x_ctrl_buf, xfer_bytes);
+
+ // Set the size of the cache packet.
+ _ft90x_ctrl_buf_complete = xfer_bytes;
+ }
+
+ // Clear the interrupt that signals a SETUP DATA packet is received.
+ USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_OPRDY);
}
}
else // !(epif & MASK_USBD_EPIF_EP0IRQ)
@@ -1035,7 +1081,7 @@ void dcd_int_handler(uint8_t rhport)
if (ep_xfer[ep_number].dir == TUSB_DIR_OUT)
{
xfer_bytes = _ft90x_edpt_xfer_out(ep_number,
- (uint8_t *)ep_xfer[ep_number].buff_ptr,
+ ep_xfer[ep_number].buff_ptr,
(uint16_t)ep_xfer[ep_number].remain_size);
ep_xfer[ep_number].buff_ptr += xfer_bytes;
@@ -1047,7 +1093,7 @@ void dcd_int_handler(uint8_t rhport)
if (ep_xfer[ep_number].remain_size > 0)
{
xfer_bytes = _ft90x_edpt_xfer_in(ep_number,
- (uint8_t *)ep_xfer[ep_number].buff_ptr,
+ ep_xfer[ep_number].buff_ptr,
(uint16_t)ep_xfer[ep_number].remain_size);
ep_xfer[ep_number].buff_ptr += xfer_bytes;