Merge pull request #1163 from hathach/generalize-synopsys-dwc2

Generalize synopsys dwc2
This commit is contained in:
Ha Thach
2021-11-04 13:41:25 +07:00
committed by GitHub
71 changed files with 8193 additions and 1828 deletions

View File

@@ -481,7 +481,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if (p_cbw->total_bytes)
{
// 6.7 The 13 Cases: case 4 (Hi > Dn)
TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
// TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
@@ -494,7 +494,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( p_cbw->total_bytes == 0 )
{
// 6.7 The 13 Cases: case 2 (Hn < Di)
TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
// TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
@@ -609,7 +609,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) )
{
// 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
// TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
usbd_edpt_stall(rhport, p_msc->ep_in);
}else
{
@@ -617,7 +617,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
}
}
#if TU_CHECK_MCU(CXD56)
#if TU_CHECK_MCU(OPT_MCU_CXD56)
// WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD.
// There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and
// hope everything will work

View File

@@ -111,6 +111,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); }
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); }
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); }
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); }
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); }
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); }
@@ -235,37 +238,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, ui
#endif
/*------------------------------------------------------------------*/
/* Count number of arguments of __VA_ARGS__
* - reference https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s
* - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th)
* - _RSEQ_N() is reverse sequential to N to add padding to have
* Nth position is the same as the number of arguments
* - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma)
*------------------------------------------------------------------*/
#ifndef TU_ARGS_NUM
#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N())
#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__)
#define _GET_NTH_ARG( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define _RSEQ_N() \
62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#endif
// To be removed
//------------- Binary constant -------------//
#if defined(__GNUC__) && !defined(__CC_ARM)
@@ -334,8 +306,8 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
#define TU_LOG1 tu_printf
#define TU_LOG1_MEM tu_print_mem
#define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (uint32_t) (_x) )
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (uint32_t) (_x) )
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) )
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) )
// Log Level 2: Warn
#if CFG_TUSB_DEBUG >= 2

View File

@@ -67,6 +67,46 @@
#define TU_LITTLE_ENDIAN (0x12u)
#define TU_BIG_ENDIAN (0x21u)
/*------------------------------------------------------------------*/
/* Count number of arguments of __VA_ARGS__
* - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments
* - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th)
* - _RSEQ_N() is reverse sequential to N to add padding to have
* Nth position is the same as the number of arguments
* - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma)
*------------------------------------------------------------------*/
#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N())
#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__)
#define _GET_NTH_ARG( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define _RSEQ_N() \
62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
// Apply an macro X to each of the arguments with an separated of choice
#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__)
#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1)
#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2)
#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3)
#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4)
#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5)
#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6)
#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7)
#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8)
//--------------------------------------------------------------------+
// Compiler porting with Attribute and Endian
//--------------------------------------------------------------------+

View File

@@ -47,8 +47,8 @@
typedef enum
{
TUSB_SPEED_FULL = 0,
TUSB_SPEED_LOW ,
TUSB_SPEED_HIGH,
TUSB_SPEED_LOW = 1,
TUSB_SPEED_HIGH = 2,
TUSB_SPEED_INVALID = 0xff,
}tusb_speed_t;

View File

@@ -36,124 +36,155 @@
// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on.
//------------- NXP -------------//
#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX)
#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX)
#define DCD_ATTR_ENDPOINT_MAX 5
#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX)
#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX)
#define DCD_ATTR_ENDPOINT_MAX 16
#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX)
#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
// TODO USB0 has 6, USB1 has 4
#define DCD_ATTR_ENDPOINT_MAX 6
#elif TU_CHECK_MCU(LPC51UXX)
#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX)
#define DCD_ATTR_ENDPOINT_MAX 5
#elif TU_CHECK_MCU(LPC54XXX)
#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX)
// TODO USB0 has 5, USB1 has 6
#define DCD_ATTR_ENDPOINT_MAX 6
#elif TU_CHECK_MCU(LPC55XX)
#elif TU_CHECK_MCU(OPT_MCU_LPC55XX)
// TODO USB0 has 5, USB1 has 6
#define DCD_ATTR_ENDPOINT_MAX 6
#elif TU_CHECK_MCU(MIMXRT10XX)
#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(MKL25ZXX) || TU_CHECK_MCU(K32L2BXX)
#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX)
#define DCD_ATTR_ENDPOINT_MAX 16
#elif TU_CHECK_MCU(MM32F327X)
#elif TU_CHECK_MCU(OPT_MCU_MM32F327X)
#define DCD_ATTR_ENDPOINT_MAX 16
//------------- Nordic -------------//
#elif TU_CHECK_MCU(NRF5X)
#elif TU_CHECK_MCU(OPT_MCU_NRF5X)
// 8 CBI + 1 ISO
#define DCD_ATTR_ENDPOINT_MAX 9
//------------- Microchip -------------//
#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \
TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22)
#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \
TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(SAMG)
#elif TU_CHECK_MCU(OPT_MCU_SAMG)
#define DCD_ATTR_ENDPOINT_MAX 6
#define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
#elif TU_CHECK_MCU(SAMX7X)
#elif TU_CHECK_MCU(OPT_MCU_SAMX7X)
#define DCD_ATTR_ENDPOINT_MAX 10
#define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
//------------- ST -------------//
#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \
TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4)
// F1: F102, F103
// L4: L4x2, L4x3
#elif TU_CHECK_MCU(OPT_MCU_STM32F0)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3)
// F1: F105, F107 only has 4
// L4: L4x5, L4x6 has 6
// For most mcu, FS has 4, HS has 6
#define DCD_ATTR_ENDPOINT_MAX 6
#elif TU_CHECK_MCU(OPT_MCU_STM32F1)
#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \
defined (STM32F107xB) || defined (STM32F107xC)
#define DCD_ATTR_ENDPOINT_MAX 4
#define DCD_ATTR_DWC2_STM32
#else
#define DCD_ATTR_ENDPOINT_MAX 8
#endif
#elif TU_CHECK_MCU(STM32F7)
#elif TU_CHECK_MCU(OPT_MCU_STM32F2)
// FS has 4 ep, HS has 5 ep
#define DCD_ATTR_ENDPOINT_MAX 6
#define DCD_ATTR_DWC2_STM32
#elif TU_CHECK_MCU(OPT_MCU_STM32F3)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(OPT_MCU_STM32F4)
// For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9
#define DCD_ATTR_ENDPOINT_MAX 6
#define DCD_ATTR_DWC2_STM32
#elif TU_CHECK_MCU(OPT_MCU_STM32F7)
// FS has 6, HS has 9
#define DCD_ATTR_ENDPOINT_MAX 9
#define DCD_ATTR_DWC2_STM32
#elif TU_CHECK_MCU(STM32H7)
#elif TU_CHECK_MCU(OPT_MCU_STM32H7)
#define DCD_ATTR_ENDPOINT_MAX 9
#define DCD_ATTR_DWC2_STM32
#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(OPT_MCU_STM32L4)
#if defined (STM32L475xx) || defined (STM32L476xx) || \
defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \
defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \
defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define DCD_ATTR_ENDPOINT_MAX 6
#define DCD_ATTR_DWC2_STM32
#else
#define DCD_ATTR_ENDPOINT_MAX 8
#endif
//------------- Sony -------------//
#elif TU_CHECK_MCU(CXD56)
#elif TU_CHECK_MCU(OPT_MCU_CXD56)
#define DCD_ATTR_ENDPOINT_MAX 7
#define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
//------------- TI -------------//
#elif TU_CHECK_MCU(MSP430x5xx)
#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx)
#define DCD_ATTR_ENDPOINT_MAX 8
//------------- ValentyUSB -------------//
#elif TU_CHECK_MCU(VALENTYUSB_EPTRI)
#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI)
#define DCD_ATTR_ENDPOINT_MAX 16
//------------- Nuvoton -------------//
#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126)
#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126)
#define DCD_ATTR_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(NUC120)
#elif TU_CHECK_MCU(OPT_MCU_NUC120)
#define DCD_ATTR_ENDPOINT_MAX 6
#elif TU_CHECK_MCU(NUC505)
#elif TU_CHECK_MCU(OPT_MCU_NUC505)
#define DCD_ATTR_ENDPOINT_MAX 12
//------------- Espressif -------------//
#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3)
#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
#define DCD_ATTR_ENDPOINT_MAX 6
//------------- Dialog -------------//
#elif TU_CHECK_MCU(DA1469X)
#elif TU_CHECK_MCU(OPT_MCU_DA1469X)
#define DCD_ATTR_ENDPOINT_MAX 4
//------------- Raspberry Pi -------------//
#elif TU_CHECK_MCU(RP2040)
#elif TU_CHECK_MCU(OPT_MCU_RP2040)
#define DCD_ATTR_ENDPOINT_MAX 16
//------------- Silabs -------------//
#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12)
#elif TU_CHECK_MCU(OPT_MCU_EFM32GG)
#define DCD_ATTR_ENDPOINT_MAX 7
//------------- Renesas -------------//
#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N)
#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
#define DCD_ATTR_ENDPOINT_MAX 10
//#elif TU_CHECK_MCU(MM32F327X)
// #define DCD_ATTR_ENDPOINT_MAX not known yet
//------------- GigaDevice -------------//
#elif TU_CHECK_MCU(GD32VF103)
#elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
#define DCD_ATTR_ENDPOINT_MAX 4
//------------- Broadcom -------------//
#elif TU_CHECK_MCU(OPT_MCU_BCM2711)
#define DCD_ATTR_ENDPOINT_MAX 8
#else
#warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8"
#define DCD_ATTR_ENDPOINT_MAX 8

View File

@@ -34,64 +34,64 @@
// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on.
//------------- NXP -------------//
#if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX)
#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX)
#define HCD_ATTR_OHCI
#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX)
#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
#define HCD_ATTR_EHCI_TRANSDIMENSION
#elif TU_CHECK_MCU(LPC54XXX)
#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX)
// #define HCD_ATTR_EHCI_NXP_PTD
#elif TU_CHECK_MCU(LPC55XX)
#elif TU_CHECK_MCU(OPT_MCU_LPC55XX)
// #define HCD_ATTR_EHCI_NXP_PTD
#elif TU_CHECK_MCU(MIMXRT10XX)
#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX)
#define HCD_ATTR_EHCI_TRANSDIMENSION
#elif TU_CHECK_MCU(MKL25ZXX)
#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX)
//------------- Microchip -------------//
#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \
TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22)
#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \
TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22)
#elif TU_CHECK_MCU(SAMG)
#elif TU_CHECK_MCU(OPT_MCU_SAMG)
#elif TU_CHECK_MCU(SAMX7X)
#elif TU_CHECK_MCU(OPT_MCU_SAMX7X)
//------------- ST -------------//
#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \
TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4)
#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1, OPT_MCU_STM32F3) || \
TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32L4)
#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3)
#elif TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F3, OPT_MCU_STM32F4)
#elif TU_CHECK_MCU(STM32F7)
#elif TU_CHECK_MCU(OPT_MCU_STM32F7)
#elif TU_CHECK_MCU(STM32H7)
#elif TU_CHECK_MCU(OPT_MCU_STM32H7)
//------------- Sony -------------//
#elif TU_CHECK_MCU(CXD56)
#elif TU_CHECK_MCU(OPT_MCU_CXD56)
//------------- Nuvoton -------------//
#elif TU_CHECK_MCU(NUC505)
#elif TU_CHECK_MCU(OPT_MCU_NUC505)
//------------- Espressif -------------//
#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3)
#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
//------------- Raspberry Pi -------------//
#elif TU_CHECK_MCU(RP2040)
#elif TU_CHECK_MCU(OPT_MCU_RP2040)
//------------- Silabs -------------//
#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12)
#elif TU_CHECK_MCU(OPT_MCU_EFM32GG)
//------------- Renesas -------------//
#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N)
#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
//#elif TU_CHECK_MCU(MM32F327X)
//#elif TU_CHECK_MCU(OPT_MCU_MM32F327X)
// #define DCD_ATTR_ENDPOINT_MAX not known yet
//------------- GigaDevice -------------//
#elif TU_CHECK_MCU(GD32VF103)
#elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
#else
// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,936 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Rafael Silva (@perigoso)
* 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.
*/
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && ( \
(CFG_TUSB_MCU == OPT_MCU_EFM32GG) || \
(CFG_TUSB_MCU == OPT_MCU_EFM32GG11) || \
(CFG_TUSB_MCU == OPT_MCU_EFM32GG12) )
/* Silabs */
#include "em_device.h"
#include "device/dcd.h"
/*
* Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
* We disable SOF for now until needed later on
*/
#define USE_SOF 0
/*
* Number of endpoints
* 12 software-configurable endpoints (6 IN, 6 OUT) in addition to endpoint 0
*/
#define EP_COUNT 7
/* FIFO size in bytes */
#define EP_FIFO_SIZE 2048
/* Max number of IN EP FIFOs */
#define EP_FIFO_NUM 7
/* */
typedef struct {
uint8_t *buffer;
uint16_t total_len;
uint16_t queued_len;
uint16_t max_size;
bool short_packet;
} xfer_ctl_t;
static uint32_t _setup_packet[2];
#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
static xfer_ctl_t xfer_status[EP_COUNT][2];
/* Keep count of how many FIFOs are in use */
static uint8_t _allocated_fifos = 1; /* FIFO0 is always in use */
static volatile uint32_t* tx_fifo[EP_FIFO_NUM] = {
USB->FIFO0D,
USB->FIFO1D,
USB->FIFO2D,
USB->FIFO3D,
USB->FIFO4D,
USB->FIFO5D,
USB->FIFO6D,
};
/* Register Helpers */
#define DCTL_WO_BITMASK (USB_DCTL_CGOUTNAK | USB_DCTL_SGOUTNAK | USB_DCTL_CGNPINNAK | USB_DCTL_SGNPINNAK)
#define GUSBCFG_WO_BITMASK (USB_GUSBCFG_CORRUPTTXPKT)
#define DEPCTL_WO_BITMASK (USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF)
/* Will either return an unused FIFO number, or 0 if all are used. */
static uint8_t get_free_fifo(void)
{
if(_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++;
return 0;
}
/*
static void flush_rx_fifo(void)
{
USB->GRSTCTL = USB_GRSTCTL_RXFFLSH;
while(USB->GRSTCTL & USB_GRSTCTL_RXFFLSH);
}
*/
static void flush_tx_fifo(uint8_t fifo_num)
{
USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | (fifo_num << _USB_GRSTCTL_TXFNUM_SHIFT);
while(USB->GRSTCTL & USB_GRSTCTL_TXFFLSH);
}
/* Setup the control endpoint 0. */
static void bus_reset(void)
{
USB->DOEP0CTL |= USB_DIEP_CTL_SNAK;
for(uint8_t i = 0; i < EP_COUNT - 1; i++)
{
USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK;
}
/* reset address */
USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK;
USB->DAINTMSK |= USB_DAINTMSK_OUTEPMSK0 | USB_DAINTMSK_INEPMSK0;
USB->DOEPMSK |= USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK;
USB->DIEPMSK |= USB_DIEPMSK_TIMEOUTMSK | USB_DIEPMSK_XFERCOMPLMSK;
/*
* - All EP OUT shared a unique OUT FIFO which uses
* * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets).
* * 2 locations for OUT endpoint control words.
* * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes)
* * 1 location for global NAK (not required/used here).
* * It is recommended to allocate 2 times the largest packet size, therefore
* Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52
*/
flush_tx_fifo(_USB_GRSTCTL_TXFNUM_FALL); // Flush All
USB->GRXFSIZ = 52;
/* Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) */
USB->GNPTXFSIZ = (16 << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT) | (USB->GRXFSIZ & _USB_GNPTXFSIZ_NPTXFSTADDR_MASK);
/* Ready to receive SETUP packet */
USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT);
USB->GINTMSK |= USB_GINTMSK_IEPINTMSK | USB_GINTMSK_OEPINTMSK;
}
static void enum_done_processing(void)
{
/* Maximum packet size for EP 0 is set for both directions by writing DIEPCTL */
if((USB->DSTS & _USB_DSTS_ENUMSPD_MASK) == USB_DSTS_ENUMSPD_FS)
{
/* Full Speed (PHY on 48 MHz) */
USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_64B; /* Maximum Packet Size 64 bytes */
USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */
xfer_status[0][TUSB_DIR_OUT].max_size = 64;
xfer_status[0][TUSB_DIR_IN].max_size = 64;
}
else
{
/* Low Speed (PHY on 6 MHz) */
USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_8B; /* Maximum Packet Size 64 bytes */
USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */
xfer_status[0][TUSB_DIR_OUT].max_size = 8;
xfer_status[0][TUSB_DIR_IN].max_size = 8;
}
}
/*------------------------------------------------------------------*/
/* Controller API */
/*------------------------------------------------------------------*/
void dcd_init(uint8_t rhport)
{
(void) rhport;
/* Reset Core */
USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE);
/* Core Soft Reset */
USB->GRSTCTL |= USB_GRSTCTL_CSFTRST;
while(USB->GRSTCTL & USB_GRSTCTL_CSFTRST);
while(!(USB->GRSTCTL & USB_GRSTCTL_AHBIDLE));
/* Enable PHY pins */
USB->ROUTE = USB_ROUTE_PHYPEN;
dcd_disconnect(rhport);
/*
* Set device speed (Full speed PHY)
* Stall on non-zero len status OUT packets (ctrl transfers)
* periodic frame interval to 80%
*/
USB->DCFG = (USB->DCFG & ~(_USB_DCFG_DEVSPD_MASK | _USB_DCFG_PERFRINT_MASK)) | USB_DCFG_DEVSPD_FS | USB_DCFG_NZSTSOUTHSHK;
/* Enable Global Interrupts */
USB->GAHBCFG = (USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK) | USB_GAHBCFG_GLBLINTRMSK;
/* Force Device Mode */
USB->GUSBCFG = (USB->GUSBCFG & ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE)) | USB_GUSBCFG_FORCEDEVMODE;
/* No Overrides */
USB->GOTGCTL &= ~(USB_GOTGCTL_BVALIDOVVAL | USB_GOTGCTL_BVALIDOVEN | USB_GOTGCTL_VBVALIDOVVAL);
/* Ignore frame numbers on ISO transfers. */
USB->DCTL = (USB->DCTL & ~DCTL_WO_BITMASK) | USB_DCTL_IGNRFRMNUM;
/* Setting SNAKs */
USB->DOEP0CTL |= USB_DIEP_CTL_SNAK;
for(uint8_t i = 0; i < EP_COUNT - 1; i++)
{
USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK;
}
/* D. Interruption masking */
/* Disable all device interrupts */
USB->DIEPMSK = 0;
USB->DOEPMSK = 0;
USB->DAINTMSK = 0;
USB->DIEPEMPMSK = 0;
USB->GINTMSK = 0;
USB->GOTGINT = ~0U; /* clear OTG ints */
USB->GINTSTS = ~0U; /* clear pending ints */
USB->GINTMSK = USB_GINTMSK_MODEMISMSK |
#if USE_SOF
USB_GINTMSK_SOFMSK |
#endif
USB_GINTMSK_ERLYSUSPMSK |
USB_GINTMSK_USBSUSPMSK |
USB_GINTMSK_USBRSTMSK |
USB_GINTMSK_ENUMDONEMSK |
USB_GINTMSK_RESETDETMSK |
USB_GINTMSK_DISCONNINTMSK;
NVIC_ClearPendingIRQ(USB_IRQn);
dcd_connect(rhport);
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
(void) rhport;
USB->DCFG = (USB->DCFG & ~_USB_DCFG_DEVADDR_MASK) | (dev_addr << _USB_DCFG_DEVADDR_SHIFT);
/* Response with status after changing device address */
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
}
void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
}
void dcd_connect(uint8_t rhport)
{
(void) rhport;
/* connect by enabling internal pull-up resistor on D+/D- */
USB->DCTL &= ~(DCTL_WO_BITMASK | USB_DCTL_SFTDISCON);
}
void dcd_disconnect(uint8_t rhport)
{
(void) rhport;
/* disconnect by disabling internal pull-up resistor on D+/D- */
USB->DCTL = (USB->DCTL & ~(DCTL_WO_BITMASK)) | USB_DCTL_SFTDISCON;
}
/*------------------------------------------------------------------*/
/* DCD Endpoint Port */
/*------------------------------------------------------------------*/
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
if(dir == TUSB_DIR_IN)
{
if(epnum == 0)
{
USB->DIEP0CTL = (USB->DIEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_SNAK | USB_DIEP0CTL_STALL;
flush_tx_fifo(_USB_GRSTCTL_TXFNUM_F0);
}
else
{
/* Only disable currently enabled non-control endpoint */
if(USB->DIEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA)
{
USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL;
while(!(USB->DIEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD));
USB->DIEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD;
}
else
{
USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL;
}
/* Flush the FIFO */
uint8_t const fifo_num = ((USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_TXFNUM_MASK) >> _USB_DIEP_CTL_TXFNUM_SHIFT);
flush_tx_fifo(fifo_num);
}
}
else
{
if(epnum == 0)
{
USB->DOEP0CTL = (USB->DOEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_STALL;
}
else
{
/* Only disable currently enabled non-control endpoint */
if(USB->DOEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA)
{
/* Asserting GONAK is required to STALL an OUT endpoint. */
USB->DCTL |= USB_DCTL_SGOUTNAK;
while(!(USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF));
/* Disable the endpoint. Note that only STALL and not SNAK is set here. */
USB->DOEP[epnum - 1].CTL = (USB->DOEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_STALL;
while(USB->DOEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD);
USB->DOEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD;
/* Allow other OUT endpoints to keep receiving. */
USB->DCTL |= USB_DCTL_CGOUTNAK;
}
else
{
USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_STALL;
}
}
}
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
if(dir == TUSB_DIR_IN)
{
if(epnum == 0)
{
USB->DIEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP0CTL_STALL);
}
else
{
USB->DIEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP_CTL_STALL);
/* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */
uint8_t eptype = (USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_EPTYPE_MASK) >> _USB_DIEP_CTL_EPTYPE_SHIFT;
if((eptype == _USB_DIEP_CTL_EPTYPE_BULK) || (eptype == _USB_DIEP_CTL_EPTYPE_INT))
{
USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_SETD0PIDEF;
}
}
}
else
{
if(epnum == 0)
{
USB->DOEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP0CTL_STALL);
}
else
{
USB->DOEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP_CTL_STALL);
/* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */
uint8_t eptype = (USB->DOEP[epnum - 1].CTL & _USB_DOEP_CTL_EPTYPE_MASK) >> _USB_DOEP_CTL_EPTYPE_SHIFT;
if((eptype == _USB_DOEP_CTL_EPTYPE_BULK) || (eptype == _USB_DOEP_CTL_EPTYPE_INT))
{
USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_SETD0PIDEF;
}
}
}
}
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
{
(void)rhport;
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
TU_ASSERT(epnum < EP_COUNT);
TU_ASSERT(epnum != 0);
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir);
xfer->max_size = tu_edpt_packet_size(p_endpoint_desc);
if(dir == TUSB_DIR_OUT)
{
USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_USBACTEP |
(p_endpoint_desc->bmAttributes.xfer << _USB_DOEP_CTL_EPTYPE_SHIFT) |
(xfer->max_size << _USB_DOEP_CTL_MPS_SHIFT);
USB->DAINTMSK |= (1 << (_USB_DAINTMSK_OUTEPMSK0_SHIFT + epnum));
}
else
{
uint8_t fifo_num = get_free_fifo();
TU_ASSERT(fifo_num != 0);
USB->DIEP[epnum - 1].CTL &= ~(_USB_DIEP_CTL_TXFNUM_MASK | _USB_DIEP_CTL_EPTYPE_MASK | USB_DIEP_CTL_SETD0PIDEF | _USB_DIEP_CTL_MPS_MASK);
USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_USBACTEP |
(fifo_num << _USB_DIEP_CTL_TXFNUM_SHIFT) |
(p_endpoint_desc->bmAttributes.xfer << _USB_DIEP_CTL_EPTYPE_SHIFT) |
((p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) ? USB_DIEP_CTL_SETD0PIDEF : 0) |
(xfer->max_size << 0);
USB->DAINTMSK |= (1 << epnum);
/* Both TXFD and TXSA are in unit of 32-bit words. */
/* IN FIFO 0 was configured during enumeration, hence the "+ 16". */
uint16_t const allocated_size = (USB->GRXFSIZ & _USB_GRXFSIZ_RXFDEP_MASK) + 16;
uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1);
uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1);
/* DIEPTXF starts at FIFO #1. */
volatile uint32_t* usb_dieptxf = &USB->DIEPTXF1;
usb_dieptxf[epnum - 1] = (fifo_size << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT) | fifo_offset;
}
return true;
}
void dcd_edpt_close_all (uint8_t rhport)
{
(void) rhport;
// TODO implement dcd_edpt_close_all()
}
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
{
(void)rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
xfer->buffer = buffer;
xfer->total_len = total_bytes;
xfer->queued_len = 0;
xfer->short_packet = false;
uint16_t num_packets = (total_bytes / xfer->max_size);
uint8_t short_packet_size = total_bytes % xfer->max_size;
// Zero-size packet is special case.
if(short_packet_size > 0 || (total_bytes == 0))
{
num_packets++;
}
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them
// here.
if(dir == TUSB_DIR_IN)
{
if(epnum == 0)
{
// A full IN transfer (multiple packets, possibly) triggers XFRC.
USB->DIEP0TSIZ = (num_packets << _USB_DIEP0TSIZ_PKTCNT_SHIFT) | total_bytes;
USB->DIEP0CTL |= USB_DIEP0CTL_EPENA | USB_DIEP0CTL_CNAK; // Enable | CNAK
}
else
{
// A full IN transfer (multiple packets, possibly) triggers XFRC.
USB->DIEP[epnum - 1].TSIZ = (num_packets << _USB_DIEP_TSIZ_PKTCNT_SHIFT) | total_bytes;
USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_EPENA | USB_DIEP_CTL_CNAK; // Enable | CNAK
}
// Enable fifo empty interrupt only if there are something to put in the fifo.
if(total_bytes != 0)
{
USB->DIEPEMPMSK |= (1 << epnum);
}
}
else
{
if(epnum == 0)
{
// A full IN transfer (multiple packets, possibly) triggers XFRC.
USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK;
}
else
{
// A full IN transfer (multiple packets, possibly) triggers XFRC.
USB->DOEP[epnum - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT);
USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK;
}
}
return true;
}
/*------------------------------------------------------------------*/
/* IRQ */
/*------------------------------------------------------------------*/
void dcd_int_enable(uint8_t rhport)
{
(void) rhport;
NVIC_EnableIRQ(USB_IRQn);
}
void dcd_int_disable(uint8_t rhport)
{
(void) rhport;
NVIC_DisableIRQ(USB_IRQn);
}
static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size)
{
uint16_t remaining = xfer->total_len - xfer->queued_len;
uint16_t to_recv_size;
if(remaining <= xfer->max_size)
{
/* Avoid buffer overflow. */
to_recv_size = (xfer_size > remaining) ? remaining : xfer_size;
}
else
{
/* Room for full packet, choose recv_size based on what the microcontroller claims. */
to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size;
}
uint8_t to_recv_rem = to_recv_size % 4;
uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem;
/* Do not assume xfer buffer is aligned. */
uint8_t *base = (xfer->buffer + xfer->queued_len);
/* This for loop always runs at least once- skip if less than 4 bytes to collect. */
if(to_recv_size >= 4)
{
for(uint16_t i = 0; i < to_recv_size_aligned; i += 4)
{
uint32_t tmp = (*USB->FIFO0D);
base[i] = tmp & 0x000000FF;
base[i + 1] = (tmp & 0x0000FF00) >> 8;
base[i + 2] = (tmp & 0x00FF0000) >> 16;
base[i + 3] = (tmp & 0xFF000000) >> 24;
}
}
/* Do not read invalid bytes from RX FIFO. */
if(to_recv_rem != 0)
{
uint32_t tmp = (*USB->FIFO0D);
uint8_t *last_32b_bound = base + to_recv_size_aligned;
last_32b_bound[0] = tmp & 0x000000FF;
if(to_recv_rem > 1)
{
last_32b_bound[1] = (tmp & 0x0000FF00) >> 8;
}
if(to_recv_rem > 2)
{
last_32b_bound[2] = (tmp & 0x00FF0000) >> 16;
}
}
xfer->queued_len += xfer_size;
/* Per USB spec, a short OUT packet (including length 0) is always */
/* indicative of the end of a transfer (at least for ctl, bulk, int). */
xfer->short_packet = (xfer_size < xfer->max_size);
}
static void transmit_packet(xfer_ctl_t *xfer, uint8_t fifo_num)
{
uint16_t remaining;
if(fifo_num == 0)
{
remaining = (USB->DIEP0TSIZ & 0x7FFFFU) >> _USB_DIEP0TSIZ_XFERSIZE_SHIFT;
}
else
{
remaining = (USB->DIEP[fifo_num - 1].TSIZ & 0x7FFFFU) >> _USB_DIEP_TSIZ_XFERSIZE_SHIFT;
}
xfer->queued_len = xfer->total_len - remaining;
uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining;
uint8_t to_xfer_rem = to_xfer_size % 4;
uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem;
/* Buffer might not be aligned to 32b, so we need to force alignment by copying to a temp var. */
uint8_t *base = (xfer->buffer + xfer->queued_len);
/* This for loop always runs at least once- skip if less than 4 bytes to send off. */
if(to_xfer_size >= 4)
{
for(uint16_t i = 0; i < to_xfer_size_aligned; i += 4)
{
uint32_t tmp = base[i] | (base[i + 1] << 8) | (base[i + 2] << 16) | (base[i + 3] << 24);
*tx_fifo[fifo_num] = tmp;
}
}
/* Do not read beyond end of buffer if not divisible by 4. */
if(to_xfer_rem != 0)
{
uint32_t tmp = 0;
uint8_t *last_32b_bound = base + to_xfer_size_aligned;
tmp |= last_32b_bound[0];
if(to_xfer_rem > 1)
{
tmp |= (last_32b_bound[1] << 8);
}
if(to_xfer_rem > 2)
{
tmp |= (last_32b_bound[2] << 16);
}
*tx_fifo[fifo_num] = tmp;
}
}
static void read_rx_fifo(void)
{
/*
* Pop control word off FIFO (completed xfers will have 2 control words,
* we only pop one ctl word each interrupt).
*/
uint32_t const ctl_word = USB->GRXSTSP;
uint8_t const pktsts = (ctl_word & _USB_GRXSTSP_PKTSTS_MASK) >> _USB_GRXSTSP_PKTSTS_SHIFT;
uint8_t const epnum = (ctl_word & _USB_GRXSTSP_CHNUM_MASK ) >> _USB_GRXSTSP_CHNUM_SHIFT;
uint16_t const bcnt = (ctl_word & _USB_GRXSTSP_BCNT_MASK ) >> _USB_GRXSTSP_BCNT_SHIFT;
switch(pktsts)
{
case 0x01: /* Global OUT NAK (Interrupt) */
break;
case 0x02:
{
/* Out packet recvd */
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
receive_packet(xfer, bcnt);
}
break;
case 0x03:
/* Out packet done (Interrupt) */
break;
case 0x04:
/* Step 2: Setup transaction completed (Interrupt) */
/* After this event, OEPINT interrupt will occur with SETUP bit set */
if(epnum == 0)
{
USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT);
}
break;
case 0x06:
{
/* Step1: Setup data packet received */
/*
* We can receive up to three setup packets in succession, but
* only the last one is valid. Therefore we just overwrite it
*/
_setup_packet[0] = (*USB->FIFO0D);
_setup_packet[1] = (*USB->FIFO0D);
}
break;
default:
/* Invalid, breakpoint. */
TU_BREAKPOINT();
break;
}
}
static void handle_epout_ints(void)
{
// GINTSTS will be cleared with DAINT == 0
// DAINT for a given EP clears when DOEPINTx is cleared.
// DOEPINT will be cleared when DAINT's out bits are cleared.
for(uint8_t n = 0; n < EP_COUNT; n++)
{
xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
if(n == 0)
{
if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n)))
{
// SETUP packet Setup Phase done.
if((USB->DOEP0INT & USB_DOEP0INT_SETUP))
{
USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD | USB_DOEP0INT_SETUP; // clear
dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true);
}
// OUT XFER complete (single packet).q
if(USB->DOEP0INT & USB_DOEP0INT_XFERCOMPL)
{
USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL;
// Transfer complete if short packet or total len is transferred
if(xfer->short_packet || (xfer->queued_len == xfer->total_len))
{
xfer->short_packet = false;
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
}
else
{
// Schedule another packet to be received.
USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK;
}
}
}
}
else
{
if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n)))
{
// SETUP packet Setup Phase done.
if((USB->DOEP[n - 1].INT & USB_DOEP_INT_SETUP))
{
USB->DOEP[n - 1].INT = USB_DOEP_INT_STUPPKTRCVD | USB_DOEP_INT_SETUP; // clear
dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true);
}
// OUT XFER complete (single packet).q
if(USB->DOEP[n - 1].INT & USB_DOEP_INT_XFERCOMPL)
{
USB->DOEP[n - 1].INT = USB_DOEP_INT_XFERCOMPL;
// Transfer complete if short packet or total len is transferred
if(xfer->short_packet || (xfer->queued_len == xfer->total_len))
{
xfer->short_packet = false;
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
}
else
{
// Schedule another packet to be received.
USB->DOEP[n - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT);
USB->DOEP[n - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK;
}
}
}
}
}
}
static void handle_epin_ints(void)
{
for(uint32_t n = 0; n < EP_COUNT; n++)
{
xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN];
if(n == 0)
{
if(USB->DAINT & (1 << n))
{
/* IN XFER complete (entire xfer). */
if(USB->DIEP0INT & USB_DIEP0INT_XFERCOMPL)
{
USB->DIEP0INT = USB_DIEP0INT_XFERCOMPL;
dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
/* XFER FIFO empty */
if(USB->DIEP0INT & USB_DIEP0INT_TXFEMP)
{
USB->DIEP0INT = USB_DIEP0INT_TXFEMP;
transmit_packet(xfer, n);
/* Turn off TXFE if all bytes are written. */
if(xfer->queued_len == xfer->total_len)
{
USB->DIEPEMPMSK &= ~(1 << n);
}
}
/* XFER Timeout */
if(USB->DIEP0INT & USB_DIEP0INT_TIMEOUT)
{
/* Clear interrupt or enpoint will hang. */
USB->DIEP0INT = USB_DIEP0INT_TIMEOUT;
}
}
}
else
{
if(USB->DAINT & (1 << n))
{
/* IN XFER complete (entire xfer). */
if(USB->DIEP[n - 1].INT & USB_DIEP_INT_XFERCOMPL)
{
USB->DIEP[n - 1].INT = USB_DIEP_INT_XFERCOMPL;
dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
/* XFER FIFO empty */
if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TXFEMP)
{
USB->DIEP[n - 1].INT = USB_DIEP_INT_TXFEMP;
transmit_packet(xfer, n);
/* Turn off TXFE if all bytes are written. */
if(xfer->queued_len == xfer->total_len)
{
USB->DIEPEMPMSK &= ~(1 << n);
}
}
/* XFER Timeout */
if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TIMEOUT)
{
/* Clear interrupt or enpoint will hang. */
USB->DIEP[n - 1].INT = USB_DIEP_INT_TIMEOUT;
}
}
}
}
}
void dcd_int_handler(uint8_t rhport)
{
(void) rhport;
const uint32_t int_status = USB->GINTSTS;
/* USB Reset */
if(int_status & USB_GINTSTS_USBRST)
{
/* start of reset */
USB->GINTSTS = USB_GINTSTS_USBRST;
/* FIFOs will be reassigned when the endpoints are reopen */
_allocated_fifos = 1;
bus_reset();
}
/* Reset detected Interrupt */
if(int_status & USB_GINTSTS_RESETDET)
{
USB->GINTSTS = USB_GINTSTS_RESETDET;
bus_reset();
}
/* Enumeration Done */
if(int_status & USB_GINTSTS_ENUMDONE)
{
/* This interrupt is considered the end of reset. */
USB->GINTSTS = USB_GINTSTS_ENUMDONE;
enum_done_processing();
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
}
/* OTG Interrupt */
if(int_status & USB_GINTSTS_OTGINT)
{
/* OTG INT bit is read-only */
uint32_t const otg_int = USB->GOTGINT;
if(otg_int & USB_GOTGINT_SESENDDET)
{
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
}
USB->GOTGINT = otg_int;
}
#if USE_SOF
if(int_status & USB_GINTSTS_SOF)
{
USB->GINTSTS = USB_GINTSTS_SOF;
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
}
#endif
/* RxFIFO Non-Empty */
if(int_status & USB_GINTSTS_RXFLVL)
{
/* RXFLVL bit is read-only */
/* Mask out RXFLVL while reading data from FIFO */
USB->GINTMSK &= ~USB_GINTMSK_RXFLVLMSK;
read_rx_fifo();
USB->GINTMSK |= USB_GINTMSK_RXFLVLMSK;
}
/* OUT Endpoints Interrupt */
if(int_status & USB_GINTMSK_OEPINTMSK)
{
/* OEPINT is read-only */
handle_epout_ints();
}
/* IN Endpoints Interrupt */
if(int_status & USB_GINTMSK_IEPINTMSK)
{
/* IEPINT bit read-only */
handle_epin_ints();
}
/* unhandled */
USB->GINTSTS |= USB_GINTSTS_CURMOD |
USB_GINTSTS_MODEMIS |
USB_GINTSTS_OTGINT |
USB_GINTSTS_NPTXFEMP |
USB_GINTSTS_GINNAKEFF |
USB_GINTSTS_GOUTNAKEFF |
USB_GINTSTS_ERLYSUSP |
USB_GINTSTS_USBSUSP |
USB_GINTSTS_ISOOUTDROP |
USB_GINTSTS_EOPF |
USB_GINTSTS_EPMIS |
USB_GINTSTS_INCOMPISOIN |
USB_GINTSTS_INCOMPLP |
USB_GINTSTS_FETSUSP |
USB_GINTSTS_PTXFEMP;
}
#endif

View File

@@ -109,13 +109,10 @@
#define STM32F1_FSDEV
#endif
#if (TUSB_OPT_DEVICE_ENABLED) && ( \
(CFG_TUSB_MCU == OPT_MCU_STM32F0 ) || \
(CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_FSDEV)) || \
(CFG_TUSB_MCU == OPT_MCU_STM32F3 ) || \
(CFG_TUSB_MCU == OPT_MCU_STM32L0 ) || \
(CFG_TUSB_MCU == OPT_MCU_STM32L1 ) \
)
#if TUSB_OPT_DEVICE_ENABLED && \
( TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F3, OPT_MCU_STM32L0, OPT_MCU_STM32L1) || \
(TU_CHECK_MCU(OPT_MCU_STM32F1) && defined(STM32F1_FSDEV)) \
)
// In order to reduce the dependance on HAL, we undefine this.
// Some definitions are copied to our private include file.

View File

@@ -370,7 +370,7 @@ static bool USB_HS_PHYCInit(void)
{
USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE;
// Enable LDO
// Enable LDO: Note STM32F72/3xx Reference Manual rev 3 June 2018 incorrectly defined this bit as Disabled !!
usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE;
// Wait until LDO ready

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
/*
* 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 _TUSB_DWC2_BCM_H_
#define _TUSB_DWC2_BCM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "broadcom/interrupts.h"
#include "broadcom/caches.h"
#define DWC2_REG_BASE 0xFE980000UL
#define DWC2_EP_MAX 8
#define DWC2_EP_FIFO_SIZE 4096
#define dcache_clean(_addr, _size) data_clean(_addr, _size)
#define dcache_invalidate(_addr, _size) data_invalidate(_addr, _size)
#define dcache_clean_invalidate(_addr, _size) data_clean_and_invalidate(_addr, _size)
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable(uint8_t rhport)
{
(void) rhport;
BP_EnableIRQ(USB_IRQn);
__asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !?
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
BP_DisableIRQ(USB_IRQn);
__asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !?
}
static inline void dwc2_remote_wakeup_delay(void)
{
// try to delay for 1 ms
// TODO implement later
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,87 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Rafael Silva (@perigoso)
* 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 _DWC2_EFM32_H_
#define _DWC2_EFM32_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "em_device.h"
// EFM32 has custom control register before DWC registers
#define DWC2_REG_BASE (USB_BASE + offsetof(USB_TypeDef, GOTGCTL))
#define DWC2_EP_MAX 7
#define DWC2_EP_FIFO_SIZE 2048
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable(uint8_t rhport)
{
(void) rhport;
NVIC_EnableIRQ(USB_IRQn);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
NVIC_DisableIRQ(USB_IRQn);
}
static inline void dwc2_remote_wakeup_delay(void)
{
// try to delay for 1 ms
// uint32_t count = SystemCoreClock / 1000;
// while ( count-- ) __NOP();
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// Enable PHY
USB->ROUTE = USB_ROUTE_PHYPEN;
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// EFM32 Manual: turn around must be 5 (reset & default value)
// dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,94 @@
/*
* 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 _DWC2_ESP32_H_
#define _DWC2_ESP32_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
//#include "soc/usb_periph.h"
#define DWC2_REG_BASE 0x60080000UL
#define DWC2_EP_MAX 5 // USB_OUT_EP_NUM
#define DWC2_EP_FIFO_SIZE 1024
// #define EP_FIFO_NUM 5
static intr_handle_t usb_ih;
static void dcd_int_handler_wrap(void* arg)
{
(void) arg;
dcd_int_handler(0);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable (uint8_t rhport)
{
(void) rhport;
esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, dcd_int_handler_wrap, NULL, &usb_ih);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
esp_intr_free(usb_ih);
}
static inline void dwc2_remote_wakeup_delay(void)
{
vTaskDelay(pdMS_TO_TICKS(1));
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
#ifdef __cplusplus
}
#endif
#endif /* _DWC2_ESP32_H_ */

View File

@@ -0,0 +1,100 @@
/*
* 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 DWC2_GD32_H_
#define DWC2_GD32_H_
#ifdef __cplusplus
extern "C" {
#endif
#define DWC2_REG_BASE 0x50000000UL
#define DWC2_EP_MAX 4
#define DWC2_EP_FIFO_SIZE 1280
#define RHPORT_IRQn 86
extern uint32_t SystemCoreClock;
// The GD32VF103 is a RISC-V MCU, which implements the ECLIC Core-Local
// Interrupt Controller by Nuclei. It is nearly API compatible to the
// NVIC used by ARM MCUs.
#define ECLIC_INTERRUPT_ENABLE_BASE 0xD2001001UL
TU_ATTR_ALWAYS_INLINE
static inline void __eclic_enable_interrupt (uint32_t irq) {
*(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 1;
}
TU_ATTR_ALWAYS_INLINE
static inline void __eclic_disable_interrupt (uint32_t irq){
*(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0;
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable(uint8_t rhport)
{
(void) rhport;
__eclic_enable_interrupt(RHPORT_IRQn);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
__eclic_disable_interrupt(RHPORT_IRQn);
}
static inline void dwc2_remote_wakeup_delay(void)
{
// try to delay for 1 ms
uint32_t count = SystemCoreClock / 1000;
while ( count-- ) __asm volatile ("nop");
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
(void) dwc2;
(void) hs_phy_type;
// nothing to do
}
#ifdef __cplusplus
}
#endif
#endif /* DWC2_GD32_H_ */

View File

@@ -0,0 +1,205 @@
/*
* 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 _DWC2_STM32_H_
#define _DWC2_STM32_H_
#ifdef __cplusplus
extern "C" {
#endif
// EP_MAX : Max number of bi-directional endpoints including EP0
// EP_FIFO_SIZE : Size of dedicated USB SRAM
#if CFG_TUSB_MCU == OPT_MCU_STM32F1
#include "stm32f1xx.h"
#define EP_MAX_FS 4
#define EP_FIFO_SIZE_FS 1280
#elif CFG_TUSB_MCU == OPT_MCU_STM32F2
#include "stm32f2xx.h"
#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS
#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE
#elif CFG_TUSB_MCU == OPT_MCU_STM32F4
#include "stm32f4xx.h"
#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS
#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE
#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS
#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE
#elif CFG_TUSB_MCU == OPT_MCU_STM32H7
#include "stm32h7xx.h"
#define EP_MAX_FS 9
#define EP_FIFO_SIZE_FS 4096
#define EP_MAX_HS 9
#define EP_FIFO_SIZE_HS 4096
#elif CFG_TUSB_MCU == OPT_MCU_STM32F7
#include "stm32f7xx.h"
#define EP_MAX_FS 6
#define EP_FIFO_SIZE_FS 1280
#define EP_MAX_HS 9
#define EP_FIFO_SIZE_HS 4096
#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
#include "stm32l4xx.h"
#define EP_MAX_FS 6
#define EP_FIFO_SIZE_FS 1280
#else
#error "Unsupported MCUs"
#endif
// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS
#if TUD_OPT_RHPORT == 0
#define DWC2_REG_BASE USB_OTG_FS_PERIPH_BASE
#define DWC2_EP_MAX EP_MAX_FS
#define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_FS
#define RHPORT_IRQn OTG_FS_IRQn
#else
#define DWC2_REG_BASE USB_OTG_HS_PERIPH_BASE
#define DWC2_EP_MAX EP_MAX_HS
#define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_HS
#define RHPORT_IRQn OTG_HS_IRQn
#endif
extern uint32_t SystemCoreClock;
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_enable(uint8_t rhport)
{
(void) rhport;
NVIC_EnableIRQ(RHPORT_IRQn);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_dcd_int_disable (uint8_t rhport)
{
(void) rhport;
NVIC_DisableIRQ(RHPORT_IRQn);
}
TU_ATTR_ALWAYS_INLINE
static inline void dwc2_remote_wakeup_delay(void)
{
// try to delay for 1 ms
uint32_t count = SystemCoreClock / 1000;
while ( count-- ) __NOP();
}
// MCU specific PHY init, called BEFORE core reset
static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
if ( hs_phy_type == HS_PHY_TYPE_NONE )
{
// Enable on-chip FS PHY
dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN;
}else
{
// Disable FS PHY
dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN;
// Enable on-chip HS PHY
if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI)
{
#ifdef USB_HS_PHYC
// Enable UTMI HS PHY
dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN;
// Enable LDO
USB_HS_PHYC->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE;
// Wait until LDO ready
while ( 0 == (USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {}
uint32_t phyc_pll = 0;
// TODO Try to get HSE_VALUE from registers instead of depending CFLAGS
switch ( HSE_VALUE )
{
case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break;
case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break;
case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break;
case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break;
case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break;
case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header
default:
TU_ASSERT(false, );
}
USB_HS_PHYC->USB_HS_PHYC_PLL = phyc_pll;
// Control the tuning interface of the High Speed PHY
// Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver for F7
USB_HS_PHYC->USB_HS_PHYC_TUNE |= 0x00000F13U;
// Enable PLL internal PHY
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN;
#endif
}
}
}
// MCU specific PHY update, it is called AFTER init() and core reset
static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
{
// used to set turnaround time for fullspeed, nothing to do in highspeed mode
if ( hs_phy_type == HS_PHY_TYPE_NONE )
{
// Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual
uint32_t turnaround;
if ( SystemCoreClock >= 32000000u )
turnaround = 0x6u;
else if ( SystemCoreClock >= 27500000u )
turnaround = 0x7u;
else if ( SystemCoreClock >= 24000000u )
turnaround = 0x8u;
else if ( SystemCoreClock >= 21800000u )
turnaround = 0x9u;
else if ( SystemCoreClock >= 20000000u )
turnaround = 0xAu;
else if ( SystemCoreClock >= 18500000u )
turnaround = 0xBu;
else if ( SystemCoreClock >= 17200000u )
turnaround = 0xCu;
else if ( SystemCoreClock >= 16000000u )
turnaround = 0xDu;
else if ( SystemCoreClock >= 15000000u )
turnaround = 0xEu;
else
turnaround = 0xFu;
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos);
}
}
#ifdef __cplusplus
}
#endif
#endif /* _DWC2_STM32_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,722 @@
# DWC2 Hardware Configuration Registers
## Broadcom BCM2711 (Pi4)
dwc2->guid = 2708A000
dwc2->gsnpsid = 4F54280A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 228DDD50
hw_cfg2->op_mode = 0
hw_cfg2->arch = 2
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 1
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 7
hw_cfg2->num_host_ch = 7
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 0
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = FF000E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 4080
dwc2->ghwcfg4 = 1FF00020
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 0
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 15
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## EFM32GG FS
dwc2->guid = 0
dwc2->gsnpsid = 4F54330A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 228F5910
hw_cfg2->op_mode = 0
hw_cfg2->arch = 2
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 6
hw_cfg2->num_host_ch = 13
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 0
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 1F204E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 1
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 498
dwc2->ghwcfg4 = 1BF08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 13
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## ESP32-S2 Fullspeed
dwc2->guid = 0
dwc2->gsnpsid = 4F54400A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 224DD930
hw_cfg2->op_mode = 2
hw_cfg2->arch = 3
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 1
hw_cfg2->fs_phy_type = 2
hw_cfg2->num_dev_ep = 6
hw_cfg2->num_host_ch = 9
hw_cfg2->period_channel_support = 0
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 1
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 22
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = C804B5
hw_cfg3->xfer_size_width = 10
hw_cfg3->packet_size_width = 5
hw_cfg3->otg_enable = 0
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 1
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 1
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 23130
dwc2->ghwcfg4 = D3F0A030
hw_cfg4->num_dev_period_in_ep = 10
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 0
hw_cfg4->hibernation = 1
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 1
hw_cfg4->acg_enable = 1
hw_cfg4->utmi_phy_data_width = 1
hw_cfg4->dev_ctrl_ep_num = 10
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 0
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 0
hw_cfg4->dedicated_fifos = 0
hw_cfg4->num_dev_in_eps = 13
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 1
## STM32F407 and STM32F207
STM32F407 and STM32F207 are exactly the same
### STM32F407 Fullspeed
dwc2->guid = 1200
dwc2->gsnpsid = 4F54281A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229DCD20
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 3
hw_cfg2->num_host_ch = 7
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 20001E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = FF08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 7
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
### STM32F407 Highspeed
dwc2->guid = 1100
dwc2->gsnpsid = 4F54281A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229ED590
hw_cfg2->op_mode = 0
hw_cfg2->arch = 2
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 2
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 5
hw_cfg2->num_host_ch = 11
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 3F403E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 1
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 1012
dwc2->ghwcfg4 = 17F00030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 11
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## STM32F411 Fullspeed
dwc2->guid = 1200
dwc2->gsnpsid = 4F54281A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229DCD20
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 3
hw_cfg2->num_host_ch = 7
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 20001E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = FF08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 7
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## STM32F412 FS
dwc2->guid = 2000
dwc2->gsnpsid = 4F54320A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229ED520
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 5
hw_cfg2->num_host_ch = 11
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 200D1E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = 17F08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 11
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## STM32F723
### STM32F723 HighSpeed
dwc2->guid = 3100
dwc2->gsnpsid = 4F54330A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229FE1D0
hw_cfg2->op_mode = 0
hw_cfg2->arch = 2
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 3
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 8
hw_cfg2->num_host_ch = 15
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 3EED2E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 1
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 1006
dwc2->ghwcfg4 = 23F00030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 1
hw_cfg4->dma_desc_enable = 1
hw_cfg4->dma_dynamic = 0
### STM32F723 Fullspeed
dwc2->guid = 3000
dwc2->gsnpsid = 4F54330A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229ED520
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 5
hw_cfg2->num_host_ch = 11
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 200D1E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = 17F08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 11
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## STM32F767 FS
dwc2->guid = 2000
dwc2->gsnpsid = 4F54320A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229ED520
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 5
hw_cfg2->num_host_ch = 11
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 200D1E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = 17F08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 11
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## STM32H743 (both cores HS)
dwc2->guid = 2300
dwc2->gsnpsid = 4F54330A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229FE190
hw_cfg2->op_mode = 0
hw_cfg2->arch = 2
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 2
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 8
hw_cfg2->num_host_ch = 15
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 3B8D2E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 1
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 952
dwc2->ghwcfg4 = E3F00030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 1
hw_cfg4->dma_desc_enable = 1
hw_cfg4->dma_dynamic = 1
## STM32L476 FS
dwc2->guid = 2000
dwc2->gsnpsid = 4F54310A
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 229ED520
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 1
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 1
hw_cfg2->num_dev_ep = 5
hw_cfg2->num_host_ch = 11
hw_cfg2->period_channel_support = 1
hw_cfg2->enable_dynamic_fifo = 1
hw_cfg2->mul_cpu_int = 1
hw_cfg2->nperiod_tx_q_depth = 2
hw_cfg2->host_period_tx_q_depth = 2
hw_cfg2->dev_token_q_depth = 8
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 200D1E8
hw_cfg3->xfer_size_width = 8
hw_cfg3->packet_size_width = 6
hw_cfg3->otg_enable = 1
hw_cfg3->i2c_enable = 1
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 1
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 1
hw_cfg3->lpm_mode = 1
hw_cfg3->total_fifo_size = 512
dwc2->ghwcfg4 = 17F08030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 1
hw_cfg4->ahb_freq_min = 1
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 2
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 1
hw_cfg4->vbus_valid_filter_enabled = 1
hw_cfg4->a_valid_filter_enabled = 1
hw_cfg4->b_valid_filter_enabled = 1
hw_cfg4->dedicated_fifos = 1
hw_cfg4->num_dev_in_eps = 11
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
## GD32VF103 Fullspeed
dwc2->guid = 1000
dwc2->gsnpsid = 0
dwc2->ghwcfg1 = 0
dwc2->ghwcfg2 = 0
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 0
hw_cfg2->num_dev_ep = 0
hw_cfg2->num_host_ch = 0
hw_cfg2->period_channel_support = 0
hw_cfg2->enable_dynamic_fifo = 0
hw_cfg2->mul_cpu_int = 0
hw_cfg2->nperiod_tx_q_depth = 0
hw_cfg2->host_period_tx_q_depth = 0
hw_cfg2->dev_token_q_depth = 0
hw_cfg2->otg_enable_ic_usb = 0
dwc2->ghwcfg3 = 0
hw_cfg3->xfer_size_width = 0
hw_cfg3->packet_size_width = 0
hw_cfg3->otg_enable = 0
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 0
dwc2->ghwcfg4 = 0
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 0
hw_cfg4->ahb_freq_min = 0
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 0
hw_cfg4->vbus_valid_filter_enabled = 0
hw_cfg4->a_valid_filter_enabled = 0
hw_cfg4->b_valid_filter_enabled = 0
hw_cfg4->dedicated_fifos = 0
hw_cfg4->num_dev_in_eps = 0
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0

View File

@@ -27,6 +27,8 @@
#ifndef _TUSB_OPTION_H_
#define _TUSB_OPTION_H_
#include "common/tusb_compiler.h"
#define TUSB_VERSION_MAJOR 0
#define TUSB_VERSION_MINOR 12
#define TUSB_VERSION_REVISION 0
@@ -36,7 +38,6 @@
// Supported MCUs
// CFG_TUSB_MCU must be defined to one of following value
//--------------------------------------------------------------------+
#define TU_CHECK_MCU(_m) (CFG_TUSB_MCU == OPT_MCU_##_m)
#define OPT_MCU_NONE 0
@@ -112,8 +113,6 @@
// Silabs
#define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG
#define OPT_MCU_EFM32GG11 1301 ///< Silabs EFM32GG11
#define OPT_MCU_EFM32GG12 1302 ///< Silabs EFM32GG12
// Renesas RX
#define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631
@@ -126,6 +125,14 @@
// GigaDevice
#define OPT_MCU_GD32VF103 1600 ///< GigaDevice GD32VF103
// Broadcom
#define OPT_MCU_BCM2711 1700 ///< Broadcom BCM2711
// Helper to check if configured MCU is one of listed
// Apply _TU_CHECK_MCU with || as separator to list of input
#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m)
#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__))
//--------------------------------------------------------------------+
// Supported OS
//--------------------------------------------------------------------+