From 62c613f6d2d4e3e2cf0918f75e302d48a3df673e Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Tue, 5 Oct 2021 13:54:47 +0100 Subject: [PATCH 01/16] Add initial port for FT9xx series from Bridgetek. Add FT90X and FT93X to the list of devices in tusb_option.h. 1700 for FT90x and 1701 for FT93x. Set endpoint attributes for FT90x and FT93x in dcd_attr.h. Add FT90x routines for USB device in src/portable/bridgetek/ft90x/dcd_ft90x.c The location for hardware header files and libraries is hw/mcu/bridgetek/ft90x/hardware. There are no files in the repository, but files will be linked as a submodule in the future. The required files can be copied from or linked to the location "C:/Program Files(x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware" once the toolchain is installed. Makefile for the MM900EV1B board for developing with an FT900 device is present. Use "BOARD=mm900ev1b". --- hw/bsp/brtmm90x/boards/mm900ev1b/board.h | 56 + hw/bsp/brtmm90x/family.c | 210 ++++ hw/bsp/brtmm90x/family.mk | 35 + hw/mcu/bridgetek/ft90x/Readme.md | 6 + .../bridgetek/ft90x/hardware/scripts/crt0.S | 286 +++++ .../ft90x/hardware/scripts/ldscript.ld | 94 ++ src/device/dcd_attr.h | 7 + src/portable/bridgetek/ft90x/dcd_ft90x.c | 1101 +++++++++++++++++ src/tusb_option.h | 4 + 9 files changed, 1799 insertions(+) create mode 100644 hw/bsp/brtmm90x/boards/mm900ev1b/board.h create mode 100644 hw/bsp/brtmm90x/family.c create mode 100644 hw/bsp/brtmm90x/family.mk create mode 100644 hw/mcu/bridgetek/ft90x/Readme.md create mode 100644 hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S create mode 100644 hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld create mode 100644 src/portable/bridgetek/ft90x/dcd_ft90x.c diff --git a/hw/bsp/brtmm90x/boards/mm900ev1b/board.h b/hw/bsp/brtmm90x/boards/mm900ev1b/board.h new file mode 100644 index 00000000..dfb56628 --- /dev/null +++ b/hw/bsp/brtmm90x/boards/mm900ev1b/board.h @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(__FT900__) +#define GPIO_UART0_TX 48 +#define GPIO_UART0_RX 49 +#define GPIO_ETH_LED0 61 +#define GPIO_ETH_LED1 62 +#define GPIO_REMOTE_WAKEUP_PIN 18 +#define USBD_VBUS_DTC_PIN 3 +#elif defined(__FT930__) +#define GPIO_UART0_TX 23 +#define GPIO_UART0_RX 22 +#define GPIO_ETH_LED0 4 +#define GPIO_ETH_LED1 5 +#define GPIO_REMOTE_WAKEUP_PIN 12 +#define USBD_VBUS_DTC_PIN 39 +#endif + +//#define GPIO_REMOTE_WAKEUP + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c new file mode 100644 index 00000000..010704d9 --- /dev/null +++ b/hw/bsp/brtmm90x/family.c @@ -0,0 +1,210 @@ +/* + * The MIT License (MIT) + * + * Copyright 2019 Sony Semiconductor Solutions Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include +#include "bsp/board.h" +#include "board.h" +//#include "src/device/dcd.h" + +#if TUSB_OPT_DEVICE_ENABLED +int8_t board_ft90x_vbus(void); // Board specific implementation of VBUS detection for USB device. +extern void ft90x_usbd_pm_ISR(uint16_t pmcfg); // Interrupt handler for USB device power management +#endif + +#ifdef GPIO_REMOTE_WAKEUP +void gpio_ISR(void); +#endif +void timer_ISR(void); +volatile unsigned int timer_ms = 0; +void board_pm_ISR(void); + +#define WELCOME_MSG "\x1B[2J\x1B[H" \ + "MM900EV1B board\r\n" + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + sys_reset_all(); + // Enable the UART Device. + sys_enable(sys_device_uart0); + // Set UART0 GPIO functions to UART0_TXD and UART0_RXD. + gpio_function(GPIO_UART0_TX, pad_uart0_txd); /* UART0 TXD */ + gpio_function(GPIO_UART0_RX, pad_uart0_rxd); /* UART0 RXD */ + uart_open(UART0, /* Device */ + 1, /* Prescaler = 1 */ + UART_DIVIDER_19200_BAUD, /* Divider = 1302 */ + uart_data_bits_8, /* No. Data Bits */ + uart_parity_none, /* Parity */ + uart_stop_bits_1); /* No. Stop Bits */ + // Print out a welcome message. + // Use sizeof to avoid pulling in strlen unnecessarily. + board_uart_write(WELCOME_MSG, sizeof(WELCOME_MSG)); + +#if 1 + gpio_function(GPIO_ETH_LED0, pad_gpio4); /* ETH LED0 */ + gpio_dir(GPIO_ETH_LED0, pad_dir_open_drain); + gpio_function(GPIO_ETH_LED1, pad_gpio5); /* ETH LED0 */ + gpio_dir(GPIO_ETH_LED1, pad_dir_output); +#endif + sys_enable(sys_device_timer_wdt); + interrupt_attach(interrupt_timers, (int8_t)interrupt_timers, timer_ISR); + /* Timer A = 1ms */ + timer_prescaler(timer_select_a, 1000); + timer_init(timer_select_a, 100, timer_direction_down, timer_prescaler_select_on, timer_mode_continuous); + timer_enable_interrupt(timer_select_a); + timer_start(timer_select_a); + + // Setup VBUS detect GPIO. If the device is connected then this + // will set the MASK_SYS_PMCFG_DEV_DETECT_EN bit in PMCFG. + gpio_interrupt_disable(USBD_VBUS_DTC_PIN); + gpio_function(USBD_VBUS_DTC_PIN, pad_vbus_dtc); + gpio_pull(USBD_VBUS_DTC_PIN, pad_pull_pulldown); + gpio_dir(USBD_VBUS_DTC_PIN, pad_dir_input); + + interrupt_attach(interrupt_0, (int8_t)interrupt_0, board_pm_ISR); + +#ifdef GPIO_REMOTE_WAKEUP + //Configuring GPIO pin to wakeup. + // Set up the wakeup pin. + gpio_dir(GPIO_REMOTE_WAKEUP_PIN, pad_dir_input); + gpio_pull(GPIO_REMOTE_WAKEUP_PIN, pad_pull_pullup); + + // Attach an interrupt handler. + interrupt_attach(interrupt_gpio, (uint8_t)interrupt_gpio, gpio_ISR); + gpio_interrupt_enable(GPIO_REMOTE_WAKEUP_PIN, gpio_int_edge_falling); +#endif + + uart_disable_interrupt(UART0, uart_interrupt_tx); + uart_disable_interrupt(UART0, uart_interrupt_rx); + + // Enable all peripheral interrupts. + interrupt_enable_globally(); + + TU_LOG1("MM900EV1B board setup complete\r\n"); +}; + +void timer_ISR(void) +{ + if (timer_is_interrupted(timer_select_a)) + { + timer_ms++; + } +} + +#ifdef GPIO_REMOTE_WAKEUP +void gpio_ISR(void) +{ + if (gpio_is_interrupted(GPIO_REMOTE_WAKEUP_PIN)) + { + } +} +#endif + +/* Power management ISR */ +void board_pm_ISR(void) +{ + uint16_t pmcfg = SYS->PMCFG_H; + +#if defined(__FT930__) + if (pmcfg & MASK_SYS_PMCFG_SLAVE_PERI_IRQ_PEND) + { + // Clear d2xx hw engine wakeup. + SYS->PMCFG_H = MASK_SYS_PMCFG_SLAVE_PERI_IRQ_PEND; + } +#endif + if (pmcfg & MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND) + { + // Clear GPIO wakeup pending. + SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; + } + +#if defined(__FT900__) + // USB device power management interrupts. + if (pmcfg & (MASK_SYS_PMCFG_DEV_CONN_DEV | + MASK_SYS_PMCFG_DEV_DIS_DEV | + MASK_SYS_PMCFG_HOST_RST_DEV | + MASK_SYS_PMCFG_HOST_RESUME_DEV) + ) + { +#if TUSB_OPT_DEVICE_ENABLED + ft90x_usbd_pm_ISR(pmcfg); +#endif + } +#endif +} + +#if TUSB_OPT_DEVICE_ENABLED +int8_t board_ft90x_vbus(void) +{ + return gpio_read(USBD_VBUS_DTC_PIN); +} +#endif + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +// Turn LED on or off +void board_led_write(bool state) +{ + gpio_write(GPIO_ETH_LED0, state); +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + return 0; +} + +// Get characters from UART +int board_uart_read(uint8_t *buf, int len) +{ + int r = uart_readn(UART0, (uint8_t *)buf, len); + + return r; +} + +// Send characters to UART +int board_uart_write(void const *buf, int len) +{ + int r = uart_writen(UART0, (uint8_t *)buf, len); + + return r; +} + +// Get current milliseconds +uint32_t board_millis(void) +{ + uint32_t safe_ms; + + CRITICAL_SECTION_BEGIN + safe_ms = timer_ms; + CRITICAL_SECTION_END + + return safe_ms; +} diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk new file mode 100644 index 00000000..57a14150 --- /dev/null +++ b/hw/bsp/brtmm90x/family.mk @@ -0,0 +1,35 @@ + +CROSS_COMPILE = ft32-elf- +DEPS_SUBMODULES += hw/mcu/bridgetek/ft90x/hardware +SKIP_NANOLIB = 1 + +# This is installed at "C:/Program Files(x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware" +FT90X_SDK = $(TOP)/hw/mcu/bridgetek/ft90x/hardware + +CFLAGS += \ + -D__FT900__ \ + -fvar-tracking \ + -fvar-tracking-assignments \ + -fmessage-length=0 \ + -ffunction-sections \ + -DCFG_TUSB_MCU=OPT_MCU_FT90X + +# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration +CFLAGS += -Wno-error=shadow +CFLAGS:=$(filter-out -Wcast-function-type,$(CFLAGS)) + +# All source paths should be relative to the top level. +LDINC += $(FT90X_SDK)/lib/Release +LIBS += -lft900 +LD_FILE = hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld +LDFLAGS += $(addprefix -L,$(LDINC)) \ + -Xlinker --entry=_start \ + -Wl,-lc + +SRC_C += src/portable/bridgetek/ft90x/dcd_ft90x.c + +#SRC_S += hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S + +INC += \ + $(FT90X_SDK)/include \ + $(TOP)/$(BOARD_PATH) diff --git a/hw/mcu/bridgetek/ft90x/Readme.md b/hw/mcu/bridgetek/ft90x/Readme.md new file mode 100644 index 00000000..e197f182 --- /dev/null +++ b/hw/mcu/bridgetek/ft90x/Readme.md @@ -0,0 +1,6 @@ +# BridgeTek FT9xx MCU + +**BridgeTek** provides a hardware abstraction library with software source code for the SDKs for FT9xx software family. +The pre-built libraries and the source code can be redistributed. +Registers definition files `/include/registers/ft900_registers.h` and included peripheral register definition files have licenses that allow for redistribution. +Whole SDK repository is installed as part of the FT9xx Toolchain and can be downloaded from BridgeTek web page `https://www.brtchip.com` diff --git a/hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S b/hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S new file mode 100644 index 00000000..62fa266e --- /dev/null +++ b/hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S @@ -0,0 +1,286 @@ +.equ SYS_REGMSC0CFG_B3 , 0x1001b +.equ SYS_REGIRQCTL_B3 , 0x100e3 +.equ MAILBOX_MEMORY , 0x13000 + +.equ IS_IMG_SDBL_PRESENT, 0 +.equ IS_IMG_D2XX_PRESENT, 0 +.equ IS_IMG_DLOG_PRESENT, 0 + +.section .crt0 +.global _start + +_start: +# START Interrupt Vector Table [[ + jmp __PMSIZE-4 # RESET Vector + jmp interrupt_33 # Watchdog reset vector + jmp interrupt_0 + jmp interrupt_1 + jmp interrupt_2 + jmp interrupt_3 + jmp interrupt_4 + jmp interrupt_5 + jmp interrupt_6 + jmp interrupt_7 + jmp interrupt_8 + jmp interrupt_9 + jmp interrupt_10 + jmp interrupt_11 + jmp interrupt_12 + jmp interrupt_13 + jmp interrupt_14 + jmp interrupt_15 + jmp interrupt_16 + jmp interrupt_17 + jmp interrupt_18 + jmp interrupt_19 + jmp interrupt_20 + jmp interrupt_21 + jmp interrupt_22 + jmp interrupt_23 + jmp interrupt_24 + jmp interrupt_25 + jmp interrupt_26 + jmp interrupt_27 + jmp interrupt_28 + jmp interrupt_29 + jmp interrupt_30 + jmp interrupt_31 + jmp __PMSIZE-8 #Interrupt vector 32 (NMI) +# ]] END Interrupt Vector Table + +codestart: + jmp init + +.global _exithook +_exithook: # Debugger uses '_exithook' at 0x90 to catch program exit + return + +init: + # Disable all interrupts + ldk $r0,0x80 +.ifdef __FT930__ + sta.b 0x10123, $r0 +.else + sta.b 0x100e3,$r0 +.endif + + # Reset all peripherals + # lda.l $r0, 0x10018 + # bins.l $r0, $r0, 0x23F # Set bit 31 + # sta.l 0x10018, $r0 + + # Initialize DATA by copying from program memory + ldk.l $r0,__data_load_start + ldk.l $r1,__data_load_end + ldk.l $r2,0 # Will use __data after binutils patch + + jmp .dscopy +.dsloop: + # Copy PM[$r0] to RAM $r2 + lpmi.l $r3,$r0,0 + sti.l $r2,0,$r3 + add.l $r0,$r0,4 + add.l $r2,$r2,4 +.dscopy: + cmp.l $r0,$r1 + jmpc lt,.dsloop + + # Zero BSS + ldk.l $r0,_bss_start + ldk.l $r2,_end + sub.l $r2,$r2,$r0 + ldk.l $r1,0 + ldk $r3,32764 +1: + cmp $r2,$r3 + jmpc lt,2f + memset $r0,$r1,$r3 + add $r0,$r0,$r3 + sub $r2,$r2,$r3 + jmp 1b +2: + memset $r0,$r1,$r2 +.ifdef __FT930__ +/*##############################################################*/ + # copy UserConfig DATA from flash to mailbox memory +/*##############################################################*/ + ldk.l $r0,D2XX_Struct_start /*start of d2xx config in PM memory */ + ldk.l $r1,D2XX_Struct_end /*end of d2xx config in PM memory */ + ldk.l $r2,D2XXTEST_UserD2xxConfig /* RAM cache where the d2xx config from PM to be copied*/ + jmp .configcopy + +.configloop: + # Copy PM[$r0] to RAM[$r2] + lpmi.l $r3,$r0,0 + sti.l $r2,0,$r3 + # Increment + add.l $r0,$r0,4 + add.l $r2,$r2,4 +.configcopy: + cmp.l $r0,$r1 + jmpc lt,.configloop + + ldk.l $r1,D2XX_Struct_start + ldk.l $r2,D2XX_Struct_end + #compute size + sub.l $r2,$r2,$r1 + ldk.l $r1,D2XXTEST_UserD2xxConfig + ldk.l $r0,MAILBOX_MEMORY /* D2xx config from RAM cache to be copied to Mailbox memory */ + # Copy RAM[$r1] to Mailbox $r0, for $r2 bytes + streamouti.b $r0,$r1,$r2 +/*############################################################*/ +.endif + sub.l $sp,$sp,24 # Space for the caller argument frame + call main + +.equ EXITEXIT , 0x1fffc + +.global _exit +_exit: + sta.l EXITEXIT,$r0 # simulator end of test + jmp _exithook + +#_watchdog_isr: +# ldk $sp,__RAMSIZE +# jmp __PMSIZE-4 + +# Macro to construct the interrupt stub code. +# it just saves r0, loads r0 with the int vector +# and branches to interrupt_common. + +.macro inth i=0 +interrupt_\i: + push $r0 # { + lda $r0,(vector_table + 4 * \i) + jmp interrupt_common +.endm + + inth 0 + inth 1 + inth 2 + inth 3 + inth 4 + inth 5 + inth 6 + inth 7 + inth 8 + inth 9 + inth 10 + inth 11 + inth 12 + inth 13 + inth 14 + inth 15 + inth 16 + inth 17 + inth 18 + inth 19 + inth 20 + inth 21 + inth 22 + inth 23 + inth 24 + inth 25 + inth 26 + inth 27 + inth 28 + inth 29 + inth 30 + inth 31 + inth 32 + inth 33 + + # On entry: r0, already saved, holds the handler function +interrupt_common: + push $r1 # { + push $r2 # { + push $r3 # { + push $r4 # { + push $r5 # { + push $r6 # { + push $r7 # { + push $r8 # { + push $r9 # { + push $r10 # { + push $r11 # { + push $r12 # { + push $cc # { + + calli $r0 + + pop $cc # } + pop $r12 # } + pop $r11 # } + pop $r10 # } + pop $r9 # } + pop $r8 # } + pop $r7 # } + pop $r6 # } + pop $r5 # } + pop $r4 # } + pop $r3 # } + pop $r2 # } + pop $r1 # } + pop $r0 # } matching push in interrupt_0-31 above + reti + + # Null function for unassigned interrupt to point at +.global nullvector +nullvector: + return + +.section .data +.global vector_table + .align (4) # assembler alignment is in the power of 2 (in this case 2^4) +vector_table: + .rept 34 + .long nullvector + .endr + + +.section .text +.global __gxx_personality_sj0 +__gxx_personality_sj0: + + + .section ._flash_d2xx_config +.global __pD2XXDefaultConfiguration + .align (10) + +D2XX_partition_start = . + +.if IS_IMG_D2XX_PRESENT +.ifdef __FT930__ +.include "ft930_d2xx_default_config.inc" +.else +.include "ft900_d2xx_default_config.inc" +.endif +.endif + +D2XX_partition_end = . + + .section ._flash_dlog_partition + .align (10) +.global __dlog_partition +__dlog_partition: +dlog_partition_start = . +.if IS_IMG_DLOG_PRESENT + .long 0xF7D1D106 + .rept (0x1000-4) + .byte 0xFF + .endr +.endif +dlog_partition_end = . + + .section ._pm +.global __sdbl_partition_sizeof +.global __D2XX_partition_sizeof +.global __dlog_partition_sizeof + .if IS_IMG_SDBL_PRESENT +__sdbl_partition_sizeof = 0x2000 + .else +__sdbl_partition_sizeof = 0 + .endif + +__D2XX_partition_sizeof = D2XX_partition_end - D2XX_partition_start +__dlog_partition_sizeof = dlog_partition_end - dlog_partition_start diff --git a/hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld b/hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld new file mode 100644 index 00000000..d1b4d46c --- /dev/null +++ b/hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld @@ -0,0 +1,94 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-ft32") +OUTPUT_ARCH(ft32) +SEARCH_DIR("/data/win8/ft32/ft32-elf/lib"); +/* Allow the command line to override the memory region sizes. */ +__PMSIZE = DEFINED(__PMSIZE) ? __PMSIZE : 256K; +__RAMSIZE = DEFINED(__RAMSIZE) ? __RAMSIZE : 64K; +MEMORY +{ + flash (rx) : ORIGIN = 0, LENGTH = __PMSIZE + ram (rw!x) : ORIGIN = 0x800000, LENGTH = __RAMSIZE +} +SECTIONS +{ + .text : + { + *(.text*) + *(.strings) + *(._pm*) + *(.init) + *(.fini) + _etext = . ; + . = ALIGN(4); + } > flash + .tors : + { + ___ctors = . ; + *(.ctors) + ___ctors_end = . ; + ___dtors = . ; + *(.dtors) + ___dtors_end = . ; + . = ALIGN(4); + } > ram + .data : AT (ADDR (.text) + SIZEOF (.text)) + { + *(.data) + *(.data*) + *(.rodata) + *(.rodata*) + _edata = . ; + . = ALIGN(4); + } > ram + .bss SIZEOF(.data) + ADDR(.data) : + { + _bss_start = . ; + *(.bss) + *(.bss*) + *(COMMON) + _end = . ; + . = ALIGN(4); + } > ram + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + .stab 0 (NOLOAD) : + { + *(.stab) + } + .stabstr 0 (NOLOAD) : + { + *(.stabstr) + } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } +} diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index a35fc0ac..638a1781 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -151,6 +151,13 @@ #elif TU_CHECK_MCU(GD32VF103) #define DCD_ATTR_ENDPOINT_MAX 4 +//------------- BridgeTek -------------// +#elif TU_CHECK_MCU(FT90X) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(FT93X) + #define DCD_ATTR_ENDPOINT_MAX 16 + #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" #define DCD_ATTR_ENDPOINT_MAX 8 diff --git a/src/portable/bridgetek/ft90x/dcd_ft90x.c b/src/portable/bridgetek/ft90x/dcd_ft90x.c new file mode 100644 index 00000000..ac13f11d --- /dev/null +++ b/src/portable/bridgetek/ft90x/dcd_ft90x.c @@ -0,0 +1,1101 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" +#include "bsp/board.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_FT90X + +#define USBD_USE_STREAMS + +#include +#include +#include +#include + +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// Board code will determine the state of VBUS from USB host. +extern int8_t board_ft90x_vbus(void); + +// Static array to store an incoming SETUP request for processing by tinyusb. +static uint8_t _ft90x_setup_packet[8]; + +struct ft90x_xfer_state +{ + 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. + volatile uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid. + + 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. + uint16_t buff_size; // Actual size of buffer RAM used by endpoint. + uint16_t size; // Max packet size for endpoint from endpoint descriptor. +}; +// Endpoint description array for each endpoint. +static struct ft90x_xfer_state ep_xfer[USBD_MAX_ENDPOINT_COUNT]; +// USB speed. +static tusb_speed_t _speed; + +// Interrupt handlers. +void _ft90x_usbd_ISR(void); // Interrupt handler for USB device. +void ft90x_usbd_pm_ISR(void); // Interrupt handler for USB device for power management (called by board). + +// Internal functions forward declarations. +static uint16_t _ft90x_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes); +static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes); +static void _ft90x_reset_edpts(void); +static inline void _ft90x_phy_enable(bool en); +static void _ft90x_usb_speed(void); +static void _dcd_ft90x_attach(void); +static void _dcd_ft90x_detach(void) __attribute__((unused)); +static uint16_t _ft90x_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length); +static uint16_t _ft90x_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length); + +// Internal functions. + +// Manage an OUT transfer from the host. +// This can be up-to the maximum packet size of the endpoint. +// Continuation of a transfer beyond the maximum packet size is performed +// by the interrupt handler. +static uint16_t _ft90x_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes) +{ + //Note: this is called from only the interrupt handler when an OUT transfer is called. + uint16_t ep_size = ep_xfer[ep_number].size; + (void)ep_size; + if (xfer_bytes > ep_size) + { + xfer_bytes = ep_size; + } + + // Wait until the endpoint has finished - it should be complete! + //while (!(USBD_EP_SR_REG(ep_number) & MASK_USBD_EPxSR_OPRDY)) + //; + + // Send the first packet of max packet size + xfer_bytes = _ft90x_dusb_out(ep_number, (uint8_t *)buffer, xfer_bytes); + if (ep_number == USBD_EP_0) + { + // Set flags to indicate data ready. + USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_OPRDY); + } + else + { + USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_OPRDY); + } + + return xfer_bytes; +} + +// Manage an IN transfer to the host. +// This can be up-to the maximum packet size of the endpoint. +// Continuation of a transfer beyond the maximum packet size is performed +// by the interrupt handler. +static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes) +{ + //Note: this may be called from the interrupt handler or from normal code. + uint8_t end = 0; + uint16_t ep_size = ep_xfer[ep_number].size; + (void)ep_size; + if ((xfer_bytes == 0) || (xfer_bytes < ep_size)) + { + end = 1; + } + else + { + xfer_bytes = ep_size; + } + + if (ep_number == USBD_EP_0) + { + // An IN direction SETUP can be interrupted by an OUT packet. + // This will result in a STALL generated by the silicon. + while (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_STALL) + { + // Clear the STALL and finish the transaction. + USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_STALL); + } + } + else + { + uint8_t sr_reg; + // If there is data to transmit then wait until the IN buffer + // for the endpoint is empty. + do + { + sr_reg = USBD_EP_SR_REG(ep_number); + } while (sr_reg & MASK_USBD_EPxSR_INPRDY); + + } + + xfer_bytes = _ft90x_dusb_in(ep_number, (uint8_t *)buffer, xfer_bytes); + + if (ep_number == USBD_EP_0) + { + if (end) + { + // Set flags to indicate data ready and transfer complete. + USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_INPRDY | MASK_USBD_EP0SR_DATAEND; + } + else + { + // Set flags to indicate data ready. + USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_INPRDY); + } + } + else + { + // Set flags to indicate data ready. + USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_INPRDY); + } + + return xfer_bytes; +} + +// Reset all endpoints to a default state. +// Control endpoint enabled and ready. All others disabled. +static void _ft90x_reset_edpts(void) +{ + // Disable all endpoints and remove configuration values. + // Clear settings. + tu_memclr(ep_xfer, sizeof(ep_xfer)); + for (int i = 0; i < USBD_MAX_ENDPOINT_COUNT; i++) + { + // Disable hardware. + USBD_EP_CR_REG(i) = 0; + } + + // Setup the control endpoint only. +#if CFG_TUD_ENDPOINT0_SIZE == 64 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_64 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 32 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_32 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 16 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_16 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 8 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_8 << BIT_USBD_EP0_MAX_SIZE); +#else +#error "CFG_TUD_ENDPOINT0_SIZE must be defined with a value of 8, 16, 32 or 64." +#endif + // Configure the control endpoint. + ep_xfer[USBD_EP_0].size = CFG_TUD_ENDPOINT0_SIZE; + ep_xfer[USBD_EP_0].type = TUSB_XFER_CONTROL; + + // Enable interrupts from USB device control. + USBD_REG(cmie) = MASK_USBD_CMIE_ALL; + // Enable interrupts on EP0. + USBD_REG(epie) = (MASK_USBD_EPIE_EP0IE); +} + +// Enable or disable the USB PHY. +static inline void _ft90x_phy_enable(bool en) +{ + if (en) + SYS->PMCFG_L |= MASK_SYS_PMCFG_DEV_PHY_EN; + else + SYS->PMCFG_L &= ~MASK_SYS_PMCFG_DEV_PHY_EN; +} + +// Safely connect to the USB. +static void _dcd_ft90x_attach(void) +{ + uint8_t reg; + + CRITICAL_SECTION_BEGIN + // Disable device responses. + USBD_REG(faddr) = 0; + + // Reset USB Device. + SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL; + // Disable device connect/disconnect/host reset detection. + SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_DIS_DEV; + SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_CONN_DEV; + SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN); + + // Enable Chip USB device clock/PM configuration. + sys_enable(sys_device_usb_device); + CRITICAL_SECTION_END; + + // Wait a short time to get started. + delayms(1); + + CRITICAL_SECTION_BEGIN + // Turn off the device enable bit. +#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED + USBD_REG(fctrl) = 0; +#else + //Set the full speed only bit if required. + USBD_REG(fctrl) = MASK_USBD_FCTRL_MODE_FS_ONLY; +#endif + + // Clear first reset and suspend interrupts. + do + { + reg = USBD_REG(cmif); + USBD_REG(cmif) = reg; + } while (reg); + // Clear any endpoint interrupts. + reg = USBD_REG(epif); + USBD_REG(epif) = reg; + + // Disable all interrupts from USB device control before attaching interrupt. + USBD_REG(cmie) = 0; + CRITICAL_SECTION_END; + + // Enable device connect/disconnect/host reset detection. + // Set device detect and remote wakeup enable interrupt enables. + SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN; + +#if defined(__FT930__) + // Setup VBUS detect + SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN; +#endif +} + +// Gracefully disconnect from the USB. +static void _dcd_ft90x_detach(void) +{ + // Disable device connect/disconnect/host reset detection. + SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN); + +#if defined(__FT930__) + // Disable VBUS detection. + SYS->MSC0CFG = SYS->MSC0CFG & (~MASK_SYS_MSC0CFG_USB_VBUS_EN); +#endif + CRITICAL_SECTION_BEGIN + USBD_REG(epie) = 0; + USBD_REG(cmie) = 0; + CRITICAL_SECTION_END; + + // Disable the USB function. + USBD_REG(fctrl) = 0; + delayms(1); + + // Disable USB PHY + dcd_disconnect(0); + delayms(1); + + // Disable Chip USB device clock/PM configuration. + sys_disable(sys_device_usb_device); + + // Reset USB Device... Needed for Back voltage D+ to be <400mV + SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL; + + delayms(1); + // Set device detect and remote wakeup enable interrupt enables. + SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN; + +#if defined(__FT930__) + // Setup VBUS detect + SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN; +#endif +} + +// Determine the speed of the USB to which we are connected. +// Set the speed of the PHY accordingly. +// High speed can be disabled through CFG_TUSB_RHPORT0_MODE settings. +static void _ft90x_usb_speed(void) +{ + uint8_t fctrl_val; + + // If USB device function is already enabled then disable it. + if (USBD_REG(fctrl) & MASK_USBD_FCTRL_USB_DEV_EN) { + USBD_REG(fctrl) = (USBD_REG(fctrl) & (~MASK_USBD_FCTRL_USB_DEV_EN)); + delayus(200); + } + +#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED + + /* Detect high or full speed */ + fctrl_val = MASK_USBD_FCTRL_USB_DEV_EN; +#if defined(__FT900__) + if (!sys_check_ft900_revB())//if 90x series is rev C + { + fctrl_val |= MASK_USBD_FCTRL_IMP_PERF; + } +#endif + USBD_REG(fctrl) = fctrl_val; + +#if defined(__FT930__) + delayus(200); + + _speed = (SYS->MSC0CFG & MASK_SYS_MSC0CFG_HIGH_SPED_MODE) ? + TUSB_SPEED_HIGH : TUSB_SPEED_FULL; +#else /* __FT930__ */ + /* Detection by SOF */ + while (!(USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ)); + USBD_REG(cmif) = MASK_USBD_CMIF_SOFIRQ; + delayus(125 + 5); + _speed = (USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ) ? + TUSB_SPEED_HIGH : TUSB_SPEED_FULL; + dcd_event_bus_reset(0, _speed, true); + +#endif /* !__FT930__ */ + +#else /* CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED */ + + /* User force set to full speed */ + _speed = TUSB_SPEED_FULL; + fctrl_val = + MASK_USBD_FCTRL_USB_DEV_EN | MASK_USBD_FCTRL_MODE_FS_ONLY; +#if defined(__FT900__) + if (!sys_check_ft900_revB())//if 90x series is rev C + { + fctrl_val |= MASK_USBD_FCTRL_IMP_PERF; + } +#endif + USBD_REG(fctrl) = fctrl_val; + dcd_event_bus_reset(0, _speed, true); + return; + +#endif /* CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED */ +} + +// Send a buffer to the USB IN FIFO. +// When the macro USBD_USE_STREAMS is defined this will stream a buffer of data +// to the FIFO using the most efficient MCU streamout combination. +// If streaming is disabled then it will send each byte of the buffer in turn +// to the FIFO. The is no reason to not stream. +// The total number of bytes sent to the FIFO is returned. +static uint16_t _ft90x_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length) +{ + uint16_t bytes_read = 0; + uint16_t buff_size = length; + +#ifdef USBD_USE_STREAMS + volatile uint8_t *data_reg; + + data_reg = (uint8_t *)&(USBD->ep[ep_number].epxfifo); + if (buff_size) + { + if (((uint32_t)buffer) % 4 == 0) + { + uint16_t aligned = buff_size & (~3); + uint16_t left = buff_size & 3; + + if (aligned) + { + __asm__ volatile("streamout.l %0,%1,%2" + : + : "r"(data_reg), "r"(buffer), "r"(aligned)); + buffer += aligned; + } + if (left) + { + __asm__ volatile("streamout.b %0,%1,%2" + : + : "r"(data_reg), "r"(buffer), "r"(left)); + } + } + else + { + __asm__ volatile("streamout.b %0,%1,%2" + : + : "r"(data_reg), "r"(buffer), "r"(buff_size)); + } + bytes_read = buff_size; + } +#else // USBD_USE_STREAMS + + bytes_read = buff_size; + while (buff_size--) + { + USBD_EP_FIFO_REG(ep_number) = *buffer++; + }; + +#endif // USBD_USE_STREAMS + + return bytes_read; +} + +// Receive a buffer from the USB OUT FIFO. +// When the macro USBD_USE_STREAMS is defined this will stream from the FIFO +// to a buffer of data using the most efficient MCU streamin combination. +// If streaming is disabled then it will receive each byte from the FIFO in turn +// to the buffer. The is no reason to not stream. +// The total number of bytes received from the FIFO is returned. +static uint16_t _ft90x_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length) +{ +#ifdef USBD_USE_STREAMS + volatile uint8_t *data_reg; +#endif // USBD_USE_STREAMS + uint16_t bytes_read = 0; + uint16_t buff_size = length; + + if (length > 0) + { + if (ep_number == USBD_EP_0) + { + buff_size = USBD_EP_CNT_REG(USBD_EP_0); + } + else + { + if (USBD_EP_SR_REG(ep_number) & (MASK_USBD_EPxSR_OPRDY)) + { + buff_size = USBD_EP_CNT_REG(ep_number); + } + } + } + + // Only read as many bytes as we have space for. + if (buff_size > length) + buff_size = length; + +#ifdef USBD_USE_STREAMS + data_reg = (uint8_t *)&(USBD->ep[ep_number].epxfifo); + if (buff_size) + { + if ((uint32_t)buffer % 4 == 0) + { + uint16_t aligned = buff_size & (~3); + uint16_t left = buff_size & 3; + + if (aligned) + { + __asm__ volatile("streamin.l %0,%1,%2" + : + : "r"(buffer), "r"(data_reg), "r"(aligned)); + buffer += aligned; + } + if (left) + { + __asm__ volatile("streamin.b %0,%1,%2" + : + : "r"(buffer), "r"(data_reg), "r"(left)); + } + } + else + { + __asm__ volatile("streamin.b %0,%1,%2" + : + : "r"(buffer), "r"(data_reg), "r"(buff_size)); + } + bytes_read = buff_size; + } +#else // USBD_USE_STREAMS + + bytes_read = buff_size; + while (buff_size--) + { + *buffer++ = USBD_EP_FIFO_REG(ep_number); + } + +#endif // USBD_USE_STREAMS + + return bytes_read; +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ + +// Initialize controller to device mode +void dcd_init(uint8_t rhport) +{ + TU_LOG2("FT90x initialisation\r\n"); + + _dcd_ft90x_attach(); + + //_ft90x_reset_edpts(void);//tu_memclr(ep_xfer, sizeof(ep_xfer)); + + interrupt_attach(interrupt_usb_device, (int8_t)interrupt_usb_device, _ft90x_usbd_ISR); + + dcd_connect(rhport); +} + +// Enable device interrupt +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + TU_LOG3("FT90x int enable\r\n"); + + // Peripheral devices interrupt enable. + interrupt_enable_globally(); +} + +// Disable device interrupt +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + TU_LOG3("FT90x int disable\r\n"); + + // Peripheral devices interrupt disable. + interrupt_disable_globally(); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + (void)dev_addr; + + // Respond with status. There is no checking that the address is in range. + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + + // Set the update bit for the address register. + dev_addr |= 0x80; + + // Modify the address register within a critical section. + CRITICAL_SECTION_BEGIN + { + USBD_REG(faddr) = dev_addr; + } + CRITICAL_SECTION_END; +} + +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +#if 0 // never called +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) + { + if (request->bRequest == TUSB_REQ_SET_ADDRESS) + { + } + else if (request->bRequest == TUSB_REQ_SET_CONFIGURATION) + { + } + } +} +#endif // 0 + +// Wake up host +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + + SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RMWAKEUP; + + // Atleast 2 ms of delay needed for RESUME Data K state. + delayms(2); + + SYS->MSC0CFG &= ~MASK_SYS_MSC0CFG_DEV_RMWAKEUP; + + // Enable USB PHY and determine current bus speed. + dcd_connect(0); +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + TU_LOG2("FT90x connect\r\n"); + + CRITICAL_SECTION_BEGIN + // Is device connected? + if (board_ft90x_vbus()) + { + // Clear/disable address register. + USBD_REG(faddr) = 0; + _ft90x_phy_enable(true); + + // Determine bus speed and signal speed to tusb. + _ft90x_usb_speed(); + } + CRITICAL_SECTION_END; + + // Restore default endpoint state. + _ft90x_reset_edpts(); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + TU_LOG2("FT90x disconnect\r\n"); + + // Disable the USB PHY. + _ft90x_phy_enable(false); +} + + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc) +{ + (void)rhport; + uint8_t const ep_number = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint8_t const ep_type = ep_desc->bmAttributes.xfer; + uint16_t const ep_size = ep_desc->wMaxPacketSize.size; + uint16_t ep_buff_size; + uint8_t ep_reg_size = USBD_EP_MAX_SIZE_8; + uint8_t ep_reg_data = 0; + int16_t total_ram; + + TU_LOG2("FT90x endpoint open %d %c\r\n", ep_number, ep_dir?'I':'O'); + + // Check that the requested endpoint number is allowable. + if (ep_number >= USBD_MAX_ENDPOINT_COUNT) + { + TU_LOG1("FT90x endpoint not valid: requested %d max %d\r\n", ep_number, USBD_MAX_ENDPOINT_COUNT); + return false; + } + + // Calculate the physical size of the endpoint as a power of 2. This may be more than + // the requested size. + while (ep_desc->wMaxPacketSize.size > (8 * (1 << ep_reg_size))) + { + ep_reg_size++; + } + if (ep_reg_size > USBD_EP_MAX_SIZE_1024) + { + TU_LOG1("FT90x endpoint size not valid: requested %d max 1024\r\n", ep_desc->wMaxPacketSize.size); + return false; + } + // Calculate actual amount of buffer RAM used by this endpoint. This may be more than the + // requested size. + ep_buff_size = 8 << ep_reg_size; + + if (ep_number > 0) + { + // Set EP cmd parameters... + ep_reg_data |= (ep_reg_size << BIT_USBD_EP_MAX_SIZE); + + if (ep_xfer[ep_number].type != USBD_EP_TYPE_DISABLED) + { + // This could be because an endpoint has been assigned with the same number. + // On FT90x, IN and OUT endpoints may not have the same number. e.g. There + // cannot been an 0x81 and 0x01 endpoint. + TU_LOG1("FT90x endpoint %d already assigned\r\n", ep_number); + return false; + } + + // Check that there is enough buffer RAM to allocate to this new endpoint. + // Available buffer RAM depends on the device revision. + // The IN and OUT buffer RAM should be the same size. + if (ep_dir == USBD_DIR_IN) + total_ram = USBD_RAMTOTAL_IN; + else + total_ram = USBD_RAMTOTAL_OUT; + // Work out how much has been allocated to existing endpoints. + // The total RAM allocated shoudl alsyes be a positive number as this + // algorithm should not let it go below zero. + for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++) + { + if (ep_xfer[i].type != USBD_EP_TYPE_DISABLED) + { + if (ep_xfer[i].dir == ep_dir) + { + total_ram -= ep_xfer[i].buff_size; + } + } + } + // The control endpoint is taken into account as well. + total_ram -= ep_xfer[0].buff_size; + // Make sure we have enough space. The corner case is having zero bytes + // free which means that total_ram must be signed as zero bytes free is + // allowable. + if (total_ram < ep_buff_size) + { + TU_LOG1("FT90x insufficient buffer RAM for endpoint %d\r\n", ep_number); + return false; + } + + // Set the type of this endpoint in the control register. + if (ep_type == USBD_EP_BULK) + ep_reg_data |= (USBD_EP_DIS_BULK << BIT_USBD_EP_CONTROL_DIS); + else if (ep_type == USBD_EP_INT) + ep_reg_data |= (USBD_EP_DIS_INT << BIT_USBD_EP_CONTROL_DIS); + else if (ep_type == USBD_EP_ISOC) + ep_reg_data |= (USBD_EP_DIS_ISO << BIT_USBD_EP_CONTROL_DIS); + // Set the direction of this endpoint in the control register. + if (ep_dir == USBD_DIR_IN) + ep_reg_data |= MASK_USBD_EPxCR_DIR; + // Do not perform double buffering. + //if ( != USBD_DB_OFF) + //ep_reg_data |= MASK_USBD_EPxCR_DB; + // Set the control endpoint for this endpoint. + USBD_EP_CR_REG(ep_number) = ep_reg_data; + TU_LOG2("FT90x endpoint setting %x\r\n", ep_reg_data); + } + else + { + // Set the control register for endpoint zero. + USBD_EP_CR_REG(USBD_EP_0) = (ep_reg_size << BIT_USBD_EP0_MAX_SIZE); + } + + // 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; + ep_xfer[ep_number].total_size = 0; + ep_xfer[ep_number].remain_size = 0; + CRITICAL_SECTION_END + + return true; +} + +// Close all endpoints. +void dcd_edpt_close_all(uint8_t rhport) +{ + (void)rhport; + // Reset the endpoint configurations. + _ft90x_reset_edpts(); +} + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + uint8_t ep_number = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); + uint16_t xfer_bytes; + bool status = false; + + // We will attempt to transfer the buffer. If it is less than or equal to the endpoint + // maximum packet size then the whole buffer will be transferred. If it is larger then + // the interrupt handler will transfer the remainder. + // ep_xfer is used to tell the interrupt handler what to do. + // ep_xfer can be used at interrupt level to continue transfers. + CRITICAL_SECTION_BEGIN + // 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) + { + ep_xfer[USBD_EP_0].dir = dir; + } + else + { + // Enable the interrupt for this endpoint allowing the interrupt handler to report + // continue the transfer and signal completion. + USBD_REG(epie) = USBD_REG(epie) | (1 << ep_number); + } + + if (dir == TUSB_DIR_IN) + { + // For IN transfers send the first packet as a starter. Interrupt handler to complete + // this if it is larger than one packet. + xfer_bytes = _ft90x_edpt_xfer_in(ep_number, buffer, total_bytes); + + ep_xfer[ep_number].buff_ptr += xfer_bytes; + ep_xfer[ep_number].remain_size -= xfer_bytes; + } + } + CRITICAL_SECTION_END + + return status; +} + +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) +{ + (void)rhport; + (void)ep_addr; + (void)ff; + (void)total_bytes; + bool status = false; + return status; +} + +// Stall endpoint (non-control endpoint) +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t ep_number = tu_edpt_number(ep_addr); + (void)rhport; + + CRITICAL_SECTION_BEGIN + if (ep_number == USBD_EP_0) + { + USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) | + MASK_USBD_EP0CR_SDSTL; + } + else + { + USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) | + MASK_USBD_EPxCR_SDSTL; + USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE | + MASK_USBD_EPxSR_FIFO_FLUSH; + } + CRITICAL_SECTION_END +} + +// Clear stall (non-control endpoint), data toggle is also reset to DATA0 +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t ep_number = tu_edpt_number(ep_addr); + (void)rhport; + + if (ep_number > USBD_EP_0) + { + CRITICAL_SECTION_BEGIN + USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) & + (~MASK_USBD_EPxCR_SDSTL); + USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE; + + // Allow transfers to restart. + ep_xfer[ep_number].valid = 0; + ep_xfer[ep_number].remain_size = 0; + CRITICAL_SECTION_END + } +} + +// Interrupt handling. + +void _ft90x_usbd_ISR(void) +{ + tud_int_handler(0); // Resolves to dcd_int_handler(). +} + +void dcd_int_handler(uint8_t rhport) +{ + (void)rhport; + + // Read the Common Interrupt Flag Register. + uint8_t cmif = USBD_REG(cmif); + // Read the Endpoint Interrupt Flag Register. +#if defined(__FT930__) + // This is 16 bits on FT93x. + uint16_t epif = USBD_REG(epif); +#else + // This is 8 bits on FT90x. + uint8_t epif = USBD_REG(epif); +#endif + + if (cmif & MASK_USBD_CMIF_ALL) + { + // Clear all CMIF bits. + USBD_REG(cmif) = MASK_USBD_CMIF_ALL; + if (cmif & MASK_USBD_CMIF_PHYIRQ) //Handle PHY interrupt + { + } + if (cmif & MASK_USBD_CMIF_PIDIRQ) //Handle PIDIRQ interrupt + { + } + if (cmif & MASK_USBD_CMIF_CRC16IRQ) //Handle CRC16IRQ interrupt + { + } + if (cmif & MASK_USBD_CMIF_CRC5IRQ) //Handle CRC5 interrupt + { + } + if (cmif & MASK_USBD_CMIF_RSTIRQ) //Handle Reset interrupt + { + // Reset endpoints to default state. + _ft90x_reset_edpts(); + dcd_event_bus_reset(0, _speed, true); + } + if (cmif & MASK_USBD_CMIF_SUSIRQ) //Handle Suspend interrupt + { + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + if (cmif & MASK_USBD_CMIF_RESIRQ) //Handle Resume interrupt + { + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + if (cmif & MASK_USBD_CMIF_SOFIRQ) //Handle SOF interrupt + { + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } + } + // Handle endpoint interrupts. + if (epif) + { + uint16_t xfer_bytes; + + // Check for EP0 interrupts pending. + if (epif & MASK_USBD_EPIF_EP0IRQ) + { + // 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) + { + // If protocol STALL, End the STALL signalling. + if (USBD_EP_CR_REG(USBD_EP_0) & MASK_USBD_EP0CR_SDSTL) + { + // STALL end. + USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) & + (~MASK_USBD_EP0CR_SDSTL); + // Clear STALL send. + USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_STALL; + } + + // 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. + dcd_event_setup_received(0, _ft90x_setup_packet, true); + + // Clear the interrupt that signals a SETUP packet is received. + USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP); + + // Allow new transfers on the control endpoint. + ep_xfer[USBD_EP_0].valid = 0; + return; + } + else + { + // Check for a complete or partially complete transfers on EP0. + if (ep_xfer[USBD_EP_0].valid) + { + xfer_bytes = (uint16_t)ep_xfer[USBD_EP_0].total_size; + + // 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); + } + // Now signal completion of data packet. + dcd_event_xfer_complete(0, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true); + + // Allow new transfers on the control endpoint. + ep_xfer[USBD_EP_0].valid = 0; + } + } + } + else // !(epif & MASK_USBD_EPIF_EP0IRQ) + { + // Mask out currently disabled endpoints. + epif &= USBD_REG(epie); + + // Handle complete and partially complete transfers for each endpoint. + for (uint8_t ep_number = 1; ep_number < USBD_MAX_ENDPOINT_COUNT; ep_number++) + { + if ((epif & MASK_USBD_EPIF_IRQ(ep_number)) == 0) + { + // No pending interrupt for this endpoint. + continue; + } + + if (ep_xfer[ep_number].valid) + { + xfer_bytes = 0; + uint8_t ep_dirmask = (ep_xfer[ep_number].dir ? TUSB_DIR_IN_MASK : 0); + + // Clear interrupt register for this endpoint. + USBD_REG(epif) = MASK_USBD_EPIF_IRQ(ep_number); + + // Start or continue an OUT transfer. + 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, + (uint16_t)ep_xfer[ep_number].remain_size); + + ep_xfer[ep_number].buff_ptr += xfer_bytes; + ep_xfer[ep_number].remain_size -= xfer_bytes; + } + // continue an IN transfer + else // if (ep_xfer[ep_number].dir == TUSB_DIR_IN) + { + if (ep_xfer[ep_number].remain_size > 0) + { + xfer_bytes = _ft90x_edpt_xfer_in(ep_number, + (uint8_t *)ep_xfer[ep_number].buff_ptr, + (uint16_t)ep_xfer[ep_number].remain_size); + + ep_xfer[ep_number].buff_ptr += xfer_bytes; + ep_xfer[ep_number].remain_size -= xfer_bytes; + } + } + + // When the transfer is complete... + if (ep_xfer[ep_number].remain_size == 0) + { + // Signal tinyUSB. + dcd_event_xfer_complete(0, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true); + + // Allow new transfers on this endpoint. + ep_xfer[ep_number].valid = 0; + + // Disable the interrupt for this endpoint now it is complete. + USBD_REG(epie) = USBD_REG(epie) & (~(1 << ep_number)); + } + } + } + } + } +} + +// Power management interrupt handler. +// This handles USB device related power management interrupts only. +void ft90x_usbd_pm_ISR(void) +{ + uint16_t pmcfg = SYS->PMCFG_H; + + // Main interrupt handler is responible for + if (pmcfg & MASK_SYS_PMCFG_DEV_CONN_DEV) + { + // Signal connection interrupt + SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + + if (pmcfg & MASK_SYS_PMCFG_DEV_DIS_DEV) + { + // Signal disconnection interrupt + SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + if (pmcfg & MASK_SYS_PMCFG_HOST_RST_DEV) + { + // Signal Host Reset interrupt + SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } + + if (pmcfg & MASK_SYS_PMCFG_HOST_RESUME_DEV) + { + // Signal Host Resume interrupt + SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; + if (!(SYS->MSC0CFG & MASK_SYS_MSC0CFG_DEV_RMWAKEUP)) + { + // If we are driving K-state on Device USB port; + // We must maintain the 1ms requirement before resuming the phy + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + } +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index a00f3489..d04cb54f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -126,6 +126,10 @@ // GigaDevice #define OPT_MCU_GD32VF103 1600 ///< GigaDevice GD32VF103 +// BridgeTek +#define OPT_MCU_FT90X 1700 ///< BridgeTek FT90x +#define OPT_MCU_FT93X 1701 ///< BridgeTek FT93x + //--------------------------------------------------------------------+ // Supported OS //--------------------------------------------------------------------+ From bcecbfdc29f58ac019a36099a8c398650cd27191 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 6 Oct 2021 09:15:33 +0100 Subject: [PATCH 02/16] Modify cdc_msc example for Bridgetek FT90x/FT93x Add in endpoint definitions for the Bridgetek devices in usb_descriptors.c and allow high speed in tusb_config.h. --- examples/device/cdc_msc/src/tusb_config.h | 3 ++- examples/device/cdc_msc/src/usb_descriptors.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index bf6af06b..2bf5248b 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,8 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X || \ + CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X ) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 1a89ce56..565a5d60 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -116,6 +116,16 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x84 +#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X + // FT9XX 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_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x83 + + #define EPNUM_MSC_OUT 0x04 + #define EPNUM_MSC_IN 0x85 + #else #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 From 37c5eeb51de532dfbd46ae528d4d99220932d6bd Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 6 Oct 2021 16:50:55 +0100 Subject: [PATCH 03/16] Rename directories to indicate that FT930 and FT900 devices are both covered by the same SDK and src/portable code. Board makefile includes __FT900__ macro for FT90x and __FT930__ macro for boards with FT93x. --- hw/bsp/brtmm90x/family.c | 6 +++--- hw/bsp/brtmm90x/family.mk | 14 +++++++------- hw/mcu/bridgetek/{ft90x => ft9xx}/Readme.md | 7 ++++--- .../{ft90x => ft9xx}/hardware/scripts/crt0.S | 0 .../{ft90x => ft9xx}/hardware/scripts/ldscript.ld | 0 .../{ft90x/dcd_ft90x.c => ft9xx/dcd_ft9xx.c} | 2 -- 6 files changed, 14 insertions(+), 15 deletions(-) rename hw/mcu/bridgetek/{ft90x => ft9xx}/Readme.md (52%) rename hw/mcu/bridgetek/{ft90x => ft9xx}/hardware/scripts/crt0.S (100%) rename hw/mcu/bridgetek/{ft90x => ft9xx}/hardware/scripts/ldscript.ld (100%) rename src/portable/bridgetek/{ft90x/dcd_ft90x.c => ft9xx/dcd_ft9xx.c} (99%) diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 010704d9..6352f232 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -28,7 +28,6 @@ #include #include "bsp/board.h" #include "board.h" -//#include "src/device/dcd.h" #if TUSB_OPT_DEVICE_ENABLED int8_t board_ft90x_vbus(void); // Board specific implementation of VBUS detection for USB device. @@ -67,16 +66,17 @@ void board_init(void) #if 1 gpio_function(GPIO_ETH_LED0, pad_gpio4); /* ETH LED0 */ gpio_dir(GPIO_ETH_LED0, pad_dir_open_drain); - gpio_function(GPIO_ETH_LED1, pad_gpio5); /* ETH LED0 */ + gpio_function(GPIO_ETH_LED1, pad_gpio5); /* ETH LED1 */ gpio_dir(GPIO_ETH_LED1, pad_dir_output); #endif + sys_enable(sys_device_timer_wdt); - interrupt_attach(interrupt_timers, (int8_t)interrupt_timers, timer_ISR); /* Timer A = 1ms */ timer_prescaler(timer_select_a, 1000); timer_init(timer_select_a, 100, timer_direction_down, timer_prescaler_select_on, timer_mode_continuous); timer_enable_interrupt(timer_select_a); timer_start(timer_select_a); + interrupt_attach(interrupt_timers, (int8_t)interrupt_timers, timer_ISR); // Setup VBUS detect GPIO. If the device is connected then this // will set the MASK_SYS_PMCFG_DEV_DETECT_EN bit in PMCFG. diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk index 57a14150..42769c25 100644 --- a/hw/bsp/brtmm90x/family.mk +++ b/hw/bsp/brtmm90x/family.mk @@ -1,10 +1,10 @@ CROSS_COMPILE = ft32-elf- -DEPS_SUBMODULES += hw/mcu/bridgetek/ft90x/hardware +DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/hardware SKIP_NANOLIB = 1 # This is installed at "C:/Program Files(x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware" -FT90X_SDK = $(TOP)/hw/mcu/bridgetek/ft90x/hardware +FT9XX_SDK = $(TOP)/hw/mcu/bridgetek/ft9xx/hardware CFLAGS += \ -D__FT900__ \ @@ -19,17 +19,17 @@ CFLAGS += -Wno-error=shadow CFLAGS:=$(filter-out -Wcast-function-type,$(CFLAGS)) # All source paths should be relative to the top level. -LDINC += $(FT90X_SDK)/lib/Release +LDINC += $(FT9XX_SDK)/lib/Release LIBS += -lft900 -LD_FILE = hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld +LD_FILE = hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld LDFLAGS += $(addprefix -L,$(LDINC)) \ -Xlinker --entry=_start \ -Wl,-lc -SRC_C += src/portable/bridgetek/ft90x/dcd_ft90x.c +SRC_C += src/portable/bridgetek/ft9xx/dcd_ft9xx.c -#SRC_S += hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S +#SRC_S += hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S INC += \ - $(FT90X_SDK)/include \ + $(FT9XX_SDK)/include \ $(TOP)/$(BOARD_PATH) diff --git a/hw/mcu/bridgetek/ft90x/Readme.md b/hw/mcu/bridgetek/ft9xx/Readme.md similarity index 52% rename from hw/mcu/bridgetek/ft90x/Readme.md rename to hw/mcu/bridgetek/ft9xx/Readme.md index e197f182..1db91058 100644 --- a/hw/mcu/bridgetek/ft90x/Readme.md +++ b/hw/mcu/bridgetek/ft9xx/Readme.md @@ -1,6 +1,7 @@ # BridgeTek FT9xx MCU **BridgeTek** provides a hardware abstraction library with software source code for the SDKs for FT9xx software family. -The pre-built libraries and the source code can be redistributed. -Registers definition files `/include/registers/ft900_registers.h` and included peripheral register definition files have licenses that allow for redistribution. -Whole SDK repository is installed as part of the FT9xx Toolchain and can be downloaded from BridgeTek web page `https://www.brtchip.com` + +Whole SDK repository is installed as part of the FT9xx Toolchain and can be downloaded from BridgeTek web page `https://www.brtchip.com`. + +Registers definition files, and included peripheral register definition files have licenses that allow for redistribution. diff --git a/hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S b/hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S similarity index 100% rename from hw/mcu/bridgetek/ft90x/hardware/scripts/crt0.S rename to hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S diff --git a/hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld b/hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld similarity index 100% rename from hw/mcu/bridgetek/ft90x/hardware/scripts/ldscript.ld rename to hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld diff --git a/src/portable/bridgetek/ft90x/dcd_ft90x.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c similarity index 99% rename from src/portable/bridgetek/ft90x/dcd_ft90x.c rename to src/portable/bridgetek/ft9xx/dcd_ft9xx.c index ac13f11d..69b51fac 100644 --- a/src/portable/bridgetek/ft90x/dcd_ft90x.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -524,8 +524,6 @@ void dcd_init(uint8_t rhport) _dcd_ft90x_attach(); - //_ft90x_reset_edpts(void);//tu_memclr(ep_xfer, sizeof(ep_xfer)); - interrupt_attach(interrupt_usb_device, (int8_t)interrupt_usb_device, _ft90x_usbd_ISR); dcd_connect(rhport); From 9966b8a5d6d755c6b92140d617122acb39948f20 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 6 Oct 2021 16:54:52 +0100 Subject: [PATCH 04/16] Change author in header to Bridgetek Pte Ltd. --- hw/bsp/brtmm90x/boards/mm900ev1b/board.h | 2 +- hw/bsp/brtmm90x/family.c | 2 +- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/bsp/brtmm90x/boards/mm900ev1b/board.h b/hw/bsp/brtmm90x/boards/mm900ev1b/board.h index dfb56628..67f61237 100644 --- a/hw/bsp/brtmm90x/boards/mm900ev1b/board.h +++ b/hw/bsp/brtmm90x/boards/mm900ev1b/board.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021, Ha Thach (tinyusb.org) + * Copyright 2021 Bridgetek Pte Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 6352f232..3bd16b81 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright 2019 Sony Semiconductor Solutions Corporation + * Copyright 2021 Bridgetek Pte Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 69b51fac..6dbef161 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright 2021 Bridgetek Pte Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 8c40a74f295d93a62a0e7c8a873b6d7abcce19b1 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 6 Oct 2021 17:13:44 +0100 Subject: [PATCH 05/16] Sort out board settings. --- .../boards/{mm900ev1b => mm900evxb}/board.h | 14 ++++---------- hw/bsp/brtmm90x/family.c | 6 +++--- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 3 ++- 3 files changed, 9 insertions(+), 14 deletions(-) rename hw/bsp/brtmm90x/boards/{mm900ev1b => mm900evxb}/board.h (85%) diff --git a/hw/bsp/brtmm90x/boards/mm900ev1b/board.h b/hw/bsp/brtmm90x/boards/mm900evxb/board.h similarity index 85% rename from hw/bsp/brtmm90x/boards/mm900ev1b/board.h rename to hw/bsp/brtmm90x/boards/mm900evxb/board.h index 67f61237..57936fda 100644 --- a/hw/bsp/brtmm90x/boards/mm900ev1b/board.h +++ b/hw/bsp/brtmm90x/boards/mm900evxb/board.h @@ -27,27 +27,21 @@ #ifndef BOARD_H_ #define BOARD_H_ +// Note: This definition file covers all MM900EV1B, MM900EV2B, and MM900EV3B boards. +// Each of these boards has an FT900 device. + #ifdef __cplusplus extern "C" { #endif -#if defined(__FT900__) #define GPIO_UART0_TX 48 #define GPIO_UART0_RX 49 #define GPIO_ETH_LED0 61 #define GPIO_ETH_LED1 62 #define GPIO_REMOTE_WAKEUP_PIN 18 #define USBD_VBUS_DTC_PIN 3 -#elif defined(__FT930__) -#define GPIO_UART0_TX 23 -#define GPIO_UART0_RX 22 -#define GPIO_ETH_LED0 4 -#define GPIO_ETH_LED1 5 -#define GPIO_REMOTE_WAKEUP_PIN 12 -#define USBD_VBUS_DTC_PIN 39 -#endif -//#define GPIO_REMOTE_WAKEUP +#define GPIO_REMOTE_WAKEUP #ifdef __cplusplus } diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 3bd16b81..ed169655 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -24,10 +24,10 @@ * This file is part of the TinyUSB stack. */ +#include "board.h" +#include "bsp/board.h" #include #include -#include "bsp/board.h" -#include "board.h" #if TUSB_OPT_DEVICE_ENABLED int8_t board_ft90x_vbus(void); // Board specific implementation of VBUS detection for USB device. @@ -42,7 +42,7 @@ volatile unsigned int timer_ms = 0; void board_pm_ISR(void); #define WELCOME_MSG "\x1B[2J\x1B[H" \ - "MM900EV1B board\r\n" + "MM900EVxB board\r\n" // Initialize on-board peripherals : led, button, uart and USB void board_init(void) diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 6dbef161..9b08702e 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -24,8 +24,9 @@ * This file is part of the TinyUSB stack. */ -#include "tusb_option.h" +#include "board.h" #include "bsp/board.h" +#include "tusb_option.h" #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_FT90X From 5e6edecaa3594980198d8f687b3d97979ae85092 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Thu, 7 Oct 2021 17:00:28 +0100 Subject: [PATCH 06/16] Streamline settings for board. --- hw/bsp/brtmm90x/family.mk | 2 +- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 54 +++++++++++++----------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk index 42769c25..211f97f1 100644 --- a/hw/bsp/brtmm90x/family.mk +++ b/hw/bsp/brtmm90x/family.mk @@ -12,7 +12,7 @@ CFLAGS += \ -fvar-tracking-assignments \ -fmessage-length=0 \ -ffunction-sections \ - -DCFG_TUSB_MCU=OPT_MCU_FT90X + -DCFG_TUSB_MCU=OPT_MCU_FT90X # lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration CFLAGS += -Wno-error=shadow diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 9b08702e..09ca2904 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -24,11 +24,17 @@ * This file is part of the TinyUSB stack. */ +/* + * Contains code adapted from Bridgetek Pte Ltd via license terms stated + * in https://brtchip.com/BRTSourceCodeLicenseAgreement + */ + #include "board.h" #include "bsp/board.h" #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_FT90X +#if TUSB_OPT_DEVICE_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) #define USBD_USE_STREAMS @@ -250,12 +256,12 @@ static void _dcd_ft90x_attach(void) CRITICAL_SECTION_BEGIN // Turn off the device enable bit. -#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED +#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED USBD_REG(fctrl) = 0; -#else +#else // BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_FULL_SPEED //Set the full speed only bit if required. USBD_REG(fctrl) = MASK_USBD_FCTRL_MODE_FS_ONLY; -#endif +#endif // BOARD_DEVICE_RHPORT_SPEED // Clear first reset and suspend interrupts. do @@ -301,7 +307,7 @@ static void _dcd_ft90x_detach(void) delayms(1); // Disable USB PHY - dcd_disconnect(0); + dcd_disconnect(BOARD_DEVICE_RHPORT_NUM); delayms(1); // Disable Chip USB device clock/PM configuration. @@ -333,7 +339,7 @@ static void _ft90x_usb_speed(void) delayus(200); } -#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED +#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED /* Detect high or full speed */ fctrl_val = MASK_USBD_FCTRL_USB_DEV_EN; @@ -357,11 +363,11 @@ static void _ft90x_usb_speed(void) delayus(125 + 5); _speed = (USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; - dcd_event_bus_reset(0, _speed, true); + dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true); #endif /* !__FT930__ */ -#else /* CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED */ +#else // BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_FULL_SPEED /* User force set to full speed */ _speed = TUSB_SPEED_FULL; @@ -374,10 +380,10 @@ static void _ft90x_usb_speed(void) } #endif USBD_REG(fctrl) = fctrl_val; - dcd_event_bus_reset(0, _speed, true); + dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true); return; -#endif /* CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED */ +#endif // BOARD_DEVICE_RHPORT_SPEED } // Send a buffer to the USB IN FIFO. @@ -557,7 +563,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void)dev_addr; // Respond with status. There is no checking that the address is in range. - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0); // Set the update bit for the address register. dev_addr |= 0x80; @@ -603,7 +609,7 @@ void dcd_remote_wakeup(uint8_t rhport) SYS->MSC0CFG &= ~MASK_SYS_MSC0CFG_DEV_RMWAKEUP; // Enable USB PHY and determine current bus speed. - dcd_connect(0); + dcd_connect(rhport); } // Connect by enabling internal pull-up resistor on D+/D- @@ -882,7 +888,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) void _ft90x_usbd_ISR(void) { - tud_int_handler(0); // Resolves to dcd_int_handler(). + tud_int_handler(BOARD_DEVICE_RHPORT_NUM); // Resolves to dcd_int_handler(). } void dcd_int_handler(uint8_t rhport) @@ -920,19 +926,19 @@ void dcd_int_handler(uint8_t rhport) { // Reset endpoints to default state. _ft90x_reset_edpts(); - dcd_event_bus_reset(0, _speed, true); + dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true); } if (cmif & MASK_USBD_CMIF_SUSIRQ) //Handle Suspend interrupt { - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SUSPEND, true); } if (cmif & MASK_USBD_CMIF_RESIRQ) //Handle Resume interrupt { - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true); } if (cmif & MASK_USBD_CMIF_SOFIRQ) //Handle SOF interrupt { - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SOF, true); } } // Handle endpoint interrupts. @@ -963,7 +969,7 @@ void dcd_int_handler(uint8_t rhport) _ft90x_dusb_out(USBD_EP_0, (uint8_t *)_ft90x_setup_packet, sizeof(USB_device_request)); // Send the packet to tinyusb. - dcd_event_setup_received(0, _ft90x_setup_packet, true); + dcd_event_setup_received(BOARD_DEVICE_RHPORT_NUM, _ft90x_setup_packet, true); // Clear the interrupt that signals a SETUP packet is received. USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP); @@ -985,7 +991,7 @@ void dcd_int_handler(uint8_t rhport) xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, (uint8_t *)ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes); } // Now signal completion of data packet. - dcd_event_xfer_complete(0, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true); // Allow new transfers on the control endpoint. ep_xfer[USBD_EP_0].valid = 0; @@ -1042,7 +1048,7 @@ void dcd_int_handler(uint8_t rhport) if (ep_xfer[ep_number].remain_size == 0) { // Signal tinyUSB. - dcd_event_xfer_complete(0, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true); // Allow new transfers on this endpoint. ep_xfer[ep_number].valid = 0; @@ -1067,21 +1073,21 @@ void ft90x_usbd_pm_ISR(void) { // Signal connection interrupt SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true); } if (pmcfg & MASK_SYS_PMCFG_DEV_DIS_DEV) { // Signal disconnection interrupt SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_UNPLUGGED, true); } if (pmcfg & MASK_SYS_PMCFG_HOST_RST_DEV) { // Signal Host Reset interrupt SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_BUS_RESET, true); } if (pmcfg & MASK_SYS_PMCFG_HOST_RESUME_DEV) @@ -1092,7 +1098,7 @@ void ft90x_usbd_pm_ISR(void) { // If we are driving K-state on Device USB port; // We must maintain the 1ms requirement before resuming the phy - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true); } } } From 6a658007a5145147bd7435346f3617a7cda589b7 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 27 Oct 2021 12:30:51 +0100 Subject: [PATCH 07/16] Changes to use ft90x-sdk as submodule or installed SDK from toolchain. --- hw/bsp/brtmm90x/family.mk | 57 ++++++++++++++----- .../ft9xx/{hardware => }/scripts/crt0.S | 0 .../ft9xx/{hardware => }/scripts/ldscript.ld | 1 + src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 11 ++-- 4 files changed, 50 insertions(+), 19 deletions(-) rename hw/mcu/bridgetek/ft9xx/{hardware => }/scripts/crt0.S (100%) rename hw/mcu/bridgetek/ft9xx/{hardware => }/scripts/ldscript.ld (97%) diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk index 211f97f1..d47f4820 100644 --- a/hw/bsp/brtmm90x/family.mk +++ b/hw/bsp/brtmm90x/family.mk @@ -1,11 +1,28 @@ - +# GCC prefix for FT90X compile tools. CROSS_COMPILE = ft32-elf- -DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/hardware SKIP_NANOLIB = 1 -# This is installed at "C:/Program Files(x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware" -FT9XX_SDK = $(TOP)/hw/mcu/bridgetek/ft9xx/hardware +# Set to use FT90X prebuilt libraries. +FT90X_PREBUILT_LIBS = 1 +ifeq ($(FT90X_PREBUILT_LIBS),1) +# If the FT90X toolchain is installed on Windows systems then the SDK +# include files and prebuilt libraries are at: %FT90X_TOOLCHAIN%/hardware +FT9XX_SDK = $(FT90X_TOOLCHAIN)/hardware +else +# The submodule BRTSG-FOSS/ft90x-sdk contains header files and source +# code for the Bridgetek SDK. This can be used instead of the prebuilt +# library. +DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/hardware +# The SDK can be used to load specific files from the Bridgetek SDK. +FT9XX_SDK = hw/mcu/bridgetek/ft9xx/hardware/Source +endif +# Add include files which are within the TinyUSB directory structure. +INC += \ + $(TOP)/hw/mcu/bridgetek/ft9xx/hardware/Source/include \ + $(TOP)/$(BOARD_PATH) + +# Add required C Compiler flags for FT90X. CFLAGS += \ -D__FT900__ \ -fvar-tracking \ @@ -16,20 +33,34 @@ CFLAGS += \ # lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration CFLAGS += -Wno-error=shadow -CFLAGS:=$(filter-out -Wcast-function-type,$(CFLAGS)) -# All source paths should be relative to the top level. -LDINC += $(FT9XX_SDK)/lib/Release -LIBS += -lft900 -LD_FILE = hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld +# 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)) \ -Xlinker --entry=_start \ -Wl,-lc +# Additional Source files for FT90X. SRC_C += src/portable/bridgetek/ft9xx/dcd_ft9xx.c -#SRC_S += hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S +# Linker library. +ifneq ($(FT90X_PREBUILT_LIBS),1) +# Optionally add in files from the Bridgetek SDK instead of the prebuilt +# library. These are the minimum required. +SRC_C += $(FT9XX_SDK)/src/sys.c +SRC_C += $(FT9XX_SDK)/src/interrupt.c +SRC_C += $(FT9XX_SDK)/src/delay.c +SRC_C += $(FT9XX_SDK)/src/timers.c +SRC_C += $(FT9XX_SDK)/src/uart_simple.c +SRC_C += $(FT9XX_SDK)/src/gpio.c +else +# Or if using the prebuilt libraries add them. +LDFLAGS += -L"$(FT9XX_SDK)/lib" +LIBS += -lft900 +endif -INC += \ - $(FT9XX_SDK)/include \ - $(TOP)/$(BOARD_PATH) +# Not required crt0 file for FT90X. Use compiler built-in file. +#SRC_S += hw/mcu/bridgetek/ft9xx/scripts/crt0.S diff --git a/hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S b/hw/mcu/bridgetek/ft9xx/scripts/crt0.S similarity index 100% rename from hw/mcu/bridgetek/ft9xx/hardware/scripts/crt0.S rename to hw/mcu/bridgetek/ft9xx/scripts/crt0.S diff --git a/hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld b/hw/mcu/bridgetek/ft9xx/scripts/ldscript.ld similarity index 97% rename from hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld rename to hw/mcu/bridgetek/ft9xx/scripts/ldscript.ld index d1b4d46c..987c2b2b 100644 --- a/hw/mcu/bridgetek/ft9xx/hardware/scripts/ldscript.ld +++ b/hw/mcu/bridgetek/ft9xx/scripts/ldscript.ld @@ -9,6 +9,7 @@ MEMORY { flash (rx) : ORIGIN = 0, LENGTH = __PMSIZE ram (rw!x) : ORIGIN = 0x800000, LENGTH = __RAMSIZE + ehci_mmap (rw!x) : ORIGIN = 0x811000, LENGTH = 2K } SECTIONS { diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 09ca2904..3235d0ef 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -29,20 +29,19 @@ * in https://brtchip.com/BRTSourceCodeLicenseAgreement */ +#include +#include +#include + #include "board.h" #include "bsp/board.h" #include "tusb_option.h" #if TUSB_OPT_DEVICE_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) + (CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) #define USBD_USE_STREAMS -#include -#include -#include -#include - #include "device/dcd.h" //--------------------------------------------------------------------+ From ba76b2e3395ca3cb5033d70e34a6fa9a6ff7373c Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Mon, 22 Nov 2021 10:33:07 +0000 Subject: [PATCH 08/16] Add submodule for ft90x SDK Add Bridgetek FT90x SDK as submodule. --- .gitmodules | 3 +++ hw/mcu/bridgetek/ft9xx/ft90x-sdk | 1 + 2 files changed, 4 insertions(+) create mode 160000 hw/mcu/bridgetek/ft9xx/ft90x-sdk diff --git a/.gitmodules b/.gitmodules index 4c86fd55..e87b8750 100644 --- a/.gitmodules +++ b/.gitmodules @@ -127,3 +127,6 @@ [submodule "hw/mcu/gd/nuclei-sdk"] path = hw/mcu/gd/nuclei-sdk url = https://github.com/Nuclei-Software/nuclei-sdk.git +[submodule "hw/mcu/bridgetek/ft9xx/ft90x-sdk"] + path = hw/mcu/bridgetek/ft9xx/ft90x-sdk + url = https://github.com/BRTSG-FOSS/ft90x-sdk diff --git a/hw/mcu/bridgetek/ft9xx/ft90x-sdk b/hw/mcu/bridgetek/ft9xx/ft90x-sdk new file mode 160000 index 00000000..a94bec48 --- /dev/null +++ b/hw/mcu/bridgetek/ft9xx/ft90x-sdk @@ -0,0 +1 @@ +Subproject commit a94bec4856b7e0f1dfda57307b66e3edb2c5a3c7 From edf3f3501656b010ad4a9e1d0a0d62573dd0b3fb Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Mon, 22 Nov 2021 12:38:04 +0000 Subject: [PATCH 09/16] Update ft90x-sdk Update submodule for FT90X SDK to point to the v2.5.0 release code currently in main. --- hw/mcu/bridgetek/ft9xx/ft90x-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mcu/bridgetek/ft9xx/ft90x-sdk b/hw/mcu/bridgetek/ft9xx/ft90x-sdk index a94bec48..e8122eb6 160000 --- a/hw/mcu/bridgetek/ft9xx/ft90x-sdk +++ b/hw/mcu/bridgetek/ft9xx/ft90x-sdk @@ -1 +1 @@ -Subproject commit a94bec4856b7e0f1dfda57307b66e3edb2c5a3c7 +Subproject commit e8122eb6bd6286a1fe31f175a3e3eb0e7770c3e3 From 5039a5e54c184d6cc281890b6f328caef116bce7 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 09:34:29 +0000 Subject: [PATCH 10/16] Update code to implement changes from upstream master --- hw/bsp/brtmm90x/family.c | 8 ++++++-- src/device/dcd_attr.h | 4 ++-- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 18 +++++++++--------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index ed169655..739a8358 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -63,7 +63,8 @@ void board_init(void) // Use sizeof to avoid pulling in strlen unnecessarily. board_uart_write(WELCOME_MSG, sizeof(WELCOME_MSG)); -#if 1 +#if 0 + // Ethernet LEDs gpio_function(GPIO_ETH_LED0, pad_gpio4); /* ETH LED0 */ gpio_dir(GPIO_ETH_LED0, pad_dir_open_drain); gpio_function(GPIO_ETH_LED1, pad_gpio5); /* ETH LED1 */ @@ -192,7 +193,10 @@ int board_uart_read(uint8_t *buf, int len) // Send characters to UART int board_uart_write(void const *buf, int len) { - int r = uart_writen(UART0, (uint8_t *)buf, len); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" // uart_writen does not have const for buffer parameter. + int r = uart_writen(UART0, (uint8_t *)((const void *)buf), len); +#pragma GCC diagnostic pop return r; } diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index c5194057..21bfbb54 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -198,10 +198,10 @@ #define DCD_ATTR_ENDPOINT_MAX 8 //------------- BridgeTek -------------// -#elif TU_CHECK_MCU(FT90X) +#elif TU_CHECK_MCU(OPT_MCU_FT90X) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(FT93X) +#elif TU_CHECK_MCU(OPT_MCU_FT93X) #define DCD_ATTR_ENDPOINT_MAX 16 #else diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 3235d0ef..aa45aa1d 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -56,10 +56,10 @@ static uint8_t _ft90x_setup_packet[8]; struct ft90x_xfer_state { - 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. - volatile uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid. + uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid. + 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. @@ -399,7 +399,7 @@ static uint16_t _ft90x_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_ #ifdef USBD_USE_STREAMS volatile uint8_t *data_reg; - data_reg = (uint8_t *)&(USBD->ep[ep_number].epxfifo); + data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo); if (buff_size) { if (((uint32_t)buffer) % 4 == 0) @@ -476,7 +476,7 @@ static uint16_t _ft90x_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t len buff_size = length; #ifdef USBD_USE_STREAMS - data_reg = (uint8_t *)&(USBD->ep[ep_number].epxfifo); + data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo); if (buff_size) { if ((uint32_t)buffer % 4 == 0) @@ -656,7 +656,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc) uint8_t const ep_number = tu_edpt_number(ep_desc->bEndpointAddress); uint8_t const ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); uint8_t const ep_type = ep_desc->bmAttributes.xfer; - uint16_t const ep_size = ep_desc->wMaxPacketSize.size; + uint16_t const ep_size = tu_edpt_packet_size(ep_desc); // Mask size per packet, bits 10..0. uint16_t ep_buff_size; uint8_t ep_reg_size = USBD_EP_MAX_SIZE_8; uint8_t ep_reg_data = 0; @@ -673,13 +673,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc) // Calculate the physical size of the endpoint as a power of 2. This may be more than // the requested size. - while (ep_desc->wMaxPacketSize.size > (8 * (1 << ep_reg_size))) + while (ep_size > (8 * (1 << ep_reg_size))) { ep_reg_size++; } if (ep_reg_size > USBD_EP_MAX_SIZE_1024) { - TU_LOG1("FT90x endpoint size not valid: requested %d max 1024\r\n", ep_desc->wMaxPacketSize.size); + TU_LOG1("FT90x endpoint size not valid: requested %d max 1024\r\n", ep_size); return false; } // Calculate actual amount of buffer RAM used by this endpoint. This may be more than the From 45869958f6066fe4d195c62423cba2fec1886cbc Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 10:03:33 +0000 Subject: [PATCH 11/16] Add FT9xx to more examples which support High-Speed --- examples/device/hid_boot_interface/src/tusb_config.h | 3 ++- examples/device/hid_composite/src/tusb_config.h | 3 ++- examples/device/hid_multiple_interface/src/tusb_config.h | 3 ++- examples/device/midi_test/src/tusb_config.h | 3 ++- hw/bsp/brtmm90x/family.c | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/device/hid_boot_interface/src/tusb_config.h b/examples/device/hid_boot_interface/src/tusb_config.h index 59fb9962..1381dd6b 100644 --- a/examples/device/hid_boot_interface/src/tusb_config.h +++ b/examples/device/hid_boot_interface/src/tusb_config.h @@ -48,7 +48,8 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X || \ + CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 8fa5e5cd..449efbc7 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -48,7 +48,8 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\ - TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) + TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\ + TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/hid_multiple_interface/src/tusb_config.h b/examples/device/hid_multiple_interface/src/tusb_config.h index a0aa17a9..c034b086 100644 --- a/examples/device/hid_multiple_interface/src/tusb_config.h +++ b/examples/device/hid_multiple_interface/src/tusb_config.h @@ -48,7 +48,8 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || \ + CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 61b9b655..a40d7605 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -48,7 +48,8 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || \ + CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 739a8358..803a62a9 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -24,8 +24,9 @@ * This file is part of the TinyUSB stack. */ -#include "board.h" #include "bsp/board.h" +#include "board.h" + #include #include From fa06bd01c97a3a14215ea145764c09aecaa0dd79 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 10:05:32 +0000 Subject: [PATCH 12/16] Merge in upstream changes Merge upstream changes and expand example support to hid examples. --- .vscode/c_cpp_properties.json | 41 ++++++++ .vscode/launch.json | 32 +++++++ .vscode/settings.json | 17 ++++ .vscode/tasks.json | 176 ++++++++++++++++++++++++++++++++++ examples/make.mk | 3 +- examples/rules.mk | 4 +- 6 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..28d4718b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,41 @@ +{ + "configurations": [ + { + "name": "FT900", + "includePath": [ + // Toolchain installed FT90X SDK. + "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware/include", + // Submodule for FT90X SDK. + //"${workspaceFolder}/hw/mcu/bridgetek/ft9xx/hardware/Source/include", + // Board headers. + "${workspaceFolder}/hw/bsp/brtmm90x/boards/mm900evxb", + // Hardware abstraction headers. + "${workspaceFolder}/hw/", + // Local header files. + ".", + "${workspaceFolder}/src", + // Example headers. + "${workspaceFolder}/examples/device/cdc_msc/src" + //"${workspaceFolder}/examples/host/hid_controller/src" + ], + "defines": [ + "__FT900__", + "BOARD=mm900evxb", + //"FT32_PORT", "FT32_PORT_HEAP=4", // For FreeRTOS + "CFG_TUSB_MCU=OPT_MCU_FT90X", // For FT90x + //"CFG_TUSB_RHPORT0_MODE=(OPT_MODE_HOST|OPT_MODE_HIGH_SPEED)", + //"CFG_TUSB_RHPORT1_MODE=(OPT_MODE_DEVICE|OPT_MODE_HIGH_SPEED)", + //"BOARD_DEVICE_RHPORT_NUM=1", + //"BOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED", + "CFG_TUSB_DEBUG=0" + ], + "windowsSdkVersion": "10.0.18362.0", + "compilerPath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gcc", + "cStandard": "c11", + "cppStandard": "c++11", + "intelliSenseMode": "windows-gcc-x64", + "configurationProvider": "ms-vscode.makefile-tools" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..7aa6e061 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug TinyUSB CDC_MSC", + "type": "cppdbg", + "MIMode": "gdb", + "request": "launch", + "cwd": "${workspaceFolder}", + "program": "examples/device/program.elf", + //"program": "examples/device/cdc_msc/_build/mm900ev1b/cdc_msc.elf", + "preLaunchTask": "Build and Program (Memory)", + "target": "localhost:9998", + "remote": true, + "gdbpath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gdb.exe", + "stopAtEntry": true, + "environment": [], + "console": "externalTerminal", + "miDebuggerPath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gdb.exe", + //"miDebuggerArgs": "-x lib\\FreeRTOS\\.gdbinit-FreeRTOS-helpers", + "miDebuggerServerAddress": "localhost:9998", + "launchCompleteCommand": "None", + "debugServerPath": "C:\\Users\\gordon.mcnab\\AppData\\Local\\Programs\\Python\\Python37\\python.exe", + "debugServerArgs": + "\"C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/utilities/gdb_bridge.py\" live pm", + //"rtos": "FreeRTOS", + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..b0aef0cf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "files.associations": { + "tusb_option.h": "c", + "ft900.h": "c", + "ft900_usbd.h": "c", + "ft900_registers.h": "c", + "ft900_usbd_registers.h": "c", + "dcd.h": "c", + "stdint.h": "c", + "board.h": "c", + "ft900_ehci_registers.h": "c", + "stdint-gcc.h": "c", + "ft900_memctl.h": "c", + "stddef.h": "c" + }, + "cmake.configureOnOpen": true +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..459351c4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,176 @@ +{ + "version": "2.0.0", + + "options": { + "env": { + // Set this to the type of example. + // Choices can be "device" or "host". + "exampleType": "device", + // Set this to the name of the example. + // The name is the folder name in the examples directory. + "exampleName": "cdc_msc", + // Set this to the name of the board to target. + "boardName": "mm900evxb" + } + }, + + "inputs": [ + { + "type": "pickString", + "id": "pickExampleName", + "description": "Which example project do you want to use?", + "options": [ + "board_test", + "cdc_msc", + "hid_boot_interface", + "hid_composite", + + ], + "default": "board_test" + }, + { + "type": "pickString", + "id": "pickBoardName", + "description": "Which board type do you want to use?", + "options": [ + "mm900ev1b", + "mm900ev2b", + "mm900ev3b" + ], + "default": "mm900ev1b" + } + ], + + "tasks": [ + { + "label": "test env", + "type": "shell", + "command": "echo", + "args": [ + "$env:exampleName" + ], + "problemMatcher": [] + }, + { + "label": "Build and Program (Memory)", + "dependsOrder": "sequence", + "dependsOn": [ + "Build Project", + "Program Project (Memory)" + ], + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "copy", + "args": [ + "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.elf", + "examples\\$env:exampleType\\program.elf" + ], + "problemMatcher": { + "pattern": { + "regexp": "^Error:\\s+(.*)$", + "message": 1 + } + } + }, + { + "label": "Build Project", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "make.exe", + "args": [ + "-C", + "examples\\$env:exampleType\\$env:exampleName", + "BOARD=$env:boardName" + ], + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Rebuild Project", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "make.exe", + "args": [ + "-C", + "examples\\$env:exampleType\\$env:exampleName", + "BOARD=$env:boardName", + "-B" + ], + "problemMatcher": [ + "$gcc" + ], + "group": "build" + }, + { + "label": "Clean Project", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "make.exe", + "args": [ + "-C", + "examples\\$env:exampleType\\$env:exampleName", + "BOARD=$env:boardName", + "clean" + ], + "problemMatcher": [ + "$gcc" + ], + "group": "build" + }, + { + "label": "Program Project (Flash)", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "C:\\Program Files (x86)\\Bridgetek\\FT9xx Toolchain\\Toolchain\\programmer\\dist\\FT900Prog.exe", + "args": [ + "--loadflash", + "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.bin", + "--onewire", + "--noReset" + ], + "problemMatcher": { + "pattern": { + "regexp": "^Error:\\s+(.*)$", + "message": 1 + } + }, + "dependsOn": "${defaultBuildTask}" + }, + { + "label": "Program Project (Memory)", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "C:\\Program Files (x86)\\Bridgetek\\FT9xx Toolchain\\Toolchain\\programmer\\dist\\FT900Prog.exe", + "args": [ + "--loadpm", + "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.bin", + "--onewire", + "--noReset" + ], + "problemMatcher": { + "pattern": { + "regexp": "^Error:\\s+(.*)$", + "message": 1 + } + }, + "dependsOn": "${defaultBuildTask}" + } + ], +} \ No newline at end of file diff --git a/examples/make.mk b/examples/make.mk index 793c40aa..e1cd0af2 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -104,10 +104,11 @@ CFLAGS += \ -Wmissing-format-attribute \ -Wunreachable-code \ -Wcast-align \ - -Wcast-function-type \ -Wcast-qual \ -Wnull-dereference +# -Wcast-function-type \ + # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -Og diff --git a/examples/rules.mk b/examples/rules.mk index 4cc35cb2..a12a75d6 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -84,7 +84,7 @@ OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) $(OBJ_DIRS): ifeq ($(CMDEXE),1) - @$(MKDIR) $(subst /,\,$@) + -@$(MKDIR) $(subst /,\,$@) else @$(MKDIR) -p $@ endif @@ -207,7 +207,7 @@ debug-bmp: $(BUILD)/$(PROJECT).elf # Create binary directory $(BIN): - @$(MKDIR) -p $@ + -@$(MKDIR) -p $@ # Copy binaries .elf, .bin, .hex, .uf2 to BIN for upload # due to large size of combined artifacts, only uf2 is uploaded for now From 79f1f4e171393397f25e884792ecc33b2480e050 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 11:17:05 +0000 Subject: [PATCH 13/16] Revert "Merge in upstream changes" This reverts commit fa06bd01c97a3a14215ea145764c09aecaa0dd79. --- .vscode/c_cpp_properties.json | 41 -------- .vscode/launch.json | 32 ------- .vscode/settings.json | 17 ---- .vscode/tasks.json | 176 ---------------------------------- examples/make.mk | 3 +- examples/rules.mk | 4 +- 6 files changed, 3 insertions(+), 270 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 28d4718b..00000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "configurations": [ - { - "name": "FT900", - "includePath": [ - // Toolchain installed FT90X SDK. - "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/hardware/include", - // Submodule for FT90X SDK. - //"${workspaceFolder}/hw/mcu/bridgetek/ft9xx/hardware/Source/include", - // Board headers. - "${workspaceFolder}/hw/bsp/brtmm90x/boards/mm900evxb", - // Hardware abstraction headers. - "${workspaceFolder}/hw/", - // Local header files. - ".", - "${workspaceFolder}/src", - // Example headers. - "${workspaceFolder}/examples/device/cdc_msc/src" - //"${workspaceFolder}/examples/host/hid_controller/src" - ], - "defines": [ - "__FT900__", - "BOARD=mm900evxb", - //"FT32_PORT", "FT32_PORT_HEAP=4", // For FreeRTOS - "CFG_TUSB_MCU=OPT_MCU_FT90X", // For FT90x - //"CFG_TUSB_RHPORT0_MODE=(OPT_MODE_HOST|OPT_MODE_HIGH_SPEED)", - //"CFG_TUSB_RHPORT1_MODE=(OPT_MODE_DEVICE|OPT_MODE_HIGH_SPEED)", - //"BOARD_DEVICE_RHPORT_NUM=1", - //"BOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED", - "CFG_TUSB_DEBUG=0" - ], - "windowsSdkVersion": "10.0.18362.0", - "compilerPath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gcc", - "cStandard": "c11", - "cppStandard": "c++11", - "intelliSenseMode": "windows-gcc-x64", - "configurationProvider": "ms-vscode.makefile-tools" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 7aa6e061..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Debug TinyUSB CDC_MSC", - "type": "cppdbg", - "MIMode": "gdb", - "request": "launch", - "cwd": "${workspaceFolder}", - "program": "examples/device/program.elf", - //"program": "examples/device/cdc_msc/_build/mm900ev1b/cdc_msc.elf", - "preLaunchTask": "Build and Program (Memory)", - "target": "localhost:9998", - "remote": true, - "gdbpath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gdb.exe", - "stopAtEntry": true, - "environment": [], - "console": "externalTerminal", - "miDebuggerPath": "C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/tools/bin/ft32-elf-gdb.exe", - //"miDebuggerArgs": "-x lib\\FreeRTOS\\.gdbinit-FreeRTOS-helpers", - "miDebuggerServerAddress": "localhost:9998", - "launchCompleteCommand": "None", - "debugServerPath": "C:\\Users\\gordon.mcnab\\AppData\\Local\\Programs\\Python\\Python37\\python.exe", - "debugServerArgs": - "\"C:/Program Files (x86)/Bridgetek/FT9xx Toolchain/Toolchain/utilities/gdb_bridge.py\" live pm", - //"rtos": "FreeRTOS", - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b0aef0cf..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "files.associations": { - "tusb_option.h": "c", - "ft900.h": "c", - "ft900_usbd.h": "c", - "ft900_registers.h": "c", - "ft900_usbd_registers.h": "c", - "dcd.h": "c", - "stdint.h": "c", - "board.h": "c", - "ft900_ehci_registers.h": "c", - "stdint-gcc.h": "c", - "ft900_memctl.h": "c", - "stddef.h": "c" - }, - "cmake.configureOnOpen": true -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 459351c4..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "version": "2.0.0", - - "options": { - "env": { - // Set this to the type of example. - // Choices can be "device" or "host". - "exampleType": "device", - // Set this to the name of the example. - // The name is the folder name in the examples directory. - "exampleName": "cdc_msc", - // Set this to the name of the board to target. - "boardName": "mm900evxb" - } - }, - - "inputs": [ - { - "type": "pickString", - "id": "pickExampleName", - "description": "Which example project do you want to use?", - "options": [ - "board_test", - "cdc_msc", - "hid_boot_interface", - "hid_composite", - - ], - "default": "board_test" - }, - { - "type": "pickString", - "id": "pickBoardName", - "description": "Which board type do you want to use?", - "options": [ - "mm900ev1b", - "mm900ev2b", - "mm900ev3b" - ], - "default": "mm900ev1b" - } - ], - - "tasks": [ - { - "label": "test env", - "type": "shell", - "command": "echo", - "args": [ - "$env:exampleName" - ], - "problemMatcher": [] - }, - { - "label": "Build and Program (Memory)", - "dependsOrder": "sequence", - "dependsOn": [ - "Build Project", - "Program Project (Memory)" - ], - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "copy", - "args": [ - "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.elf", - "examples\\$env:exampleType\\program.elf" - ], - "problemMatcher": { - "pattern": { - "regexp": "^Error:\\s+(.*)$", - "message": 1 - } - } - }, - { - "label": "Build Project", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "make.exe", - "args": [ - "-C", - "examples\\$env:exampleType\\$env:exampleName", - "BOARD=$env:boardName" - ], - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "Rebuild Project", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "make.exe", - "args": [ - "-C", - "examples\\$env:exampleType\\$env:exampleName", - "BOARD=$env:boardName", - "-B" - ], - "problemMatcher": [ - "$gcc" - ], - "group": "build" - }, - { - "label": "Clean Project", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "make.exe", - "args": [ - "-C", - "examples\\$env:exampleType\\$env:exampleName", - "BOARD=$env:boardName", - "clean" - ], - "problemMatcher": [ - "$gcc" - ], - "group": "build" - }, - { - "label": "Program Project (Flash)", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "C:\\Program Files (x86)\\Bridgetek\\FT9xx Toolchain\\Toolchain\\programmer\\dist\\FT900Prog.exe", - "args": [ - "--loadflash", - "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.bin", - "--onewire", - "--noReset" - ], - "problemMatcher": { - "pattern": { - "regexp": "^Error:\\s+(.*)$", - "message": 1 - } - }, - "dependsOn": "${defaultBuildTask}" - }, - { - "label": "Program Project (Memory)", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}" - }, - "command": "C:\\Program Files (x86)\\Bridgetek\\FT9xx Toolchain\\Toolchain\\programmer\\dist\\FT900Prog.exe", - "args": [ - "--loadpm", - "examples\\$env:exampleType\\$env:exampleName\\_build\\$env:boardName\\$env:exampleName.bin", - "--onewire", - "--noReset" - ], - "problemMatcher": { - "pattern": { - "regexp": "^Error:\\s+(.*)$", - "message": 1 - } - }, - "dependsOn": "${defaultBuildTask}" - } - ], -} \ No newline at end of file diff --git a/examples/make.mk b/examples/make.mk index e1cd0af2..793c40aa 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -104,11 +104,10 @@ CFLAGS += \ -Wmissing-format-attribute \ -Wunreachable-code \ -Wcast-align \ + -Wcast-function-type \ -Wcast-qual \ -Wnull-dereference -# -Wcast-function-type \ - # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -Og diff --git a/examples/rules.mk b/examples/rules.mk index a12a75d6..4cc35cb2 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -84,7 +84,7 @@ OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) $(OBJ_DIRS): ifeq ($(CMDEXE),1) - -@$(MKDIR) $(subst /,\,$@) + @$(MKDIR) $(subst /,\,$@) else @$(MKDIR) -p $@ endif @@ -207,7 +207,7 @@ debug-bmp: $(BUILD)/$(PROJECT).elf # Create binary directory $(BIN): - -@$(MKDIR) -p $@ + @$(MKDIR) -p $@ # Copy binaries .elf, .bin, .hex, .uf2 to BIN for upload # due to large size of combined artifacts, only uf2 is uploaded for now From bcbcdf87de303a4db1724de2a813b80f13d7d906 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 11:24:39 +0000 Subject: [PATCH 14/16] Fix spelling mistakes and verify endpoint numbering. --- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 3c3e9c89..09894cf1 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -118,7 +118,7 @@ enum #define EPNUM_MSC_IN 0x84 #elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X - // FT9XX don't support a same endpoint number with different direction IN and OUT + // FT9XX doesn't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 From 21fa7ea468cf34e6d775c92de580796d2c7eec4f Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 8 Dec 2021 13:56:23 +0000 Subject: [PATCH 15/16] Correct path for using the ft90x-sdk submodule (BRTSG-FOSS / ft90x-sdk). Default to ft90x-sdk instead of pre-built library. --- hw/bsp/brtmm90x/family.mk | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk index d47f4820..3933f15c 100644 --- a/hw/bsp/brtmm90x/family.mk +++ b/hw/bsp/brtmm90x/family.mk @@ -3,23 +3,24 @@ CROSS_COMPILE = ft32-elf- SKIP_NANOLIB = 1 # Set to use FT90X prebuilt libraries. -FT90X_PREBUILT_LIBS = 1 +FT90X_PREBUILT_LIBS = 0 ifeq ($(FT90X_PREBUILT_LIBS),1) # If the FT90X toolchain is installed on Windows systems then the SDK # include files and prebuilt libraries are at: %FT90X_TOOLCHAIN%/hardware FT9XX_SDK = $(FT90X_TOOLCHAIN)/hardware +INC += $(FT9XX_SDK)/include else # The submodule BRTSG-FOSS/ft90x-sdk contains header files and source # code for the Bridgetek SDK. This can be used instead of the prebuilt # library. -DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/hardware +DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/ft90x-sdk # The SDK can be used to load specific files from the Bridgetek SDK. -FT9XX_SDK = hw/mcu/bridgetek/ft9xx/hardware/Source +FT9XX_SDK = hw/mcu/bridgetek/ft9xx/ft90x-sdk/Source +INC += $(TOP)/$(FT9XX_SDK)/include endif # Add include files which are within the TinyUSB directory structure. INC += \ - $(TOP)/hw/mcu/bridgetek/ft9xx/hardware/Source/include \ $(TOP)/$(BOARD_PATH) # Add required C Compiler flags for FT90X. From 8d373b08879ac382c59dcbfb2d351d4af35e3d00 Mon Sep 17 00:00:00 2001 From: Gordon McNab Date: Wed, 15 Dec 2021 12:23:58 +0000 Subject: [PATCH 16/16] Update midi_test endpoints and FT9xx code --- .../device/midi_test/src/usb_descriptors.c | 14 ++-- src/portable/bridgetek/ft9xx/dcd_ft9xx.c | 64 ++++++++++--------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index bd5a0eea..8444237c 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -83,9 +83,15 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_MIDI 0x02 + #define EPNUM_MIDI_OUT 0x02 + #define EPNUM_MIDI_IN 0x02 +#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X + // On Bridgetek FT9xx endpoint numbers must be unique... + #define EPNUM_MIDI_OUT 0x02 + #define EPNUM_MIDI_IN 0x03 #else - #define EPNUM_MIDI 0x01 + #define EPNUM_MIDI_OUT 0x01 + #define EPNUM_MIDI_IN 0x01 #endif uint8_t const desc_fs_configuration[] = @@ -94,7 +100,7 @@ uint8_t const desc_fs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_IN), 64) }; #if TUD_OPT_HIGH_SPEED @@ -104,7 +110,7 @@ uint8_t const desc_hs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 512) + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_IN), 512) }; #endif diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index aa45aa1d..793d40f8 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -56,10 +56,10 @@ static uint8_t _ft90x_setup_packet[8]; struct ft90x_xfer_state { - uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid. - 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. + 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. 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. @@ -131,6 +131,7 @@ static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t uint8_t end = 0; uint16_t ep_size = ep_xfer[ep_number].size; (void)ep_size; + if ((xfer_bytes == 0) || (xfer_bytes < ep_size)) { end = 1; @@ -186,39 +187,21 @@ static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t return xfer_bytes; } -// Reset all endpoints to a default state. -// Control endpoint enabled and ready. All others disabled. +// Reset all non-control endpoints to a default state. +// Control endpoint is always enabled and ready. All others disabled. static void _ft90x_reset_edpts(void) { // Disable all endpoints and remove configuration values. - // Clear settings. - tu_memclr(ep_xfer, sizeof(ep_xfer)); - for (int i = 0; i < USBD_MAX_ENDPOINT_COUNT; i++) + for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++) { + // Clear settings. + tu_memclr(&ep_xfer[i], sizeof(struct ft90x_xfer_state)); // Disable hardware. USBD_EP_CR_REG(i) = 0; } - // Setup the control endpoint only. -#if CFG_TUD_ENDPOINT0_SIZE == 64 - USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_64 << BIT_USBD_EP0_MAX_SIZE); -#elif CFG_TUD_ENDPOINT0_SIZE == 32 - USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_32 << BIT_USBD_EP0_MAX_SIZE); -#elif CFG_TUD_ENDPOINT0_SIZE == 16 - USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_16 << BIT_USBD_EP0_MAX_SIZE); -#elif CFG_TUD_ENDPOINT0_SIZE == 8 - USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_8 << BIT_USBD_EP0_MAX_SIZE); -#else -#error "CFG_TUD_ENDPOINT0_SIZE must be defined with a value of 8, 16, 32 or 64." -#endif - // Configure the control endpoint. - ep_xfer[USBD_EP_0].size = CFG_TUD_ENDPOINT0_SIZE; - ep_xfer[USBD_EP_0].type = TUSB_XFER_CONTROL; - // Enable interrupts from USB device control. USBD_REG(cmie) = MASK_USBD_CMIE_ALL; - // Enable interrupts on EP0. - USBD_REG(epie) = (MASK_USBD_EPIE_EP0IE); } // Enable or disable the USB PHY. @@ -297,12 +280,13 @@ static void _dcd_ft90x_detach(void) SYS->MSC0CFG = SYS->MSC0CFG & (~MASK_SYS_MSC0CFG_USB_VBUS_EN); #endif CRITICAL_SECTION_BEGIN + // Disable interrupts from USB. USBD_REG(epie) = 0; USBD_REG(cmie) = 0; + // Turn off the device enable bit. + USBD_REG(fctrl) = 0; CRITICAL_SECTION_END; - // Disable the USB function. - USBD_REG(fctrl) = 0; delayms(1); // Disable USB PHY @@ -628,8 +612,28 @@ void dcd_connect(uint8_t rhport) // Determine bus speed and signal speed to tusb. _ft90x_usb_speed(); } - CRITICAL_SECTION_END; + // Setup the control endpoint only. +#if CFG_TUD_ENDPOINT0_SIZE == 64 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_64 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 32 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_32 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 16 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_16 << BIT_USBD_EP0_MAX_SIZE); +#elif CFG_TUD_ENDPOINT0_SIZE == 8 + USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_8 << BIT_USBD_EP0_MAX_SIZE); +#else +#error "CFG_TUD_ENDPOINT0_SIZE must be defined with a value of 8, 16, 32 or 64." +#endif + CRITICAL_SECTION_END; + + // Configure the control endpoint. + ep_xfer[USBD_EP_0].size = CFG_TUD_ENDPOINT0_SIZE; + ep_xfer[USBD_EP_0].type = TUSB_XFER_CONTROL; + + // Enable interrupts on EP0. + USBD_REG(epie) = (MASK_USBD_EPIE_EP0IE); + // Restore default endpoint state. _ft90x_reset_edpts(); }