diff options
| author | Mengsk <[email protected]> | 2024-08-27 12:13:29 +0200 |
|---|---|---|
| committer | Mengsk <[email protected]> | 2024-08-27 12:13:29 +0200 |
| commit | cefee1a743c9eb2134aef2c6e38261aad333aa9b (patch) | |
| tree | 208f9563f9686b4b427736e75e254cbc192939ef /src | |
| parent | 95cb319bded7db536edaae24936a825a8524a4a2 (diff) | |
| parent | 4485bffd139086d3adc40b1b176a59567a0254fc (diff) | |
Merge remote-tracking branch 'tinyusb/master' into vendor_fifo
Diffstat (limited to 'src')
24 files changed, 1938 insertions, 3536 deletions
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ed380424f..8c86de433 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg + * Copyright (c) 2023 HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,8 +66,10 @@ //--------------------------------------------------------------------+ // Use ring buffer if it's available, some MCUs need extra RAM requirements +// For DWC2 enable ring buffer will disable DMA (if available) #ifndef TUD_AUDIO_PREFER_RING_BUFFER - #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX + #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX || \ + defined(TUP_USBIP_DWC2) #define TUD_AUDIO_PREFER_RING_BUFFER 0 #else #define TUD_AUDIO_PREFER_RING_BUFFER 1 @@ -118,23 +121,23 @@ // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING @@ -144,38 +147,38 @@ // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING @@ -185,89 +188,89 @@ // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; #if CFG_TUD_AUDIO > 1 -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; #endif #if CFG_TUD_AUDIO > 2 -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +tu_static uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +tu_static uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +tu_static uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #endif @@ -300,19 +303,18 @@ typedef struct bool mounted; // Device opened - /*------------- From this point, data is not cleared by bus reset -------------*/ - uint16_t desc_length; // Length of audio function descriptor #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP struct { - CFG_TUSB_MEM_ALIGN uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). + CFG_TUSB_MEM_ALIGN uint32_t send_buf; + uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). uint32_t min_value; // min value according to UAC2 FMT-2.0 section 2.3.1.1. uint32_t max_value; // max value according to UAC2 FMT-2.0 section 2.3.1.1. uint8_t frame_shift; // bInterval-1 in unit of frame (FS), micro-frame (HS) uint8_t compute_method; - + bool format_correction; union { uint8_t power_of_2; // pre-computed power of 2 shift float float_const; // pre-computed float constant @@ -322,12 +324,12 @@ typedef struct uint32_t mclk_freq; }fixed; -#if 0 // implement later struct { - uint32_t nominal_value; - uint32_t threshold_bytes; + uint32_t nom_value; // In 16.16 format + uint32_t fifo_lvl_avg; // In 16.16 format + uint16_t fifo_lvl_thr; // fifo level threshold + uint16_t rate_const[2]; // pre-computed feedback/fifo_depth rate }fifo_count; -#endif }compute; } feedback; @@ -365,6 +367,8 @@ typedef struct #endif #endif + /*------------- From this point, data is not cleared by bus reset -------------*/ + // Buffer for control requests uint8_t * ctrl_buf; uint8_t ctrl_buf_sz; @@ -373,14 +377,10 @@ typedef struct uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t ep_out_ff; #endif - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t ep_in_ff; #endif @@ -390,7 +390,6 @@ typedef struct CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6]; #endif - // Support FIFOs for software encoding and decoding #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t * rx_supp_ff; @@ -434,9 +433,146 @@ typedef struct #define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) //--------------------------------------------------------------------+ +// WEAK FUNCTION STUBS +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_ENABLE_EP_IN +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { + (void) rhport; + (void) func_id; + (void) ep_in; + (void) cur_alt_setting; + return true; +} + +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_copied; + (void) func_id; + (void) ep_in; + (void) cur_alt_setting; + return true; +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_received; + (void) func_id; + (void) ep_out; + (void) cur_alt_setting; + return true; +} + +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_received; + (void) func_id; + (void) ep_out; + (void) cur_alt_setting; + return true; +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id) { + (void) func_id; +} + +TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param) { + (void) func_id; + (void) alt_itf; + feedback_param->method = AUDIO_FEEDBACK_METHOD_DISABLED; +} + +TU_ATTR_WEAK bool tud_audio_feedback_format_correction_cb(uint8_t func_id) { + (void) func_id; + return CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION; +} +#endif + +TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift) { + (void) func_id; + (void) frame_number; + (void) interval_shift; +} + +#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP +TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport) { + (void) rhport; +} +#endif + +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + return true; +} + +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + return true; +} + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall +} + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall +} + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall +} + +//--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; +tu_static CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); @@ -479,7 +615,8 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); +static bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); +static void audiod_fb_fifo_count_update(audiod_function_t* audio, uint16_t lvl_new); #endif bool tud_audio_n_mounted(uint8_t func_id) @@ -560,19 +697,13 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t uint8_t const *dummy2; uint8_t idx_audio_fct = 0; - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } + idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) - { - TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } + TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING switch (audio->format_type_rx) { @@ -621,13 +752,17 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if(audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) + { + audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->ep_out_ff)); + } +#endif + #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) - { - TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } + TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -731,6 +866,13 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it // TU_VERIFY(cnt != n_bytes); +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if(audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) + { + audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->rx_supp_ff[0])); + } +#endif + return true; } #endif //CFG_TUD_AUDIO_ENABLE_DECODING @@ -854,7 +996,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -917,7 +1059,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -1073,9 +1215,38 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) +static inline bool audiod_fb_send(audiod_function_t *audio) { - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->feedback.value, 4); + bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) && audio->feedback.format_correction; + // Format the feedback value + if (apply_correction) + { + uint8_t * fb = (uint8_t *) &audio->feedback.send_buf; + + // For FS format is 10.14 + *(fb++) = (audio->feedback.value >> 2) & 0xFF; + *(fb++) = (audio->feedback.value >> 10) & 0xFF; + *(fb++) = (audio->feedback.value >> 18) & 0xFF; + *fb = 0; + } else + { + audio->feedback.send_buf = audio->feedback.value; + } + + // About feedback format on FS + // + // 3 variables: Format | packetSize | sendSize | Working OS: + // 16.16 4 4 Linux, Windows + // 16.16 4 3 Linux + // 16.16 3 4 Linux + // 16.16 3 3 Linux + // 10.14 4 4 Linux + // 10.14 4 3 Linux + // 10.14 3 4 Linux, OSX + // 10.14 3 3 Linux, OSX + // + // We send 3 bytes since sending packet larger than wMaxPacketSize is pretty ugly + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, apply_correction ? 3 : 4); } #endif @@ -1693,7 +1864,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); audio->ep_in = 0; // Necessary? @@ -1724,7 +1895,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); audio->ep_out = 0; // Necessary? @@ -1842,9 +2013,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_fb = ep_addr; audio->feedback.frame_shift = desc_ep->bInterval -1; - - // Enable SOF interrupt if callback is implemented - if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, true); } #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1857,20 +2025,23 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(foundEPs == nEps); // Invoke one callback for a final set interface - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Prepare feedback computation if callback is available - if (tud_audio_feedback_params_cb) + // Prepare feedback computation if endpoint is available + if(audio->ep_fb != 0) { audio_feedback_params_t fb_param; tud_audio_feedback_params_cb(func_id, alt, &fb_param); audio->feedback.compute_method = fb_param.method; + if(TUSB_SPEED_FULL == tud_speed_get()) + audio->feedback.format_correction = tud_audio_feedback_format_correction_cb(func_id); + // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; - audio->feedback.min_value = (fb_param.sample_freq/frame_div - 1) << 16; + audio->feedback.min_value = ((fb_param.sample_freq - 1)/frame_div) << 16; audio->feedback.max_value = (fb_param.sample_freq/frame_div + 1) << 16; switch(fb_param.method) @@ -1878,20 +2049,32 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); + audiod_set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); break; - #if 0 // implement later case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { - uint64_t fb64 = ((uint64_t) fb_param.sample_freq) << 16; - audio->feedback.compute.fifo_count.nominal_value = (uint32_t) (fb64 / frame_div); - audio->feedback.compute.fifo_count.threshold_bytes = fb_param.fifo_count.threshold_bytes; - - tud_audio_fb_set(audio->feedback.compute.fifo_count.nominal_value); + // Initialize the threshold level to half filled + uint16_t fifo_lvl_thr; +#if CFG_TUD_AUDIO_ENABLE_DECODING + fifo_lvl_thr = tu_fifo_depth(&audio->rx_supp_ff[0]) / 2; +#else + fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2; +#endif + audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr; + audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t)fifo_lvl_thr) << 16; + // Avoid 64bit division + uint32_t nominal = ((fb_param.sample_freq / 100) << 16) / (frame_div / 100); + audio->feedback.compute.fifo_count.nom_value = nominal; + audio->feedback.compute.fifo_count.rate_const[0] = (audio->feedback.max_value - nominal) / fifo_lvl_thr; + audio->feedback.compute.fifo_count.rate_const[1] = (nominal - audio->feedback.min_value) / fifo_lvl_thr; + // On HS feedback is more sensitive since packet size can vary every MSOF, could cause instability + if(tud_speed_get() == TUSB_SPEED_HIGH) { + audio->feedback.compute.fifo_count.rate_const[0] /= 8; + audio->feedback.compute.fifo_count.rate_const[1] /= 8; + } } break; - #endif // nothing to do default: break; @@ -1909,16 +2092,19 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Disable SOF interrupt if no driver has any enabled feedback EP - bool disable = true; + bool enable_sof = false; for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_fct[i].ep_fb != 0) + if (_audiod_fct[i].ep_fb != 0 && + (_audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED || + _audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT || + _audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 )) { - disable = false; + enable_sof = true; break; } } - if (disable) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, false); + usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, enable_sof); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL @@ -1948,35 +2134,19 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } } break; @@ -1985,19 +2155,11 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const { uint8_t ep = TU_U16_LOW(p_request->wIndex); - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } break; // Unknown/Unsupported recipient @@ -2054,15 +2216,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_entity_cb(rhport, p_request); } } else @@ -2073,15 +2227,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_itf_cb(rhport, p_request); } } } @@ -2097,15 +2243,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_ep_cb(rhport, p_request); } } break; @@ -2160,7 +2298,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // I assume here, that things above are handled by PHY // All transmission is done - what remains to do is to inform job was completed - if (tud_audio_int_done_cb) tud_audio_int_done_cb(rhport); + tud_audio_int_done_cb(rhport); return true; } @@ -2201,13 +2339,13 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Transmission of feedback EP finished if (audio->ep_fb == ep_addr) { - if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id); + tud_audio_fb_done_cb(func_id); // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, audio->ep_fb)) + if (usbd_edpt_claim(rhport, audio->ep_fb)) { // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, audio); + return audiod_fb_send(audio); } } #endif @@ -2219,7 +2357,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) +static bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) { // Check if frame interval is within sane limits // The interval value n_frames was taken from the descriptors within audiod_set_interface() @@ -2238,11 +2376,11 @@ static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, u if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq)) { audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; - audio->feedback.compute.power_of_2 = 16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq); + audio->feedback.compute.power_of_2 = 16 - (audio->feedback.frame_shift - 1) - tu_log2(mclk_freq / sample_freq); } else if ( audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) { - audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - audio->feedback.frame_shift)); + audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - (audio->feedback.frame_shift - 1))); } else { @@ -2253,6 +2391,38 @@ static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, u return true; } +static void audiod_fb_fifo_count_update(audiod_function_t* audio, uint16_t lvl_new) +{ + /* Low-pass (averaging) filter */ + uint32_t lvl = audio->feedback.compute.fifo_count.fifo_lvl_avg; + lvl = (uint32_t)(((uint64_t)lvl * 63 + ((uint32_t)lvl_new << 16)) >> 6); + audio->feedback.compute.fifo_count.fifo_lvl_avg = lvl; + + uint32_t const ff_lvl = lvl >> 16; + uint16_t const ff_thr = audio->feedback.compute.fifo_count.fifo_lvl_thr; + uint16_t const *rate = audio->feedback.compute.fifo_count.rate_const; + + uint32_t feedback; + + if(ff_lvl < ff_thr) + { + feedback = audio->feedback.compute.fifo_count.nom_value + (ff_thr - ff_lvl) * rate[0]; + } else + { + feedback = audio->feedback.compute.fifo_count.nom_value - (ff_lvl - ff_thr) * rate[1]; + } + + if ( feedback > audio->feedback.max_value ) feedback = audio->feedback.max_value; + if ( feedback < audio->feedback.min_value ) feedback = audio->feedback.min_value; + audio->feedback.value = feedback; + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (usbd_edpt_claim(audio->rhport, audio->ep_fb)) + { + audiod_fb_send(audio); + } +} + uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { audiod_function_t* audio = &_audiod_fct[func_id]; @@ -2270,7 +2440,7 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: { - uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - audio->feedback.frame_shift); + uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - (audio->feedback.frame_shift - 1)); feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); } break; @@ -2289,6 +2459,21 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) return feedback; } + +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + _audiod_fct[func_id].feedback.value = feedback; + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) + { + return audiod_fb_send(&_audiod_fct[func_id]); + } + + return true; +} #endif TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) @@ -2315,7 +2500,7 @@ TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) uint32_t const interval = 1UL << (audio->feedback.frame_shift - hs_adjust); if ( 0 == (frame_count & (interval-1)) ) { - if(tud_audio_feedback_interval_isr) tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); + tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); } } } @@ -2703,44 +2888,8 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da #endif -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].feedback.value; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].feedback.value = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - // No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) +static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) { for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b16514fd4..ae253f49d 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -3,6 +3,7 @@ * * Copyright (c) 2020 Ha Thach (tinyusb.org) * Copyright (c) 2020 Reinhard Panhuber + * Copyright (c) 2023 HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -192,6 +193,7 @@ #endif // Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). +// Can be override by tud_audio_feedback_format_correction_cb() #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 #endif @@ -242,7 +244,8 @@ // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size // The actual coding parameters of active AS alternate interface is parsed from the descriptors -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! +// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple +// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)! // This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! // For PCM encoding/decoding @@ -446,63 +449,80 @@ static inline bool tud_audio_int_write (const audio_interru bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); //--------------------------------------------------------------------+ -// Application Callback API (weak is optional) +// Application Callback API //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id); +void tud_audio_fb_done_cb(uint8_t func_id); -// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced. - -// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). +// Note about feedback calculation +// +// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT +// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill. +// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested +// (Windows, Linux, OSX) with a reliable result so far. +// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced. +// +// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT +// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from +// which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter). +// See tud_audio_set_fb_params() and tud_audio_feedback_update() +// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible. +// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point is the reading of the cycle counter value of f_m. +// It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). +// Long-term drift could occur since error is accumulated. +// +// Option 3 - manual +// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. +// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load. +// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced. -// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set(). // This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. // // The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. +// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb() +// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS. +// +// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the +// driver can work with either format. // -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. - // Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value. - +// // Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec // Boiled down, the feedback value Ff = n_samples / (micro)frame. -// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) +// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 +// for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) // The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) // feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); -// Update feedback value with passed cycles since last time this update function is called. +// Update feedback value with passed MCLK cycles since last time this update function is called. // Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented // This function will also call tud_audio_feedback_set() // return feedback value in 16.16 for reference (0 for error) +// Example : +// binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz +// In 4 SOF MCLK counted 49152 cycles uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles); enum { AUDIO_FEEDBACK_METHOD_DISABLED, AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED, AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT, - AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, - - // impelemnt later - // AUDIO_FEEDBACK_METHOD_FIFO_COUNT + AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only + AUDIO_FEEDBACK_METHOD_FIFO_COUNT }; typedef struct { @@ -514,52 +534,50 @@ typedef struct { uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on }frequency; -#if 0 // implement later - struct { - uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready - }fifo_count; -#endif }; }audio_feedback_params_t; // Invoked when needed to set feedback parameters -TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); +void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); // Callback in ISR context, invoked periodically according to feedback endpoint bInterval. // Could be used to compute and update feedback value, should be placed in RAM if possible // frame_number : current SOF count // interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor -TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); +TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); +// (Full-Speed only) Callback to set feedback format correction is applied or not, +// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented. +bool tud_audio_feedback_format_correction_cb(uint8_t func_id); #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP -TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport); +void tud_audio_int_done_cb(uint8_t rhport); #endif // Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); //--------------------------------------------------------------------+ // Inline Functions diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 00f6fc474..ef6c7f3af 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -134,7 +134,7 @@ uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].protocol_mode; } -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) { hid_keyboard_report_t report; report.modifier = modifier; report.reserved = 0; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 89c28e061..ab2e27373 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -65,7 +65,7 @@ bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, u // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t @@ -98,7 +98,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_report(uint8_t report_id, void return tud_hid_n_report(0, report_id, report, len); } -TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) { return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); } diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 637281bfc..52debf079 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -138,21 +138,21 @@ #elif TU_CHECK_MCU(OPT_MCU_SAMG) #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_SAMX7X) #define TUP_DCD_ENDPOINT_MAX 10 #define TUP_RHPORT_HIGHSPEED 1 - #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || \ TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // ST @@ -299,7 +299,7 @@ #elif TU_CHECK_MCU(OPT_MCU_CXD56) #define TUP_DCD_ENDPOINT_MAX 7 #define TUP_RHPORT_HIGHSPEED 1 - #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // TI @@ -308,6 +308,8 @@ #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #define TUP_USBIP_MUSB + #define TUP_USBIP_MUSB_TI #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ @@ -336,8 +338,11 @@ #define TUP_USBIP_DWC2 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) +#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) + #if (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + #endif + #define TUP_DCD_ENDPOINT_MAX 0 //--------------------------------------------------------------------+ // Dialog @@ -395,10 +400,12 @@ #elif TU_CHECK_MCU(OPT_MCU_FT90X) #define TUP_DCD_ENDPOINT_MAX 8 #define TUP_RHPORT_HIGHSPEED 1 + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_FT93X) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_RHPORT_HIGHSPEED 1 + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // Allwinner @@ -465,6 +472,16 @@ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) +//--------------------------------------------------------------------+ +// Analog Devices +//--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) + #define TUP_USBIP_MUSB + #define TUP_USBIP_MUSB_ADI + #define TUP_DCD_ENDPOINT_MAX 12 + #define TUP_RHPORT_HIGHSPEED 1 + #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + #endif //--------------------------------------------------------------------+ @@ -501,7 +518,8 @@ #define TU_ATTR_FAST_FUNC #endif -#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) +// USBIP that support ISO alloc & activate API +#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) || defined(TUP_USBIP_MUSB) #define TUP_DCD_EDPT_ISO_ALLOC #endif diff --git a/src/device/dcd.h b/src/device/dcd.h index 41e0fbee3..3ef5188fc 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -157,10 +157,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc // required for multiple configuration support. void dcd_edpt_close_all (uint8_t rhport); -// Close an endpoint. -// Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; - // 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); @@ -175,12 +171,19 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // This API never calls with control endpoints, since it is auto cleared when receiving setup packet void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); +#ifdef TUP_DCD_EDPT_ISO_ALLOC // Allocate packet buffer used by ISO endpoints // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering -TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); // Configure and enable an ISO endpoint according to descriptor -TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +#else +// Close an endpoint. +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr); + +#endif //--------------------------------------------------------------------+ // Event API (implemented by stack) diff --git a/src/device/usbd.c b/src/device/usbd.c index 6d27a3735..67faf0da7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1201,7 +1201,6 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - // TU_ASSERT(event->setup_received.bRequest != 0,); // for catching issue with ch32v203 and windows with -O0/-Og _usbd_queued_setup++; send = true; break; @@ -1419,9 +1418,12 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) { * In progress transfers on this EP may be delivered after this call. */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { +#ifdef TUP_DCD_EDPT_ISO_ALLOC + (void) rhport; (void) ep_addr; + // ISO alloc/activate Should be used instead +#else rhport = _usbd_rhport; - TU_ASSERT(dcd_edpt_close, /**/); TU_LOG_USBD(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1431,6 +1433,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { _usbd_dev.ep_status[epnum][dir].stalled = 0; _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; +#endif return; } @@ -1453,21 +1456,24 @@ void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en) { } bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { +#ifdef TUP_DCD_EDPT_ISO_ALLOC rhport = _usbd_rhport; - TU_ASSERT(dcd_edpt_iso_alloc); TU_ASSERT(tu_edpt_number(ep_addr) < CFG_TUD_ENDPPOINT_MAX); - return dcd_edpt_iso_alloc(rhport, ep_addr, largest_packet_size); +#else + (void) rhport; (void) ep_addr; (void) largest_packet_size; + return false; +#endif } bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { +#ifdef TUP_DCD_EDPT_ISO_ALLOC rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(desc_ep->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); - TU_ASSERT(dcd_edpt_iso_activate); TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); @@ -1475,6 +1481,10 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; return dcd_edpt_iso_activate(rhport, desc_ep); +#else + (void) rhport; (void) desc_ep; + return false; +#endif } #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 3d3e83f41..7913096e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -434,8 +434,8 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _epsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(_epsize), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source @@ -553,7 +553,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) -#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ +#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -567,7 +567,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* Output Terminal Descriptor(4.7.2.5) */\ TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ @@ -579,11 +579,11 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ 1) // Calculate wMaxPacketSize of Endpoints #define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index a817c5d6e..a40b3dc07 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2021 Koji KITAYAMA + * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +27,10 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && \ - TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) +#if CFG_TUD_ENABLED && defined(TUP_USBIP_MUSB) + +#define MUSB_DEBUG 2 +#define MUSB_REGS(rhport) ((musb_regs_t*) MUSB_BASES[rhport]) #if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) /* GCC warns that an address may be unaligned, even though @@ -35,48 +38,30 @@ _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); #endif +#include "musb_type.h" #include "device/dcd.h" -#if TU_CHECK_MCU(OPT_MCU_MSP432E4) - #include "musb_msp432e.h" - -#elif TU_CHECK_MCU(OPT_MCU_TM4C123, OPT_MCU_TM4C129) - #include "musb_tm4c.h" - - // HACK generalize later - #include "musb_type.h" - #define FIFO0_WORD FIFO0 - #define FIFO1_WORD FIFO1 - +// Following symbols must be defined by port header +// - musb_dcd_int_enable/disable/clear/get_enable +// - musb_dcd_int_handler_enter/exit +#if defined(TUP_USBIP_MUSB_TI) + #include "musb_ti.h" +#elif defined(TUP_USBIP_MUSB_ADI) + #include "musb_max32.h" #else - #error "Unsupported MCUs" + #error "Unsupported MCU" #endif /*------------------------------------------------------------------ * MACRO TYPEDEF CONSTANT ENUM DECLARATION *------------------------------------------------------------------*/ -#define REQUEST_TYPE_INVALID (0xFFu) -typedef struct { - uint_fast16_t beg; /* offset of including first element */ - uint_fast16_t end; /* offset of excluding the last element */ -} free_block_t; - -typedef struct TU_ATTR_PACKED { - uint16_t TXMAXP; - uint8_t TXCSRL; - uint8_t TXCSRH; - uint16_t RXMAXP; - uint8_t RXCSRL; - uint8_t RXCSRH; - uint16_t RXCOUNT; - uint16_t RESERVED[3]; -} hw_endpoint_t; +#define REQUEST_TYPE_INVALID (0xFFu) typedef union { - uint8_t u8; - uint16_t u16; - uint32_t u32; + volatile uint8_t u8; + volatile uint16_t u16; + volatile uint32_t u32; } hw_fifo_t; typedef struct TU_ATTR_PACKED @@ -92,134 +77,97 @@ typedef struct uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ int8_t status_out; pipe_state_t pipe0; - pipe_state_t pipe[2][7]; /* pipe[direction][endpoint number - 1] */ + pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]; /* pipe[direction][endpoint number - 1] */ uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */ } dcd_data_t; -/*------------------------------------------------------------------ - * INTERNAL OBJECT & FUNCTION DECLARATION - *------------------------------------------------------------------*/ static dcd_data_t _dcd; +//-------------------------------------------------------------------- +// HW FIFO Helper +// Note: Index register is already set by caller +//-------------------------------------------------------------------- -static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) -{ - free_block_t *cur = beg; - for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ; - return cur; -} +#if MUSB_CFG_DYNAMIC_FIFO -static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) -{ - free_block_t *p = find_containing_block(blks, blks + num, addr); - TU_ASSERT(p != blks + num, -2); - if (p->beg == addr) { - /* Shrink block */ - p->beg = addr + size; - if (p->beg != p->end) return 0; - /* remove block */ - free_block_t *end = blks + num; - while (p + 1 < end) { - *p = *(p + 1); - ++p; - } - return -1; - } else { - /* Split into 2 blocks */ - free_block_t tmp = { - .beg = addr + size, - .end = p->end - }; - p->end = addr; - if (p->beg == p->end) { - if (tmp.beg != tmp.end) { - *p = tmp; - return 0; - } - /* remove block */ - free_block_t *end = blks + num; - while (p + 1 < end) { - *p = *(p + 1); - ++p; - } - return -1; - } - if (tmp.beg == tmp.end) return 0; - blks[num] = tmp; - return 1; +// musb is configured to use dynamic FIFO sizing. +// FF Size is encodded: 1 << (fifo_size[3:0] + 3) = 8 << fifo_size[3:0] +// FF Address is 8*ff_addr[12:0] +// First 64 bytes are reserved for EP0 +static uint32_t alloced_fifo_bytes; + +// ffsize is log2(mps) - 3 (round up) +TU_ATTR_ALWAYS_INLINE static inline uint8_t hwfifo_byte2size(uint16_t nbytes) { + uint8_t ffsize = 28 - tu_min8(28, __builtin_clz(nbytes)); + if ((8u << ffsize) < nbytes) { + ++ffsize; } + return ffsize; } -static inline unsigned free_block_size(free_block_t const *blk) -{ - return blk->end - blk->beg; +TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned is_rx) { + (void) epnum; + musb->fifo_size[is_rx] = 0; + musb->fifo_addr[is_rx] = 0; } -#if 0 -static inline void print_block_list(free_block_t const *blk, unsigned num) -{ - TU_LOG1("*************\r\n"); - for (unsigned i = 0; i < num; ++i) { - TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end); - ++blk; +TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, + bool double_packet) { + (void) epnum; + uint8_t ffsize = hwfifo_byte2size(mps); + mps = 8 << ffsize; // round up to the next power of 2 + + if (double_packet) { + ffsize |= MUSB_FIFOSZ_DOUBLE_PACKET; + mps <<= 1; } + + TU_ASSERT(alloced_fifo_bytes + mps <= MUSB_CFG_DYNAMIC_FIFO_SIZE); + musb->fifo_addr[is_rx] = alloced_fifo_bytes / 8; + musb->fifo_size[is_rx] = ffsize; + + alloced_fifo_bytes += mps; + return true; } + #else -#define print_block_list(a,b) -#endif -static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) -{ - free_block_t free_blocks[2 * (TUP_DCD_ENDPOINT_MAX - 1)]; - unsigned num_blocks = 1; +TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned is_rx) { + (void) musb; (void) epnum; (void) is_rx; + // nothing to do for static FIFO +} - /* Initialize free memory block list */ - free_blocks[0].beg = 64 / 8; - free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ - for (int i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) { - uint_fast16_t addr; - int num; - USB0->EPIDX = i; - addr = USB0->TXFIFOADD; - if (addr) { - unsigned sz = USB0->TXFIFOSZ; - unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0); - num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); - TU_ASSERT(-2 < num, 0); - num_blocks += num; - print_block_list(free_blocks, num_blocks); - } - addr = USB0->RXFIFOADD; - if (addr) { - unsigned sz = USB0->RXFIFOSZ; - unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0); - num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); - TU_ASSERT(-2 < num, 0); - num_blocks += num; - print_block_list(free_blocks, num_blocks); +TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps, + bool double_packet) { + (void) epnum; (void) mps; + if (!double_packet) { + #if defined(TUP_USBIP_MUSB_ADI) + musb->indexed_csr.maxp_csr[is_rx].csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx); + #else + if (is_rx) { + musb->rx_doulbe_packet_disable |= 1u << epnum; + } else { + musb->tx_double_packet_disable |= 1u << epnum; } + #endif } - print_block_list(free_blocks, num_blocks); - /* Find the best fit memory block */ - uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; - free_block_t const *min = NULL; - uint_fast16_t min_sz = 0xFFFFu; - free_block_t const *end = &free_blocks[num_blocks]; - for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) { - uint_fast16_t sz = free_block_size(cur); - if (sz < size_in_8byte_unit) continue; - if (size_in_8byte_unit == sz) return cur->beg; - if (sz < min_sz) min = cur; - } - TU_ASSERT(min, 0); - return min->beg; + return true; } -static inline volatile hw_endpoint_t* edpt_regs(unsigned epnum_minus1) -{ - volatile hw_endpoint_t *regs = (volatile hw_endpoint_t*)((uintptr_t)&USB0->TXMAXP1); - return regs + epnum_minus1; +#endif + +// Flush FIFO and clear data toggle +TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigned epnum, unsigned is_rx, bool clear_dtog) { + (void) epnum; + const uint8_t csrl_dtog = clear_dtog ? MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx) : 0; + musb_ep_maxp_csr_t* maxp_csr = &musb->indexed_csr.maxp_csr[is_rx]; + // may need to flush twice for double packet + for (unsigned i=0; i<2; i++) { + if (maxp_csr->csrl & MUSB_CSRL_PACKET_READY(is_rx)) { + maxp_csr->csrl = MUSB_CSRL_FLUSH_FIFO(is_rx) | csrl_dtog; + } + } } static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) @@ -284,11 +232,14 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne ops[dir].tu_fifo_advance(f, total_len - rem); } -static void process_setup_packet(uint8_t rhport) -{ +static void process_setup_packet(uint8_t rhport) { + musb_regs_t* musb_regs = MUSB_REGS(rhport); + + // Read setup packet uint32_t *p = (void*)&_dcd.setup_packet; - p[0] = USB0->FIFO0_WORD; - p[1] = USB0->FIFO0_WORD; + volatile uint32_t *fifo_ptr = &musb_regs->fifo[0]; + p[0] = *fifo_ptr; + p[1] = *fifo_ptr; _dcd.pipe0.buf = NULL; _dcd.pipe0.length = 0; @@ -299,12 +250,16 @@ static void process_setup_packet(uint8_t rhport) _dcd.remaining_ctrl = len; const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType); /* Clear RX FIFO and reverse the transaction direction */ - if (len && dir_in) USB0->CSRL0 = USB_CSRL0_RXRDYC; + if (len && dir_in) { + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; + } } -static bool handle_xfer_in(uint_fast8_t ep_addr) +static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) { - unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + unsigned epnum = tu_edpt_number(ep_addr); + unsigned epnum_minus1 = epnum - 1; pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; const unsigned rem = pipe->remaining; @@ -313,44 +268,49 @@ static bool handle_xfer_in(uint_fast8_t ep_addr) return true; } - volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); - const unsigned mps = regs->TXMAXP; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); + const unsigned mps = ep_csr->tx_maxp; const unsigned len = TU_MIN(mps, rem); void *buf = pipe->buf; + volatile void *fifo_ptr = &musb_regs->fifo[epnum]; // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem); if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_IN); + pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN); } else { - pipe_write_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len); + pipe_write_packet(buf, fifo_ptr, len); pipe->buf = buf + len; } pipe->remaining = rem - len; } - regs->TXCSRL = USB_TXCSRL1_TXRDY; - // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum_minus1 + 1, regs->TXCSRL, rem - len); + ep_csr->tx_csrl = MUSB_TXCSRL1_TXRDY; + // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum, ep_csr->tx_csrl, rem - len); return false; } -static bool handle_xfer_out(uint_fast8_t ep_addr) +static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) { - unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + unsigned epnum = tu_edpt_number(ep_addr); + unsigned epnum_minus1 = epnum - 1; pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; - volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); - // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, regs->RXCSRL); + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); + // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, ep_csr->rx_csrl); - TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY); + TU_ASSERT(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY); - const unsigned mps = regs->RXMAXP; + const unsigned mps = ep_csr->rx_maxp; const unsigned rem = pipe->remaining; - const unsigned vld = regs->RXCOUNT; + const unsigned vld = ep_csr->rx_count; const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; + volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_OUT); + pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT); } else { - pipe_read_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len); + pipe_read_packet(buf, fifo_ptr, len); pipe->buf = buf + len; } pipe->remaining = rem - len; @@ -359,15 +319,14 @@ static bool handle_xfer_out(uint_fast8_t ep_addr) pipe->buf = NULL; return NULL != buf; } - regs->RXCSRL = 0; /* Clear RXRDY bit */ + ep_csr->rx_csrl = 0; /* Clear RXRDY bit */ return false; } static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - (void)rhport; - - unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + unsigned epnum = tu_edpt_number(ep_addr); + unsigned epnum_minus1 = epnum - 1; unsigned dir_in = tu_edpt_dir(ep_addr); pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1]; @@ -376,10 +335,11 @@ static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16 pipe->remaining = total_bytes; if (dir_in) { - handle_xfer_in(ep_addr); + handle_xfer_in(rhport, ep_addr); } else { - volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); - if (regs->RXCSRL & USB_RXCSRL1_RXRDY) regs->RXCSRL = 0; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum); + if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) ep_csr->rx_csrl = 0; } return true; } @@ -388,7 +348,8 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ { (void)rhport; TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ - + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); const unsigned req = _dcd.setup_packet.bmRequestType; TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0); @@ -399,7 +360,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ * may have already finished and received the next setup packet * without calling this function, so we have no choice but to * invoke the callback function of status packet here. */ - // TU_LOG1(" STATUS OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0); + // TU_LOG1(" STATUS OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l); _dcd.status_out = 0; if (req == REQUEST_TYPE_INVALID) { dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false); @@ -415,8 +376,9 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ TU_ASSERT(total_bytes <= _dcd.remaining_ctrl); const unsigned rem = _dcd.remaining_ctrl; const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); + volatile void *fifo_ptr = &musb_regs->fifo[0]; if (dir_in) { - pipe_write_packet(buffer, &USB0->FIFO0_WORD, len); + pipe_write_packet(buffer, fifo_ptr, len); _dcd.pipe0.buf = buffer + len; _dcd.pipe0.length = len; @@ -427,45 +389,48 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */ _dcd.status_out = 1; /* Flush TX FIFO and reverse the transaction direction. */ - USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_DATAEND; + ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND; } else { - USB0->CSRL0 = USB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */ + ep_csr->csr0l = MUSB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */ } - // TU_LOG1(" IN USB0->CSRL0 = %x\r\n", USB0->CSRL0); + // TU_LOG1(" IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l); } else { - // TU_LOG1(" OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0); + // TU_LOG1(" OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l); _dcd.pipe0.buf = buffer; _dcd.pipe0.length = len; _dcd.pipe0.remaining = len; - USB0->CSRL0 = USB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */ + ep_csr->csr0l = MUSB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */ } } else if (dir_in) { - // TU_LOG1(" STATUS IN USB0->CSRL0 = %x\r\n", USB0->CSRL0); + // TU_LOG1(" STATUS IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l); _dcd.pipe0.buf = NULL; _dcd.pipe0.length = 0; _dcd.pipe0.remaining = 0; /* Clear RX FIFO and reverse the transaction direction */ - USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } return true; } static void process_ep0(uint8_t rhport) { - uint_fast8_t csrl = USB0->CSRL0; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + uint_fast8_t csrl = ep_csr->csr0l; - // TU_LOG1(" EP0 USB0->CSRL0 = %x\r\n", csrl); + // TU_LOG1(" EP0 ep_csr->csr0l = %x\r\n", csrl); + // 21.1.5: endpoint 0 service routine as peripheral - if (csrl & USB_CSRL0_STALLED) { + if (csrl & MUSB_CSRL0_STALLED) { /* Returned STALL packet to HOST. */ - USB0->CSRL0 = 0; /* Clear STALL */ + ep_csr->csr0l = 0; /* Clear STALL */ return; } unsigned req = _dcd.setup_packet.bmRequestType; - if (csrl & USB_CSRL0_SETEND) { + if (csrl & MUSB_CSRL0_SETEND) { TU_LOG1(" ABORT by the next packets\r\n"); - USB0->CSRL0 = USB_CSRL0_SETENDC; + ep_csr->csr0l = MUSB_CSRL0_SETENDC; if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) { /* DATA stage was aborted by receiving STATUS or SETUP packet. */ _dcd.pipe0.buf = NULL; @@ -476,23 +441,24 @@ static void process_ep0(uint8_t rhport) XFER_RESULT_SUCCESS, true); } req = REQUEST_TYPE_INVALID; - if (!(csrl & USB_CSRL0_RXRDY)) return; /* Received SETUP packet */ + if (!(csrl & MUSB_CSRL0_RXRDY)) return; /* Received SETUP packet */ } - if (csrl & USB_CSRL0_RXRDY) { + if (csrl & MUSB_CSRL0_RXRDY) { /* Received SETUP or DATA OUT packet */ if (req == REQUEST_TYPE_INVALID) { /* SETUP */ - TU_ASSERT(sizeof(tusb_control_request_t) == USB0->COUNT0,); + TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0,); process_setup_packet(rhport); return; } if (_dcd.pipe0.buf) { /* DATA OUT */ - const unsigned vld = USB0->COUNT0; + const unsigned vld = ep_csr->count0; const unsigned rem = _dcd.pipe0.remaining; const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); - pipe_read_packet(_dcd.pipe0.buf, &USB0->FIFO0_WORD, len); + volatile void *fifo_ptr = &musb_regs->fifo[0]; + pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len); _dcd.pipe0.remaining = rem - len; _dcd.remaining_ctrl -= len; @@ -512,7 +478,7 @@ static void process_ep0(uint8_t rhport) /* STATUS IN */ if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) { /* The address must be changed on completion of the control transfer. */ - USB0->FADDR = (uint8_t)_dcd.setup_packet.wValue; + musb_regs->faddr = (uint8_t)_dcd.setup_packet.wValue; } _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; dcd_event_xfer_complete(rhport, @@ -534,118 +500,147 @@ static void process_ep0(uint8_t rhport) static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) { bool completed; - const unsigned dir_in = tu_edpt_dir(ep_addr); - const unsigned epn_minus1 = tu_edpt_number(ep_addr) - 1; + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned epn_minus1 = epn - 1; - volatile hw_endpoint_t *regs = edpt_regs(epn_minus1); + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); if (dir_in) { - // TU_LOG1(" TXCSRL%d = %x\r\n", epn_minus1 + 1, regs->TXCSRL); - if (regs->TXCSRL & USB_TXCSRL1_STALLED) { - regs->TXCSRL &= ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_UNDRN); + // TU_LOG1(" TX CSRL%d = %x\r\n", epn, ep_csr->tx_csrl); + if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) { + ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN); return; } - completed = handle_xfer_in(ep_addr); + completed = handle_xfer_in(rhport, ep_addr); } else { - // TU_LOG1(" RXCSRL%d = %x\r\n", epn_minus1 + 1, regs->RXCSRL); - if (regs->RXCSRL & USB_RXCSRL1_STALLED) { - regs->RXCSRL &= ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_OVER); + // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl); + if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) { + ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER); return; } - completed = handle_xfer_out(ep_addr); + completed = handle_xfer_out(rhport, ep_addr); } if (completed) { - pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1]; + pipe_state_t *pipe = &_dcd.pipe[dir_in][epn_minus1]; dcd_event_xfer_complete(rhport, ep_addr, pipe->length - pipe->remaining, XFER_RESULT_SUCCESS, true); } } -static void process_bus_reset(uint8_t rhport) -{ - /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), - * a control transfer state is SETUP or STATUS stage. */ +// Upon BUS RESET is detected, hardware havs already done: +// faddr = 0, index = 0, flushes all ep fifos, clears all ep csr, enabled all ep interrupts +static void process_bus_reset(uint8_t rhport) { + musb_regs_t* musb = MUSB_REGS(rhport); + +#if MUSB_CFG_DYNAMIC_FIFO + alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE; +#endif + + /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), a control transfer state is SETUP or STATUS stage. */ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; _dcd.status_out = 0; /* When pipe0.buf has not NULL, DATA stage works in progress. */ _dcd.pipe0.buf = NULL; - USB0->TXIE = 1; /* Enable only EP0 */ - USB0->RXIE = 0; + musb->intr_txen = 1; /* Enable only EP0 */ + musb->intr_rxen = 0; /* Clear FIFO settings */ for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) { - USB0->EPIDX = i; - USB0->TXFIFOSZ = 0; - USB0->TXFIFOADD = 0; - USB0->RXFIFOSZ = 0; - USB0->RXFIFOADD = 0; + musb->index = i; + hwfifo_reset(musb, i, 0); + hwfifo_reset(musb, i, 1); } - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + dcd_event_bus_reset(rhport, (musb->power & MUSB_POWER_HSMODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true); } /*------------------------------------------------------------------ * Device API *------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - (void)rhport; - USB0->IE |= USB_IE_SUSPND; - NVIC_ClearPendingIRQ(USB0_IRQn); +#if CFG_TUSB_DEBUG >= MUSB_DEBUG +void print_musb_info(musb_regs_t* musb_regs) { + // print version, epinfo, raminfo, config_data0, fifo_size + TU_LOG1("musb version = %u.%u\r\n", musb_regs->hwvers_bit.major, musb_regs->hwvers_bit.minor); + TU_LOG1("Number of endpoints: %u TX, %u RX\r\n", musb_regs->epinfo_bit.tx_ep_num, musb_regs->epinfo_bit.rx_ep_num); + TU_LOG1("RAM Info: %u DMA Channel, %u RAM address width\r\n", musb_regs->raminfo_bit.dma_channel, musb_regs->raminfo_bit.ram_bits); + + musb_regs->index = 0; + TU_LOG1("config_data0 = 0x%x\r\n", musb_regs->indexed_csr.config_data0); +#if MUSB_CFG_DYNAMIC_FIFO + TU_LOG1("Dynamic FIFO configuration\r\n"); +#else + for (uint8_t i=1; i <= musb_regs->epinfo_bit.tx_ep_num; i++) { + musb_regs->index = i; + TU_LOG1("FIFO %u Size: TX %u RX %u\r\n", i, musb_regs->indexed_csr.fifo_size_bit.tx, musb_regs->indexed_csr.fifo_size_bit.rx); + } +#endif +} +#endif + +void dcd_init(uint8_t rhport) { + musb_regs_t* musb_regs = MUSB_REGS(rhport); + +#if CFG_TUSB_DEBUG >= MUSB_DEBUG + print_musb_info(musb_regs); +#endif + + musb_regs->intr_usben |= MUSB_IE_SUSPND; + musb_dcd_int_clear(rhport); + musb_dcd_phy_init(rhport); dcd_connect(rhport); } -void dcd_int_enable(uint8_t rhport) -{ - (void)rhport; - NVIC_EnableIRQ(USB0_IRQn); +void dcd_int_enable(uint8_t rhport) { + musb_dcd_int_enable(rhport); } -void dcd_int_disable(uint8_t rhport) -{ - (void)rhport; - NVIC_DisableIRQ(USB0_IRQn); +void dcd_int_disable(uint8_t rhport) { + musb_dcd_int_disable(rhport); } // 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; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); + _dcd.pipe0.buf = NULL; _dcd.pipe0.length = 0; _dcd.pipe0.remaining = 0; /* Clear RX FIFO to return ACK. */ - USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND; + ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND; } // Wake up host -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - USB0->POWER |= USB_POWER_RESUME; +void dcd_remote_wakeup(uint8_t rhport) { + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_regs->power |= MUSB_POWER_RESUME; unsigned cnt = SystemCoreClock / 1000; while (cnt--) __NOP(); - USB0->POWER &= ~USB_POWER_RESUME; + musb_regs->power &= ~MUSB_POWER_RESUME; } // Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { - (void)rhport; - USB0->POWER |= USB_POWER_SOFTCONN; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_regs->power |= TUD_OPT_HIGH_SPEED ? MUSB_POWER_HSENAB : 0; + musb_regs->power |= MUSB_POWER_SOFTCONN; } // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) { - (void)rhport; - USB0->POWER &= ~USB_POWER_SOFTCONN; + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_regs->power &= ~MUSB_POWER_SOFTCONN; } void dcd_sof_enable(uint8_t rhport, bool en) @@ -659,129 +654,119 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ +// static void edpt_setup(musb_regs_t* musb, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_size){ +// const unsigned epn = tu_edpt_number(ep_addr); +// const unsigned dir_in = tu_edpt_dir(ep_addr); +// } // Configure endpoint's registers according to descriptor -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { const unsigned ep_addr = ep_desc->bEndpointAddress; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir_in = tu_edpt_dir(ep_addr); - const unsigned xfer = ep_desc->bmAttributes.xfer; const unsigned mps = tu_edpt_packet_size(ep_desc); - TU_ASSERT(epn < TUP_DCD_ENDPOINT_MAX); - pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; pipe->buf = NULL; pipe->length = 0; pipe->remaining = 0; - volatile hw_endpoint_t *regs = edpt_regs(epn - 1); + musb_regs_t* musb = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); + const uint8_t is_rx = 1 - dir_in; + musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx]; + + maxp_csr->maxp = mps; + maxp_csr->csrh = 0; +#if MUSB_CFG_SHARED_FIFO if (dir_in) { - regs->TXMAXP = mps; - regs->TXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_TXCSRH1_ISO : 0; - if (regs->TXCSRL & USB_TXCSRL1_TXRDY) - regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; - else - regs->TXCSRL = USB_TXCSRL1_CLRDT; - USB0->TXIE |= TU_BIT(epn); - } else { - regs->RXMAXP = mps; - regs->RXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_RXCSRH1_ISO : 0; - if (regs->RXCSRL & USB_RXCSRL1_RXRDY) - regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; - else - regs->RXCSRL = USB_RXCSRL1_CLRDT; - USB0->RXIE |= TU_BIT(epn); + maxp_csr->csrh |= MUSB_CSRH_TX_MODE; } +#endif - /* Setup FIFO */ - int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps)); - if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3; - unsigned addr = find_free_memory(size_in_log2_minus3); - TU_ASSERT(addr); + hwfifo_flush(musb, epn, is_rx, true); - USB0->EPIDX = epn; - if (dir_in) { - USB0->TXFIFOADD = addr; - USB0->TXFIFOSZ = size_in_log2_minus3; - } else { - USB0->RXFIFOADD = addr; - USB0->RXFIFOSZ = size_in_log2_minus3; - } + TU_ASSERT(hwfifo_config(musb, epn, is_rx, mps, false)); + musb->intren_ep[is_rx] |= TU_BIT(epn); return true; } -void dcd_edpt_close_all(uint8_t rhport) -{ - (void) rhport; - volatile hw_endpoint_t *regs = (volatile hw_endpoint_t *)(uintptr_t)&USB0->TXMAXP1; - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); - USB0->TXIE = 1; /* Enable only EP0 */ - USB0->RXIE = 0; - for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) { - regs->TXMAXP = 0; - regs->TXCSRH = 0; - if (regs->TXCSRL & USB_TXCSRL1_TXRDY) - regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; - else - regs->TXCSRL = USB_TXCSRL1_CLRDT; +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir_in = tu_edpt_dir(ep_addr); + musb_regs_t* musb = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); + const uint8_t is_rx = 1 - dir_in; + ep_csr->maxp_csr[is_rx].csrh = 0; + return hwfifo_config(musb, epn, is_rx, largest_packet_size, true); +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) { + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned mps = tu_edpt_packet_size(ep_desc); + + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); - regs->RXMAXP = 0; - regs->RXCSRH = 0; - if (regs->RXCSRL & USB_RXCSRL1_RXRDY) - regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; - else - regs->RXCSRL = USB_RXCSRL1_CLRDT; + pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; - USB0->EPIDX = i; - USB0->TXFIFOSZ = 0; - USB0->TXFIFOADD = 0; - USB0->RXFIFOSZ = 0; - USB0->RXFIFOADD = 0; + musb_regs_t* musb = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn); + const uint8_t is_rx = 1 - dir_in; + musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx]; + + maxp_csr->maxp = mps; + maxp_csr->csrh |= MUSB_CSRH_ISO; +#if MUSB_CFG_SHARED_FIFO + if (dir_in) { + maxp_csr->csrh |= MUSB_CSRH_TX_MODE; } - if (ie) NVIC_EnableIRQ(USB0_IRQn); +#endif + + hwfifo_flush(musb, epn, is_rx, true); + +#if MUSB_CFG_DYNAMIC_FIFO + // fifo space is already allocated, keep the address and just change packet size + musb->fifo_size[is_rx] = hwfifo_byte2size(mps) | MUSB_FIFOSZ_DOUBLE_PACKET; +#endif + + musb->intren_ep[is_rx] |= TU_BIT(epn); + + if (ie) musb_dcd_int_enable(rhport); + + return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_close_all(uint8_t rhport) { - (void)rhport; - unsigned const epn = tu_edpt_number(ep_addr); - unsigned const dir_in = tu_edpt_dir(ep_addr); + musb_regs_t* musb = MUSB_REGS(rhport); + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); - hw_endpoint_t volatile *regs = edpt_regs(epn - 1); - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); - if (dir_in) { - USB0->TXIE &= ~TU_BIT(epn); - regs->TXMAXP = 0; - regs->TXCSRH = 0; - if (regs->TXCSRL & USB_TXCSRL1_TXRDY) - regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; - else - regs->TXCSRL = USB_TXCSRL1_CLRDT; + musb->intr_txen = 1; /* Enable only EP0 */ + musb->intr_rxen = 0; + for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) { + musb_ep_csr_t* ep_csr = get_ep_csr(musb, i); + for (unsigned d = 0; d < 2; d++) { + musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[d]; + hwfifo_flush(musb, i, d, true); + hwfifo_reset(musb, i, d); + maxp_csr->maxp = 0; + maxp_csr->csrh = 0; + } + } - USB0->EPIDX = epn; - USB0->TXFIFOSZ = 0; - USB0->TXFIFOADD = 0; - } else { - USB0->RXIE &= ~TU_BIT(epn); - regs->RXMAXP = 0; - regs->RXCSRH = 0; - if (regs->RXCSRL & USB_RXCSRL1_RXRDY) - regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; - else - regs->RXCSRL = USB_RXCSRL1_CLRDT; +#if MUSB_CFG_DYNAMIC_FIFO + alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE; +#endif - USB0->EPIDX = epn; - USB0->RXFIFOSZ = 0; - USB0->RXFIFOADD = 0; - } - if (ie) NVIC_EnableIRQ(USB0_IRQn); + if (ie) musb_dcd_int_enable(rhport); } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack @@ -791,18 +776,22 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); unsigned const epnum = tu_edpt_number(ep_addr); - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); + if (epnum) { _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1); ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes); - } else + } else { ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes); - if (ie) NVIC_EnableIRQ(USB0_IRQn); + } + + if (ie) musb_dcd_int_enable(rhport); return ret; } -// 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 +// 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; @@ -810,99 +799,104 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); unsigned const epnum = tu_edpt_number(ep_addr); TU_ASSERT(epnum); - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1); ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes); - if (ie) NVIC_EnableIRQ(USB0_IRQn); + if (ie) musb_dcd_int_enable(rhport); return ret; } // Stall endpoint -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); + unsigned const epn = tu_edpt_number(ep_addr); - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); + if (0 == epn) { if (!ep_addr) { /* Ignore EP80 */ _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; _dcd.pipe0.buf = NULL; - USB0->CSRL0 = USB_CSRL0_STALL; + ep_csr->csr0l = MUSB_CSRL0_STALL; } } else { - volatile hw_endpoint_t *regs = edpt_regs(epn - 1); - if (tu_edpt_dir(ep_addr)) { /* IN */ - regs->TXCSRL = USB_TXCSRL1_STALL; - } else { /* OUT */ - TU_ASSERT(!(regs->RXCSRL & USB_RXCSRL1_RXRDY),); - regs->RXCSRL = USB_RXCSRL1_STALL; - } + const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); + ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_SEND_STALL(is_rx); } - if (ie) NVIC_EnableIRQ(USB0_IRQn); + + if (ie) musb_dcd_int_enable(rhport); } // clear stall, data toggle is also reset to DATA0 void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; + unsigned const ie = musb_dcd_get_int_enable(rhport); + musb_dcd_int_disable(rhport); + unsigned const epn = tu_edpt_number(ep_addr); - hw_endpoint_t volatile *regs = edpt_regs(epn - 1); - unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); - if (tu_edpt_dir(ep_addr)) { /* IN */ - regs->TXCSRL = USB_TXCSRL1_CLRDT; - } else { /* OUT */ - regs->RXCSRL = USB_RXCSRL1_CLRDT; - } - if (ie) NVIC_EnableIRQ(USB0_IRQn); + musb_regs_t* musb_regs = MUSB_REGS(rhport); + musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn); + const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr); + + ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx); + + if (ie) musb_dcd_int_enable(rhport); } /*------------------------------------------------------------------- * ISR *-------------------------------------------------------------------*/ -void dcd_int_handler(uint8_t rhport) -{ - uint_fast8_t is, txis, rxis; +void dcd_int_handler(uint8_t rhport) { + musb_regs_t* musb_regs = MUSB_REGS(rhport); + const uint8_t saved_index = musb_regs->index; // save endpoint index + + //Part specific ISR setup/entry + musb_dcd_int_handler_enter(rhport); - is = USB0->IS; /* read and clear interrupt status */ - txis = USB0->TXIS; /* read and clear interrupt status */ - rxis = USB0->RXIS; /* read and clear interrupt status */ + uint_fast8_t intr_usb = musb_regs->intr_usb; // a read will clear this interrupt status + uint_fast8_t intr_tx = musb_regs->intr_tx; // a read will clear this interrupt status + uint_fast8_t intr_rx = musb_regs->intr_rx; // a read will clear this interrupt status // TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis); - is &= USB0->IE; /* Clear disabled interrupts */ - if (is & USB_IS_DISCON) { + intr_usb &= musb_regs->intr_usben; /* Clear disabled interrupts */ + if (intr_usb & MUSB_IS_DISCON) { } - if (is & USB_IS_SOF) { + if (intr_usb & MUSB_IS_SOF) { dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } - if (is & USB_IS_RESET) { + if (intr_usb & MUSB_IS_RESET) { process_bus_reset(rhport); } - if (is & USB_IS_RESUME) { + if (intr_usb & MUSB_IS_RESUME) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } - if (is & USB_IS_SUSPEND) { + if (intr_usb & MUSB_IS_SUSPEND) { dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } - txis &= USB0->TXIE; /* Clear disabled interrupts */ - if (txis & USB_TXIE_EP0) { + intr_tx &= musb_regs->intr_txen; /* Clear disabled interrupts */ + if (intr_tx & TU_BIT(0)) { process_ep0(rhport); - txis &= ~TU_BIT(0); + intr_tx &= ~TU_BIT(0); } - while (txis) { - unsigned const num = __builtin_ctz(txis); + while (intr_tx) { + unsigned const num = __builtin_ctz(intr_tx); process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN)); - txis &= ~TU_BIT(num); + intr_tx &= ~TU_BIT(num); } - rxis &= USB0->RXIE; /* Clear disabled interrupts */ - while (rxis) { - unsigned const num = __builtin_ctz(rxis); + + intr_rx &= musb_regs->intr_rxen; /* Clear disabled interrupts */ + while (intr_rx) { + unsigned const num = __builtin_ctz(intr_rx); process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT)); - rxis &= ~TU_BIT(num); + intr_rx &= ~TU_BIT(num); } + + musb_regs->index = saved_index; // restore endpoint index } #endif diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c index 5312c2812..8fc225676 100644 --- a/src/portable/mentor/musb/hcd_musb.c +++ b/src/portable/mentor/musb/hcd_musb.c @@ -37,16 +37,10 @@ _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); #include "host/hcd.h" -#if TU_CHECK_MCU(OPT_MCU_MSP432E4) - #include "musb_msp432e.h" - -#elif TU_CHECK_MCU(OPT_MCU_TM4C123, OPT_MCU_TM4C129) - #include "musb_tm4c.h" - - // HACK generalize later - #include "musb_type.h" - #define FIFO0_WORD FIFO0 +#include "musb_type.h" +#if TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #include "musb_ti.h" #else #error "Unsupported MCUs" #endif diff --git a/src/portable/mentor/musb/musb_max32.h b/src/portable/mentor/musb/musb_max32.h new file mode 100644 index 000000000..35849b5f8 --- /dev/null +++ b/src/portable/mentor/musb/musb_max32.h @@ -0,0 +1,150 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc) + * + * 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_MUSB_MAX32_H_ +#define TUSB_MUSB_MAX32_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mxc_device.h" +#include "usbhs_regs.h" + +#define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints +#define MUSB_CFG_DYNAMIC_FIFO 0 // dynamic EP FIFO sizing + +const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS }; + +#if CFG_TUD_ENABLED +#define USBHS_M31_CLOCK_RECOVERY + +// Mapping of IRQ numbers to port. Currently just 1. +static const IRQn_Type musb_irqs[] = { + USB_IRQn +}; + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_enable(uint8_t rhport) { + NVIC_EnableIRQ(musb_irqs[rhport]); +} + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ(musb_irqs[rhport]); +} + +TU_ATTR_ALWAYS_INLINE static inline unsigned musb_dcd_get_int_enable(uint8_t rhport) { + #ifdef NVIC_GetEnableIRQ // only defined in CMSIS 5 + return NVIC_GetEnableIRQ(musb_irqs[rhport]); + #else + uint32_t IRQn = (uint32_t) musb_irqs[rhport]; + return ((NVIC->ISER[IRQn >> 5UL] & (1UL << (IRQn & 0x1FUL))) != 0UL) ? 1UL : 0UL; + #endif +} + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_clear(uint8_t rhport) { + NVIC_ClearPendingIRQ(musb_irqs[rhport]); +} + +static inline void musb_dcd_int_handler_enter(uint8_t rhport) { + mxc_usbhs_regs_t* hs_phy = MXC_USBHS; + uint32_t mxm_int, mxm_int_en, mxm_is; + + //Handle PHY specific events + mxm_int = hs_phy->mxm_int; + mxm_int_en = hs_phy->mxm_int_en; + mxm_is = mxm_int & mxm_int_en; + hs_phy->mxm_int = mxm_is; + + if (mxm_is & MXC_F_USBHS_MXM_INT_NOVBUS) { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } +} + +static inline void musb_dcd_phy_init(uint8_t rhport) { + (void) rhport; + mxc_usbhs_regs_t* hs_phy = MXC_USBHS; + + // Interrupt for VBUS disconnect + hs_phy->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS; + + musb_dcd_int_clear(rhport); + + // Unsuspend the MAC + hs_phy->mxm_suspend = 0; + + // Configure PHY + hs_phy->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11); + hs_phy->m31_phy_xcfgi_63_32 = 0; + hs_phy->m31_phy_xcfgi_95_64 = 0x1 << (72 - 64); + hs_phy->m31_phy_xcfgi_127_96 = 0; + + #ifdef USBHS_M31_CLOCK_RECOVERY + hs_phy->m31_phy_noncry_rstb = 1; + hs_phy->m31_phy_noncry_en = 1; + hs_phy->m31_phy_outclksel = 0; + hs_phy->m31_phy_coreclkin = 0; + hs_phy->m31_phy_xtlsel = 2; /* Select 25 MHz clock */ + #else + hs_phy->m31_phy_noncry_rstb = 0; + hs_phy->m31_phy_noncry_en = 0; + hs_phy->m31_phy_outclksel = 1; + hs_phy->m31_phy_coreclkin = 1; + hs_phy->m31_phy_xtlsel = 3; /* Select 30 MHz clock */ + #endif + hs_phy->m31_phy_pll_en = 1; + hs_phy->m31_phy_oscouten = 1; + + /* Reset PHY */ + hs_phy->m31_phy_ponrst = 0; + hs_phy->m31_phy_ponrst = 1; +} + +// static inline void musb_dcd_setup_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in, unsigned mps) { +// (void) mps; +// +// //Most likely the caller has already grabbed the right register block. But +// //as a precaution save and restore the register bank anyways +// unsigned saved_index = musb_periph_inst[rhport]->index; +// +// musb_periph_inst[rhport]->index = epnum; +// +// //Disable double buffering +// if (dir_in) { +// musb_periph_inst[rhport]->incsru |= (MXC_F_USBHS_INCSRU_DPKTBUFDIS | MXC_F_USBHS_INCSRU_MODE); +// } else { +// musb_periph_inst[rhport]->outcsru |= (MXC_F_USBHS_OUTCSRU_DPKTBUFDIS); +// } +// +// musb_periph_inst[rhport]->index = saved_index; +// } + +#endif // CFG_TUD_ENABLED + +#ifdef __cplusplus +} +#endif + +#endif // TUSB_MUSB_MAX32_H_ diff --git a/src/portable/mentor/musb/musb_msp432e.h b/src/portable/mentor/musb/musb_msp432e.h deleted file mode 100644 index fce21de88..000000000 --- a/src/portable/mentor/musb/musb_msp432e.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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_MUSB_MSP432E_H_ -#define _TUSB_MUSB_MSP432E_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "msp.h" - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/portable/mentor/musb/musb_tm4c.h b/src/portable/mentor/musb/musb_ti.h index 65a1751b0..d17e836ee 100644 --- a/src/portable/mentor/musb/musb_tm4c.h +++ b/src/portable/mentor/musb/musb_ti.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021, Ha Thach (tinyusb.org) + * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MUSB_TM4C_H_ -#define _TUSB_MUSB_TM4C_H_ +#ifndef TUSB_MUSB_TI_H_ +#define TUSB_MUSB_TI_H_ #ifdef __cplusplus extern "C" { @@ -33,13 +33,59 @@ #if CFG_TUSB_MCU == OPT_MCU_TM4C123 #include "TM4C123.h" + #define FIFO0_WORD FIFO0 + #define FIFO1_WORD FIFO1 //#elif CFG_TUSB_MCU == OPT_MCU_TM4C129 +#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 + #include "msp.h" #else #error "Unsupported MCUs" #endif +#define MUSB_CFG_SHARED_FIFO 0 +#define MUSB_CFG_DYNAMIC_FIFO 1 +#define MUSB_CFG_DYNAMIC_FIFO_SIZE 4096 + +const uintptr_t MUSB_BASES[] = { USB0_BASE }; + +// Header supports both device and host modes. Only include what's necessary +#if CFG_TUD_ENABLED + +// Mapping of IRQ numbers to port. Currently just 1. +static const IRQn_Type musb_irqs[] = { + USB0_IRQn +}; + +static inline void musb_dcd_phy_init(uint8_t rhport){ + (void)rhport; + //Nothing to do for this part +} + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_enable(uint8_t rhport) { + NVIC_EnableIRQ(musb_irqs[rhport]); +} + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ(musb_irqs[rhport]); +} + +TU_ATTR_ALWAYS_INLINE static inline unsigned musb_dcd_get_int_enable(uint8_t rhport) { + return NVIC_GetEnableIRQ(musb_irqs[rhport]); +} + +TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_clear(uint8_t rhport) { + NVIC_ClearPendingIRQ(musb_irqs[rhport]); +} + +static inline void musb_dcd_int_handler_enter(uint8_t rhport) { + (void)rhport; + //Nothing to do for this part +} + +#endif // CFG_TUD_ENABLED + #ifdef __cplusplus } #endif -#endif +#endif // TUSB_MUSB_TI_H_ diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h index 8f83305a5..4e448c0ed 100644 --- a/src/portable/mentor/musb/musb_type.h +++ b/src/portable/mentor/musb/musb_type.h @@ -1,3 +1,29 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + /****************************************************************************** * * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ @@ -32,2590 +58,696 @@ * *******************************************************************************/ -#ifndef _TUSB_MUSB_TYPE_H_ -#define _TUSB_MUSB_TYPE_H_ +#ifndef TUSB_MUSB_TYPE_H_ +#define TUSB_MUSB_TYPE_H_ + +#include "stdint.h" #ifdef __cplusplus extern "C" { #endif -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FADDR register. -// -//***************************************************************************** -#define USB_FADDR_M 0x0000007F // Function Address -#define USB_FADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_POWER register. -// -//***************************************************************************** -#define USB_POWER_ISOUP 0x00000080 // Isochronous Update -#define USB_POWER_SOFTCONN 0x00000040 // Soft Connect/Disconnect -#define USB_POWER_HSENAB 0x00000020 // High Speed Enable -#define USB_POWER_HSMODE 0x00000010 // High Speed Enable -#define USB_POWER_RESET 0x00000008 // RESET Signaling -#define USB_POWER_RESUME 0x00000004 // RESUME Signaling -#define USB_POWER_SUSPEND 0x00000002 // SUSPEND Mode -#define USB_POWER_PWRDNPHY 0x00000001 // Power Down PHY - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXIS register. -// -//***************************************************************************** -#define USB_TXIS_EP7 0x00000080 // TX Endpoint 7 Interrupt -#define USB_TXIS_EP6 0x00000040 // TX Endpoint 6 Interrupt -#define USB_TXIS_EP5 0x00000020 // TX Endpoint 5 Interrupt -#define USB_TXIS_EP4 0x00000010 // TX Endpoint 4 Interrupt -#define USB_TXIS_EP3 0x00000008 // TX Endpoint 3 Interrupt -#define USB_TXIS_EP2 0x00000004 // TX Endpoint 2 Interrupt -#define USB_TXIS_EP1 0x00000002 // TX Endpoint 1 Interrupt -#define USB_TXIS_EP0 0x00000001 // TX and RX Endpoint 0 Interrupt - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXIS register. -// -//***************************************************************************** -#define USB_RXIS_EP7 0x00000080 // RX Endpoint 7 Interrupt -#define USB_RXIS_EP6 0x00000040 // RX Endpoint 6 Interrupt -#define USB_RXIS_EP5 0x00000020 // RX Endpoint 5 Interrupt -#define USB_RXIS_EP4 0x00000010 // RX Endpoint 4 Interrupt -#define USB_RXIS_EP3 0x00000008 // RX Endpoint 3 Interrupt -#define USB_RXIS_EP2 0x00000004 // RX Endpoint 2 Interrupt -#define USB_RXIS_EP1 0x00000002 // RX Endpoint 1 Interrupt - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXIE register. -// -//***************************************************************************** -#define USB_TXIE_EP7 0x00000080 // TX Endpoint 7 Interrupt Enable -#define USB_TXIE_EP6 0x00000040 // TX Endpoint 6 Interrupt Enable -#define USB_TXIE_EP5 0x00000020 // TX Endpoint 5 Interrupt Enable -#define USB_TXIE_EP4 0x00000010 // TX Endpoint 4 Interrupt Enable -#define USB_TXIE_EP3 0x00000008 // TX Endpoint 3 Interrupt Enable -#define USB_TXIE_EP2 0x00000004 // TX Endpoint 2 Interrupt Enable -#define USB_TXIE_EP1 0x00000002 // TX Endpoint 1 Interrupt Enable -#define USB_TXIE_EP0 0x00000001 // TX and RX Endpoint 0 Interrupt - // Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXIE register. -// -//***************************************************************************** -#define USB_RXIE_EP7 0x00000080 // RX Endpoint 7 Interrupt Enable -#define USB_RXIE_EP6 0x00000040 // RX Endpoint 6 Interrupt Enable -#define USB_RXIE_EP5 0x00000020 // RX Endpoint 5 Interrupt Enable -#define USB_RXIE_EP4 0x00000010 // RX Endpoint 4 Interrupt Enable -#define USB_RXIE_EP3 0x00000008 // RX Endpoint 3 Interrupt Enable -#define USB_RXIE_EP2 0x00000004 // RX Endpoint 2 Interrupt Enable -#define USB_RXIE_EP1 0x00000002 // RX Endpoint 1 Interrupt Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_IS register. -// -//***************************************************************************** -#define USB_IS_VBUSERR 0x00000080 // VBUS Error (OTG only) -#define USB_IS_SESREQ 0x00000040 // SESSION REQUEST (OTG only) -#define USB_IS_DISCON 0x00000020 // Session Disconnect (OTG only) -#define USB_IS_CONN 0x00000010 // Session Connect -#define USB_IS_SOF 0x00000008 // Start of Frame -#define USB_IS_BABBLE 0x00000004 // Babble Detected -#define USB_IS_RESET 0x00000004 // RESET Signaling Detected -#define USB_IS_RESUME 0x00000002 // RESUME Signaling Detected -#define USB_IS_SUSPEND 0x00000001 // SUSPEND Signaling Detected - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_IE register. -// -//***************************************************************************** -#define USB_IE_VBUSERR 0x00000080 // Enable VBUS Error Interrupt (OTG - // only) -#define USB_IE_SESREQ 0x00000040 // Enable Session Request (OTG - // only) -#define USB_IE_DISCON 0x00000020 // Enable Disconnect Interrupt -#define USB_IE_CONN 0x00000010 // Enable Connect Interrupt -#define USB_IE_SOF 0x00000008 // Enable Start-of-Frame Interrupt -#define USB_IE_BABBLE 0x00000004 // Enable Babble Interrupt -#define USB_IE_RESET 0x00000004 // Enable RESET Interrupt -#define USB_IE_RESUME 0x00000002 // Enable RESUME Interrupt -#define USB_IE_SUSPND 0x00000001 // Enable SUSPEND Interrupt - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FRAME register. -// -//***************************************************************************** -#define USB_FRAME_M 0x000007FF // Frame Number -#define USB_FRAME_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPIDX register. -// -//***************************************************************************** -#define USB_EPIDX_EPIDX_M 0x0000000F // Endpoint Index -#define USB_EPIDX_EPIDX_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TEST register. -// -//***************************************************************************** -#define USB_TEST_FORCEH 0x00000080 // Force Host Mode -#define USB_TEST_FIFOACC 0x00000040 // FIFO Access -#define USB_TEST_FORCEFS 0x00000020 // Force Full-Speed Mode -#define USB_TEST_FORCEHS 0x00000010 // Force High-Speed Mode -#define USB_TEST_TESTPKT 0x00000008 // Test Packet Mode Enable -#define USB_TEST_TESTK 0x00000004 // Test_K Mode Enable -#define USB_TEST_TESTJ 0x00000002 // Test_J Mode Enable -#define USB_TEST_TESTSE0NAK 0x00000001 // Test_SE0_NAK Test Mode Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO0 register. -// -//***************************************************************************** -#define USB_FIFO0_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO0_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO1 register. -// -//***************************************************************************** -#define USB_FIFO1_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO1_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO2 register. -// -//***************************************************************************** -#define USB_FIFO2_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO2_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO3 register. -// -//***************************************************************************** -#define USB_FIFO3_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO3_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO4 register. -// -//***************************************************************************** -#define USB_FIFO4_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO4_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO5 register. -// -//***************************************************************************** -#define USB_FIFO5_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO5_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO6 register. -// -//***************************************************************************** -#define USB_FIFO6_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO6_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FIFO7 register. -// -//***************************************************************************** -#define USB_FIFO7_EPDATA_M 0xFFFFFFFF // Endpoint Data -#define USB_FIFO7_EPDATA_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DEVCTL register. -// -//***************************************************************************** -#define USB_DEVCTL_DEV 0x00000080 // Device Mode (OTG only) -#define USB_DEVCTL_FSDEV 0x00000040 // Full-Speed Device Detected -#define USB_DEVCTL_LSDEV 0x00000020 // Low-Speed Device Detected -#define USB_DEVCTL_VBUS_M 0x00000018 // VBUS Level (OTG only) -#define USB_DEVCTL_VBUS_NONE 0x00000000 // Below SessionEnd -#define USB_DEVCTL_VBUS_SEND 0x00000008 // Above SessionEnd, below AValid -#define USB_DEVCTL_VBUS_AVALID 0x00000010 // Above AValid, below VBUSValid -#define USB_DEVCTL_VBUS_VALID 0x00000018 // Above VBUSValid -#define USB_DEVCTL_HOST 0x00000004 // Host Mode -#define USB_DEVCTL_HOSTREQ 0x00000002 // Host Request (OTG only) -#define USB_DEVCTL_SESSION 0x00000001 // Session Start/End (OTG only) - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_CCONF register. -// -//***************************************************************************** -#define USB_CCONF_TXEDMA 0x00000002 // TX Early DMA Enable -#define USB_CCONF_RXEDMA 0x00000001 // TX Early DMA Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFIFOSZ register. -// -//***************************************************************************** -#define USB_TXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support -#define USB_TXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size -#define USB_TXFIFOSZ_SIZE_8 0x00000000 // 8 -#define USB_TXFIFOSZ_SIZE_16 0x00000001 // 16 -#define USB_TXFIFOSZ_SIZE_32 0x00000002 // 32 -#define USB_TXFIFOSZ_SIZE_64 0x00000003 // 64 -#define USB_TXFIFOSZ_SIZE_128 0x00000004 // 128 -#define USB_TXFIFOSZ_SIZE_256 0x00000005 // 256 -#define USB_TXFIFOSZ_SIZE_512 0x00000006 // 512 -#define USB_TXFIFOSZ_SIZE_1024 0x00000007 // 1024 -#define USB_TXFIFOSZ_SIZE_2048 0x00000008 // 2048 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFIFOSZ register. -// -//***************************************************************************** -#define USB_RXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support -#define USB_RXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size -#define USB_RXFIFOSZ_SIZE_8 0x00000000 // 8 -#define USB_RXFIFOSZ_SIZE_16 0x00000001 // 16 -#define USB_RXFIFOSZ_SIZE_32 0x00000002 // 32 -#define USB_RXFIFOSZ_SIZE_64 0x00000003 // 64 -#define USB_RXFIFOSZ_SIZE_128 0x00000004 // 128 -#define USB_RXFIFOSZ_SIZE_256 0x00000005 // 256 -#define USB_RXFIFOSZ_SIZE_512 0x00000006 // 512 -#define USB_RXFIFOSZ_SIZE_1024 0x00000007 // 1024 -#define USB_RXFIFOSZ_SIZE_2048 0x00000008 // 2048 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFIFOADD -// register. -// -//***************************************************************************** -#define USB_TXFIFOADD_ADDR_M 0x000001FF // Transmit/Receive Start Address -#define USB_TXFIFOADD_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFIFOADD -// register. -// -//***************************************************************************** -#define USB_RXFIFOADD_ADDR_M 0x000001FF // Transmit/Receive Start Address -#define USB_RXFIFOADD_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_ULPIVBUSCTL -// register. -// -//***************************************************************************** -#define USB_ULPIVBUSCTL_USEEXTVBUSIND \ - 0x00000002 // Use External VBUS Indicator -#define USB_ULPIVBUSCTL_USEEXTVBUS \ - 0x00000001 // Use External VBUS - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_ULPIREGDATA -// register. -// -//***************************************************************************** -#define USB_ULPIREGDATA_REGDATA_M \ - 0x000000FF // Register Data -#define USB_ULPIREGDATA_REGDATA_S \ - 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_ULPIREGADDR -// register. -// -//***************************************************************************** -#define USB_ULPIREGADDR_ADDR_M 0x000000FF // Register Address -#define USB_ULPIREGADDR_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_ULPIREGCTL -// register. -// -//***************************************************************************** -#define USB_ULPIREGCTL_RDWR 0x00000004 // Read/Write Control -#define USB_ULPIREGCTL_REGCMPLT 0x00000002 // Register Access Complete -#define USB_ULPIREGCTL_REGACC 0x00000001 // Initiate Register Access - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPINFO register. -// -//***************************************************************************** -#define USB_EPINFO_RXEP_M 0x000000F0 // RX Endpoints -#define USB_EPINFO_TXEP_M 0x0000000F // TX Endpoints -#define USB_EPINFO_RXEP_S 4 -#define USB_EPINFO_TXEP_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RAMINFO register. -// -//***************************************************************************** -#define USB_RAMINFO_DMACHAN_M 0x000000F0 // DMA Channels -#define USB_RAMINFO_RAMBITS_M 0x0000000F // RAM Address Bus Width -#define USB_RAMINFO_DMACHAN_S 4 -#define USB_RAMINFO_RAMBITS_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_CONTIM register. -// -//***************************************************************************** -#define USB_CONTIM_WTCON_M 0x000000F0 // Connect Wait -#define USB_CONTIM_WTID_M 0x0000000F // Wait ID -#define USB_CONTIM_WTCON_S 4 -#define USB_CONTIM_WTID_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_VPLEN register. -// -//***************************************************************************** -#define USB_VPLEN_VPLEN_M 0x000000FF // VBUS Pulse Length -#define USB_VPLEN_VPLEN_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_HSEOF register. -// -//***************************************************************************** -#define USB_HSEOF_HSEOFG_M 0x000000FF // HIgh-Speed End-of-Frame Gap -#define USB_HSEOF_HSEOFG_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_FSEOF register. -// -//***************************************************************************** -#define USB_FSEOF_FSEOFG_M 0x000000FF // Full-Speed End-of-Frame Gap -#define USB_FSEOF_FSEOFG_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LSEOF register. -// -//***************************************************************************** -#define USB_LSEOF_LSEOFG_M 0x000000FF // Low-Speed End-of-Frame Gap -#define USB_LSEOF_LSEOFG_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR0 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR0_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR0_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR0 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR0_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR0_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT0 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT0_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT0_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR1 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR1_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR1_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR1 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR1_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR1_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT1 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT1_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT1_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR1 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR1_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR1_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR1 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR1_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR1_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT1 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT1_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT1_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR2 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR2_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR2_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR2 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR2_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR2_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT2 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT2_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT2_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR2 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR2_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR2_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR2 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR2_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR2_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT2 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT2_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT2_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR3 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR3_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR3_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR3 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR3_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR3_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT3 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT3_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT3_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR3 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR3_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR3_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR3 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR3_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR3_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT3 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT3_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT3_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR4 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR4_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR4_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR4 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR4_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR4_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT4 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT4_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT4_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR4 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR4_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR4_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR4 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR4_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR4_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT4 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT4_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT4_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR5 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR5_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR5_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR5 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR5_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR5_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT5 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT5_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT5_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR5 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR5_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR5_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR5 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR5_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR5_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT5 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT5_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT5_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR6 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR6_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR6_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR6 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR6_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR6_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT6 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT6_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT6_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR6 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR6_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR6_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR6 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR6_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR6_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT6 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT6_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT6_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXFUNCADDR7 -// register. -// -//***************************************************************************** -#define USB_TXFUNCADDR7_ADDR_M 0x0000007F // Device Address -#define USB_TXFUNCADDR7_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBADDR7 -// register. -// -//***************************************************************************** -#define USB_TXHUBADDR7_ADDR_M 0x0000007F // Hub Address -#define USB_TXHUBADDR7_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXHUBPORT7 -// register. -// -//***************************************************************************** -#define USB_TXHUBPORT7_PORT_M 0x0000007F // Hub Port -#define USB_TXHUBPORT7_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXFUNCADDR7 -// register. -// -//***************************************************************************** -#define USB_RXFUNCADDR7_ADDR_M 0x0000007F // Device Address -#define USB_RXFUNCADDR7_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBADDR7 -// register. -// -//***************************************************************************** -#define USB_RXHUBADDR7_ADDR_M 0x0000007F // Hub Address -#define USB_RXHUBADDR7_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXHUBPORT7 -// register. -// -//***************************************************************************** -#define USB_RXHUBPORT7_PORT_M 0x0000007F // Hub Port -#define USB_RXHUBPORT7_PORT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_CSRL0 register. -// -//***************************************************************************** -#define USB_CSRL0_NAKTO 0x00000080 // NAK Timeout -#define USB_CSRL0_SETENDC 0x00000080 // Setup End Clear -#define USB_CSRL0_STATUS 0x00000040 // STATUS Packet -#define USB_CSRL0_RXRDYC 0x00000040 // RXRDY Clear -#define USB_CSRL0_REQPKT 0x00000020 // Request Packet -#define USB_CSRL0_STALL 0x00000020 // Send Stall -#define USB_CSRL0_SETEND 0x00000010 // Setup End -#define USB_CSRL0_ERROR 0x00000010 // Error -#define USB_CSRL0_DATAEND 0x00000008 // Data End -#define USB_CSRL0_SETUP 0x00000008 // Setup Packet -#define USB_CSRL0_STALLED 0x00000004 // Endpoint Stalled -#define USB_CSRL0_TXRDY 0x00000002 // Transmit Packet Ready -#define USB_CSRL0_RXRDY 0x00000001 // Receive Packet Ready - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_CSRH0 register. -// -//***************************************************************************** -#define USB_CSRH0_DISPING 0x00000008 // PING Disable -#define USB_CSRH0_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_CSRH0_DT 0x00000002 // Data Toggle -#define USB_CSRH0_FLUSH 0x00000001 // Flush FIFO - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_COUNT0 register. -// -//***************************************************************************** -#define USB_COUNT0_COUNT_M 0x0000007F // FIFO Count -#define USB_COUNT0_COUNT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TYPE0 register. -// -//***************************************************************************** -#define USB_TYPE0_SPEED_M 0x000000C0 // Operating Speed -#define USB_TYPE0_SPEED_HIGH 0x00000040 // High -#define USB_TYPE0_SPEED_FULL 0x00000080 // Full -#define USB_TYPE0_SPEED_LOW 0x000000C0 // Low - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_NAKLMT register. -// -//***************************************************************************** -#define USB_NAKLMT_NAKLMT_M 0x0000001F // EP0 NAK Limit -#define USB_NAKLMT_NAKLMT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXMAXP1 register. -// -//***************************************************************************** -#define USB_TXMAXP1_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP1_MAXLOAD_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL1 register. -// -//***************************************************************************** -#define USB_TXCSRL1_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL1_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL1_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL1_STALL 0x00000010 // Send STALL -#define USB_TXCSRL1_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL1_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL1_ERROR 0x00000004 // Error -#define USB_TXCSRL1_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL1_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL1_TXRDY 0x00000001 // Transmit Packet Ready +#ifndef __IO + #define __IO volatile +#endif -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRH1 register. -// -//***************************************************************************** -#define USB_TXCSRH1_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH1_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH1_MODE 0x00000020 // Mode -#define USB_TXCSRH1_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH1_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH1_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH1_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH1_DT 0x00000001 // Data Toggle +#ifndef __I + #define __I volatile const +#endif -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXMAXP1 register. -// -//***************************************************************************** -#define USB_RXMAXP1_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP1_MAXLOAD_S 0 +#ifndef __O + #define __O volatile +#endif -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRL1 register. -// -//***************************************************************************** -#define USB_RXCSRL1_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL1_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL1_STALL 0x00000020 // Send STALL -#define USB_RXCSRL1_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL1_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL1_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL1_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL1_OVER 0x00000004 // Overrun -#define USB_RXCSRL1_ERROR 0x00000004 // Error -#define USB_RXCSRL1_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL1_RXRDY 0x00000001 // Receive Packet Ready +#ifndef __R + #define __R volatile const +#endif -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRH1 register. -// -//***************************************************************************** -#define USB_RXCSRH1_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH1_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH1_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH1_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH1_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH1_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH1_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH1_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH1_DT 0x00000002 // Data Toggle -#define USB_RXCSRH1_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status +typedef struct TU_ATTR_PACKED { + __IO uint16_t maxp; // 0x00, 0x04: MAXP + __IO uint8_t csrl; // 0x02, 0x06: CSRL + __IO uint8_t csrh; // 0x03, 0x07: CSRH +}musb_ep_maxp_csr_t; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCOUNT1 register. -// -//***************************************************************************** -#define USB_RXCOUNT1_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT1_COUNT_S 0 +// 0: TX (device IN, host OUT) +// 1: RX (device OUT, host IN) +typedef struct TU_ATTR_PACKED { + union { + struct { + __IO uint16_t tx_maxp; // 0x00: TXMAXP + union { + __IO uint8_t csr0l; // 0x02: CSR0 + __IO uint8_t tx_csrl; // 0x02: TX CSRL + }; + union { + __IO uint8_t csr0h; // 0x03: CSR0H + __IO uint8_t tx_csrh; // 0x03: TX CSRH + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXTYPE1 register. -// -//***************************************************************************** -#define USB_TXTYPE1_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE1_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE1_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE1_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE1_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE1_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE1_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE1_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE1_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE1_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE1_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE1_TEP_S 0 + __IO uint16_t rx_maxp; // 0x04: RX MAXP + __IO uint8_t rx_csrl; // 0x06: RX CSRL + __IO uint8_t rx_csrh; // 0x07: RX CSRH + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXINTERVAL1 -// register. -// -//***************************************************************************** -#define USB_TXINTERVAL1_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL1_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL1_TXPOLL_S \ - 0 -#define USB_TXINTERVAL1_NAKLMT_S \ - 0 + musb_ep_maxp_csr_t maxp_csr[2]; + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXTYPE1 register. -// -//***************************************************************************** -#define USB_RXTYPE1_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE1_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE1_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE1_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE1_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE1_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE1_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE1_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE1_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE1_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE1_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE1_TEP_S 0 + union { + __IO uint16_t count0; // 0x08: COUNT0 + __IO uint16_t rx_count; // 0x08: RX COUNT + }; + union { + __IO uint8_t type0; // 0x0A: TYPE0 (host only) + __IO uint8_t tx_type; // 0x0A: TX TYPE + }; + __IO uint8_t tx_interval; // 0x0B: TX INTERVAL + __IO uint8_t rx_type; // 0x0C: RX TYPE + __IO uint8_t rx_interval; // 0x0D: RX INTERVAL + __IO uint8_t reserved_0x0e; // 0x0E: Reserved + union { + __IO uint8_t config_data0; // 0x0F: CONFIG DATA + struct { + __IO uint8_t utmi_data_width : 1; // [0] UTMI Data Width + __IO uint8_t softconn_en : 1; // [1] Soft Connect Enable + __IO uint8_t dynamic_fifo : 1; // [2] Dynamic FIFO Sizing + __IO uint8_t hb_tx_en : 1; // [3] High Bandwidth TX ISO Enable + __IO uint8_t hb_rx_en : 1; // [4] High Bandwidth RX ISO Enable + __IO uint8_t big_endian : 1; // [5] Big Endian + __IO uint8_t mp_tx_en : 1; // [6] Auto splitting BULK TX Enable + __IO uint8_t mp_rx_en : 1; // [7] Auto amalgamation BULK RX Enable + } config_data0_bit; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXINTERVAL1 -// register. -// -//***************************************************************************** -#define USB_RXINTERVAL1_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL1_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL1_TXPOLL_S \ - 0 -#define USB_RXINTERVAL1_NAKLMT_S \ - 0 + __IO uint8_t fifo_size; // 0x0F: FIFO_SIZE + struct { + __IO uint8_t tx : 4; // [3:0] TX FIFO Size + __IO uint8_t rx : 4; // [7:4] RX FIFO Size + }fifo_size_bit; + }; +} musb_ep_csr_t; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXMAXP2 register. -// -//***************************************************************************** -#define USB_TXMAXP2_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP2_MAXLOAD_S 0 +TU_VERIFY_STATIC(sizeof(musb_ep_csr_t) == 16, "size is not correct"); -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL2 register. -// -//***************************************************************************** -#define USB_TXCSRL2_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL2_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL2_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL2_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL2_STALL 0x00000010 // Send STALL -#define USB_TXCSRL2_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL2_ERROR 0x00000004 // Error -#define USB_TXCSRL2_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL2_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL2_TXRDY 0x00000001 // Transmit Packet Ready +typedef struct TU_ATTR_PACKED { + //------------- Common -------------// + __IO uint8_t faddr; // 0x00: FADDR + union { + __IO uint8_t power; // 0x01: POWER + struct { + __IO uint8_t suspend_mode_en : 1; // [0] SUSPEND Mode Enable + __IO uint8_t suspend_mode : 1; // [1] SUSPEND Mode + __IO uint8_t resume_mode : 1; // [2] RESUME + __IO uint8_t reset : 1; // [3] RESET + __IO uint8_t highspeed_mode : 1; // [4] High Speed Mode + __IO uint8_t highspeed_en : 1; // [5] High Speed Enable + __IO uint8_t soft_conn : 1; // [6] Soft Connect/Disconnect + __IO uint8_t iso_update : 1; // [7] Isochronous Update + } power_bit; + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRH2 register. -// -//***************************************************************************** -#define USB_TXCSRH2_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH2_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH2_MODE 0x00000020 // Mode -#define USB_TXCSRH2_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH2_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH2_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH2_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH2_DT 0x00000001 // Data Toggle + union { + struct { + __IO uint16_t intr_tx; // 0x02: INTR_TX + __IO uint16_t intr_rx; // 0x04: INTR_RX + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXMAXP2 register. -// -//***************************************************************************** -#define USB_RXMAXP2_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP2_MAXLOAD_S 0 + __IO uint16_t intr_ep[2]; // 0x02-0x05: INTR_EP0-1 + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRL2 register. -// -//***************************************************************************** -#define USB_RXCSRL2_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL2_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL2_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL2_STALL 0x00000020 // Send STALL -#define USB_RXCSRL2_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL2_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL2_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL2_ERROR 0x00000004 // Error -#define USB_RXCSRL2_OVER 0x00000004 // Overrun -#define USB_RXCSRL2_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL2_RXRDY 0x00000001 // Receive Packet Ready + union { + struct { + __IO uint16_t intr_txen; // 0x06: INTR_TXEN + __IO uint16_t intr_rxen; // 0x08: INTR_RXEN + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRH2 register. -// -//***************************************************************************** -#define USB_RXCSRH2_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH2_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH2_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH2_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH2_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH2_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH2_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH2_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH2_DT 0x00000002 // Data Toggle -#define USB_RXCSRH2_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status + __IO uint16_t intren_ep[2]; // 0x06-0x09: INTREN_EP0-1 + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCOUNT2 register. -// -//***************************************************************************** -#define USB_RXCOUNT2_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT2_COUNT_S 0 + __IO uint8_t intr_usb; // 0x0A: INTRUSB + __IO uint8_t intr_usben; // 0x0B: INTRUSBEN -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXTYPE2 register. -// -//***************************************************************************** -#define USB_TXTYPE2_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE2_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE2_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE2_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE2_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE2_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE2_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE2_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE2_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE2_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE2_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE2_TEP_S 0 + __IO uint16_t frame; // 0x0C: FRAME + __IO uint8_t index; // 0x0E: INDEX + __IO uint8_t testmode; // 0x0F: TESTMODE -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXINTERVAL2 -// register. -// -//***************************************************************************** -#define USB_TXINTERVAL2_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL2_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL2_NAKLMT_S \ - 0 -#define USB_TXINTERVAL2_TXPOLL_S \ - 0 + //------------- Endpoint CSR (indexed) -------------// + musb_ep_csr_t indexed_csr; // 0x10-0x1F: Indexed CSR 0-15 -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXTYPE2 register. -// -//***************************************************************************** -#define USB_RXTYPE2_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE2_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE2_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE2_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE2_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE2_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE2_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE2_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE2_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE2_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE2_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE2_TEP_S 0 + //------------- FIFOs -------------// + __IO uint32_t fifo[16]; // 0x20-0x5C: FIFO 0-15 -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXINTERVAL2 -// register. -// -//***************************************************************************** -#define USB_RXINTERVAL2_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL2_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL2_TXPOLL_S \ - 0 -#define USB_RXINTERVAL2_NAKLMT_S \ - 0 + // Common (2) + __IO uint8_t devctl; // 0x60: DEVCTL + __IO uint8_t misc; // 0x61: MISC -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXMAXP3 register. -// -//***************************************************************************** -#define USB_TXMAXP3_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP3_MAXLOAD_S 0 + //------------- Dynammic FIFO (indexed) -------------// + union { + struct { + __IO uint8_t txfifo_sz; // 0x62: TXFIFO_SZ + __IO uint8_t rxfifo_sz; // 0x63: RXFIFO_SZ + }; + __IO uint8_t fifo_size[2]; + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL3 register. -// -//***************************************************************************** -#define USB_TXCSRL3_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL3_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL3_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL3_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL3_STALL 0x00000010 // Send STALL -#define USB_TXCSRL3_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL3_ERROR 0x00000004 // Error -#define USB_TXCSRL3_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL3_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL3_TXRDY 0x00000001 // Transmit Packet Ready + union { + struct { + __IO uint16_t txfifo_addr; // 0x64: TXFIFO_ADDR + __IO uint16_t rxfifo_addr; // 0x66: RXFIFO_ADDR + }; + __IO uint16_t fifo_addr[2]; + }; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRH3 register. -// -//***************************************************************************** -#define USB_TXCSRH3_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH3_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH3_MODE 0x00000020 // Mode -#define USB_TXCSRH3_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH3_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH3_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH3_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH3_DT 0x00000001 // Data Toggle + //------------- Additional Control and Configuration -------------// + union { + __O uint32_t vcontrol; // 0x68: PHY VCONTROL + __IO uint32_t vstatus; // 0x68: PHY VSTATUS + }; + union { + __IO uint16_t hwvers; // 0x6C: HWVERS + struct { + __IO uint16_t minor : 10; // [9:0] Minor + __IO uint16_t major : 5; // [14:10] Major + __IO uint16_t rc : 1; // [15] Release Candidate + } hwvers_bit; + }; + __R uint16_t rsv_0x6e_0x77[5]; // 0x6E-0x77: Reserved -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXMAXP3 register. -// -//***************************************************************************** -#define USB_RXMAXP3_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP3_MAXLOAD_S 0 + //------------- Additional Configuration -------------// + union { + __IO uint8_t epinfo; // 0x78: EPINFO + struct { + __IO uint8_t tx_ep_num : 4; // [3:0] TX Endpoints + __IO uint8_t rx_ep_num : 4; // [7:4] RX Endpoints + } epinfo_bit; + }; + union { + __IO uint8_t raminfo; // 0x79: RAMINFO + struct { + __IO uint8_t ram_bits : 4; // [3:0] RAM Address Bus Width + __IO uint8_t dma_channel : 4; // [7:4] DMA Channels + }raminfo_bit; + }; + union { + __IO uint8_t link_info; // 0x7A: LINK_INFO + __IO uint8_t adi_softreset; // 0x7A: AnalogDevice SOFTRESET + }; + __IO uint8_t vplen; // 0x7B: VPLEN + __IO uint8_t hs_eof1; // 0x7C: HS_EOF1 + __IO uint8_t fs_eof1; // 0x7D: FS_EOF1 + __IO uint8_t ls_eof1; // 0x7E: LS_EOF1 + __IO uint8_t soft_rst; // 0x7F: SOFT_RST -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRL3 register. -// -//***************************************************************************** -#define USB_RXCSRL3_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL3_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL3_STALL 0x00000020 // Send STALL -#define USB_RXCSRL3_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL3_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL3_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL3_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL3_ERROR 0x00000004 // Error -#define USB_RXCSRL3_OVER 0x00000004 // Overrun -#define USB_RXCSRL3_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL3_RXRDY 0x00000001 // Receive Packet Ready + //------------- Target Endpoints (multipoint option) -------------// + __IO uint16_t ctuch; // 0x80: CTUCH + __IO uint16_t cthsrtn; // 0x82: CTHSRTN + __R uint32_t rsv_0x84_0xff[31]; // 0x84-0xFF: Reserved -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRH3 register. -// -//***************************************************************************** -#define USB_RXCSRH3_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH3_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH3_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH3_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH3_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH3_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH3_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH3_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH3_DT 0x00000002 // Data Toggle -#define USB_RXCSRH3_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status + //------------- Non-Indexed Endpoint CSRs -------------// + // TI tm4c can access this directly, but should use indexed_csr for portability + musb_ep_csr_t abs_csr[16]; // 0x100-0x1FF: EP0-15 CSR -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCOUNT3 register. -// -//***************************************************************************** -#define USB_RXCOUNT3_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT3_COUNT_S 0 + //------------- DMA -------------// + __IO uint8_t dma_intr; // 0x200: DMA_INTR + __R uint8_t rsv_0x201_0x203[3]; // 0x201-0x203: Reserved + struct { + __IO uint16_t cntl; // 0x204: DMA_CNTL + __IO uint16_t rsv_0x206; // 0x206: Reserved + __IO uint32_t addr; // 0x208: DMA_ADDR + __IO uint32_t count; // 0x20C: DMA_COUNT + __IO uint32_t rsv_0x210; // 0x210: Reserved + }dma[8]; + __R uint32_t rsv_0x284_0x2FF[31]; // 0x284-0x2FF: Reserved -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXTYPE3 register. -// -//***************************************************************************** -#define USB_TXTYPE3_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE3_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE3_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE3_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE3_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE3_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE3_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE3_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE3_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE3_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE3_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE3_TEP_S 0 + //------------- Extended -------------// + __R uint32_t rsv_0x300; // 0x300: Reserved + struct { + __IO uint16_t count; // 0x304: REQ_PACKET_COUNT + __R uint16_t rsv_0x306; // 0x306: Reserved + }req_packet[15]; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXINTERVAL3 -// register. -// -//***************************************************************************** -#define USB_TXINTERVAL3_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL3_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL3_TXPOLL_S \ - 0 -#define USB_TXINTERVAL3_NAKLMT_S \ - 0 + __IO uint16_t rx_doulbe_packet_disable; // 0x340: RX_DOUBLE_PACKET_DISABLE + __IO uint16_t tx_double_packet_disable; // 0x342: TX_DOUBLE_PACKET_DISABLE -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXTYPE3 register. -// -//***************************************************************************** -#define USB_RXTYPE3_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE3_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE3_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE3_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE3_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE3_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE3_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE3_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE3_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE3_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE3_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE3_TEP_S 0 + __IO uint16_t chirp_timeout; // 0x344: CHIRP_TIMEOUT + __IO uint16_t hs_to_utm; // 0x346: HS_TO_UTM delay + __IO uint16_t hs_timeout_adder; // 0x348: HS_TIMEOUT_ADDER -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXINTERVAL3 -// register. -// -//***************************************************************************** -#define USB_RXINTERVAL3_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL3_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL3_TXPOLL_S \ - 0 -#define USB_RXINTERVAL3_NAKLMT_S \ - 0 + __R uint8_t rsv_34A_34f[6]; // 0x34A-0x34F: Reserved +} musb_regs_t; -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXMAXP4 register. -// -//***************************************************************************** -#define USB_TXMAXP4_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP4_MAXLOAD_S 0 +TU_VERIFY_STATIC(sizeof(musb_regs_t) == 0x350, "size is not correct"); -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL4 register. -// -//***************************************************************************** -#define USB_TXCSRL4_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL4_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL4_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL4_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL4_STALL 0x00000010 // Send STALL -#define USB_TXCSRL4_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL4_ERROR 0x00000004 // Error -#define USB_TXCSRL4_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL4_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL4_TXRDY 0x00000001 // Transmit Packet Ready +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline musb_ep_csr_t* get_ep_csr(musb_regs_t* musb_regs, unsigned epnum) { + musb_regs->index = epnum; + return &musb_regs->indexed_csr; +} -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRH4 register. -// -//***************************************************************************** -#define USB_TXCSRH4_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH4_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH4_MODE 0x00000020 // Mode -#define USB_TXCSRH4_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH4_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH4_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH4_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH4_DT 0x00000001 // Data Toggle +//--------------------------------------------------------------------+ +// Register Bit Field +//--------------------------------------------------------------------+ -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXMAXP4 register. -// -//***************************************************************************** -#define USB_RXMAXP4_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP4_MAXLOAD_S 0 +// 0x01: Power +#define MUSB_POWER_ISOUP 0x0080 // Isochronous Update +#define MUSB_POWER_SOFTCONN 0x0040 // Soft Connect/Disconnect +#define MUSB_POWER_HSENAB 0x0020 // High Speed Enable +#define MUSB_POWER_HSMODE 0x0010 // High Speed Enable +#define MUSB_POWER_RESET 0x0008 // RESET Signaling +#define MUSB_POWER_RESUME 0x0004 // RESUME Signaling +#define MUSB_POWER_SUSPEND 0x0002 // SUSPEND Mode +#define MUSB_POWER_PWRDNPHY 0x0001 // Power Down PHY -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRL4 register. -// -//***************************************************************************** -#define USB_RXCSRL4_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL4_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL4_STALL 0x00000020 // Send STALL -#define USB_RXCSRL4_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL4_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL4_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL4_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL4_OVER 0x00000004 // Overrun -#define USB_RXCSRL4_ERROR 0x00000004 // Error -#define USB_RXCSRL4_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL4_RXRDY 0x00000001 // Receive Packet Ready - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRH4 register. -// -//***************************************************************************** -#define USB_RXCSRH4_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH4_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH4_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH4_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH4_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH4_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH4_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH4_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH4_DT 0x00000002 // Data Toggle -#define USB_RXCSRH4_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCOUNT4 register. -// -//***************************************************************************** -#define USB_RXCOUNT4_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT4_COUNT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXTYPE4 register. -// -//***************************************************************************** -#define USB_TXTYPE4_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE4_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE4_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE4_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE4_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE4_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE4_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE4_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE4_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE4_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE4_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE4_TEP_S 0 +// Interrupt TX/RX Status and Enable: each bit is for an endpoint -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXINTERVAL4 -// register. -// -//***************************************************************************** -#define USB_TXINTERVAL4_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL4_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL4_NAKLMT_S \ - 0 -#define USB_TXINTERVAL4_TXPOLL_S \ - 0 +// 0x6c: HWVERS +#define MUSB_HWVERS_RC_SHIFT 15 +#define MUSB_HWVERS_RC_MASK 0x8000 +#define MUSB_HWVERS_MAJOR_SHIFT 10 +#define MUSB_HWVERS_MAJOR_MASK 0x7C00 +#define MUSB_HWVERS_MINOR_SHIFT 0 +#define MUSB_HWVERS_MINOR_MASK 0x03FF -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXTYPE4 register. -// -//***************************************************************************** -#define USB_RXTYPE4_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE4_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE4_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE4_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE4_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE4_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE4_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE4_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE4_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE4_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE4_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE4_TEP_S 0 +// 0x12, 0x16: TX/RX CSRL +#define MUSB_CSRL_PACKET_READY(_rx) (1u << 0) +#define MUSB_CSRL_FLUSH_FIFO(_rx) (1u << ((_rx) ? 4 : 3)) +#define MUSB_CSRL_SEND_STALL(_rx) (1u << ((_rx) ? 5 : 4)) +#define MUSB_CSRL_STALLED(_rx) (1u << ((_rx) ? 6 : 5)) +#define MUSB_CSRL_CLEAR_DATA_TOGGLE(_rx) (1u << ((_rx) ? 7 : 6)) -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXINTERVAL4 -// register. -// -//***************************************************************************** -#define USB_RXINTERVAL4_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL4_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL4_NAKLMT_S \ - 0 -#define USB_RXINTERVAL4_TXPOLL_S \ - 0 +// 0x13, 0x17: TX/RX CSRH +#define MUSB_CSRH_DISABLE_DOUBLE_PACKET(_rx) (1u << 1) +#define MUSB_CSRH_TX_MODE (1u << 5) // 1 = TX, 0 = RX. only relevant for SHARED FIFO +#define MUSB_CSRH_ISO (1u << 6) -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXMAXP5 register. -// -//***************************************************************************** -#define USB_TXMAXP5_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP5_MAXLOAD_S 0 +// 0x62, 0x63: TXFIFO_SZ, RXFIFO_SZ +#define MUSB_FIFOSZ_DOUBLE_PACKET (1u << 4) -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL5 register. -// -//***************************************************************************** -#define USB_TXCSRL5_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL5_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL5_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL5_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL5_STALL 0x00000010 // Send STALL -#define USB_TXCSRL5_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL5_ERROR 0x00000004 // Error -#define USB_TXCSRL5_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL5_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL5_TXRDY 0x00000001 // Transmit Packet Ready //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXCSRH5 register. +// The following are defines for the bit fields in the MUSB_O_IS register. // //***************************************************************************** -#define USB_TXCSRH5_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH5_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH5_MODE 0x00000020 // Mode -#define USB_TXCSRH5_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH5_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH5_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH5_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH5_DT 0x00000001 // Data Toggle +#define MUSB_IS_VBUSERR 0x0080 // VBUS Error (OTG only) +#define MUSB_IS_SESREQ 0x0040 // SESSION REQUEST (OTG only) +#define MUSB_IS_DISCON 0x0020 // Session Disconnect (OTG only) +#define MUSB_IS_CONN 0x0010 // Session Connect +#define MUSB_IS_SOF 0x0008 // Start of Frame +#define MUSB_IS_BABBLE 0x0004 // Babble Detected +#define MUSB_IS_RESET 0x0004 // RESET Signaling Detected +#define MUSB_IS_RESUME 0x0002 // RESUME Signaling Detected +#define MUSB_IS_SUSPEND 0x0001 // SUSPEND Signaling Detected //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXMAXP5 register. +// The following are defines for the bit fields in the MUSB_O_IE register. // //***************************************************************************** -#define USB_RXMAXP5_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP5_MAXLOAD_S 0 +#define MUSB_IE_VBUSERR 0x0080 // Enable VBUS Error Interrupt (OTG only) +#define MUSB_IE_SESREQ 0x0040 // Enable Session Request (OTG only) +#define MUSB_IE_DISCON 0x0020 // Enable Disconnect Interrupt +#define MUSB_IE_CONN 0x0010 // Enable Connect Interrupt +#define MUSB_IE_SOF 0x0008 // Enable Start-of-Frame Interrupt +#define MUSB_IE_BABBLE 0x0004 // Enable Babble Interrupt +#define MUSB_IE_RESET 0x0004 // Enable RESET Interrupt +#define MUSB_IE_RESUME 0x0002 // Enable RESUME Interrupt +#define MUSB_IE_SUSPND 0x0001 // Enable SUSPEND Interrupt //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCSRL5 register. +// The following are defines for the bit fields in the MUSB_O_FRAME register. // //***************************************************************************** -#define USB_RXCSRL5_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL5_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL5_STALL 0x00000020 // Send STALL -#define USB_RXCSRL5_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL5_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL5_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL5_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL5_ERROR 0x00000004 // Error -#define USB_RXCSRL5_OVER 0x00000004 // Overrun -#define USB_RXCSRL5_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL5_RXRDY 0x00000001 // Receive Packet Ready +#define MUSB_FRAME_M 0x07FF // Frame Number +#define MUSB_FRAME_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCSRH5 register. +// The following are defines for the bit fields in the MUSB_O_TEST register. // //***************************************************************************** -#define USB_RXCSRH5_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH5_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH5_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH5_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH5_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH5_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH5_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH5_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH5_DT 0x00000002 // Data Toggle -#define USB_RXCSRH5_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status +#define MUSB_TEST_FORCEH 0x0080 // Force Host Mode +#define MUSB_TEST_FIFOACC 0x0040 // FIFO Access +#define MUSB_TEST_FORCEFS 0x0020 // Force Full-Speed Mode +#define MUSB_TEST_FORCEHS 0x0010 // Force High-Speed Mode +#define MUSB_TEST_TESTPKT 0x0008 // Test Packet Mode Enable +#define MUSB_TEST_TESTK 0x0004 // Test_K Mode Enable +#define MUSB_TEST_TESTJ 0x0002 // Test_J Mode Enable +#define MUSB_TEST_TESTSE0NAK 0x0001 // Test_SE0_NAK Test Mode Enable //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCOUNT5 register. +// The following are defines for the bit fields in the MUSB_O_DEVCTL register. // //***************************************************************************** -#define USB_RXCOUNT5_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT5_COUNT_S 0 +#define MUSB_DEVCTL_DEV 0x0080 // Device Mode (OTG only) +#define MUSB_DEVCTL_FSDEV 0x0040 // Full-Speed Device Detected +#define MUSB_DEVCTL_LSDEV 0x0020 // Low-Speed Device Detected +#define MUSB_DEVCTL_VBUS_M 0x0018 // VBUS Level (OTG only) +#define MUSB_DEVCTL_VBUS_NONE 0x0000 // Below SessionEnd +#define MUSB_DEVCTL_VBUS_SEND 0x0008 // Above SessionEnd, below AValid +#define MUSB_DEVCTL_VBUS_AVALID 0x0010 // Above AValid, below VBUSValid +#define MUSB_DEVCTL_VBUS_VALID 0x0018 // Above VBUSValid +#define MUSB_DEVCTL_HOST 0x0004 // Host Mode +#define MUSB_DEVCTL_HOSTREQ 0x0002 // Host Request (OTG only) +#define MUSB_DEVCTL_SESSION 0x0001 // Session Start/End (OTG only) //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXTYPE5 register. +// The following are defines for the bit fields in the MUSB_O_CCONF register. // //***************************************************************************** -#define USB_TXTYPE5_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE5_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE5_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE5_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE5_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE5_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE5_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE5_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE5_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE5_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE5_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE5_TEP_S 0 +#define MUSB_CCONF_TXEDMA 0x0002 // TX Early DMA Enable +#define MUSB_CCONF_RXEDMA 0x0001 // TX Early DMA Enable //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXINTERVAL5 +// The following are defines for the bit fields in the MUSB_O_ULPIVBUSCTL // register. // //***************************************************************************** -#define USB_TXINTERVAL5_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL5_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL5_NAKLMT_S \ - 0 -#define USB_TXINTERVAL5_TXPOLL_S \ - 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXTYPE5 register. -// -//***************************************************************************** -#define USB_RXTYPE5_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE5_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE5_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE5_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE5_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE5_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE5_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE5_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE5_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE5_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE5_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE5_TEP_S 0 +#define MUSB_ULPIVBUSCTL_USEEXTVBUSIND 0x0002 // Use External VBUS Indicator +#define MUSB_ULPIVBUSCTL_USEEXTVBUS 0x0001 // Use External VBUS //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXINTERVAL5 +// The following are defines for the bit fields in the MUSB_O_ULPIREGDATA // register. // //***************************************************************************** -#define USB_RXINTERVAL5_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL5_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL5_TXPOLL_S \ - 0 -#define USB_RXINTERVAL5_NAKLMT_S \ - 0 - +#define MUSB_ULPIREGDATA_REGDATA_M 0x00FF // Register Data +#define MUSB_ULPIREGDATA_REGDATA_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXMAXP6 register. -// -//***************************************************************************** -#define USB_TXMAXP6_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP6_MAXLOAD_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRL6 register. -// -//***************************************************************************** -#define USB_TXCSRL6_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL6_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL6_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL6_STALL 0x00000010 // Send STALL -#define USB_TXCSRL6_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL6_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL6_ERROR 0x00000004 // Error -#define USB_TXCSRL6_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL6_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL6_TXRDY 0x00000001 // Transmit Packet Ready - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXCSRH6 register. -// -//***************************************************************************** -#define USB_TXCSRH6_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH6_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH6_MODE 0x00000020 // Mode -#define USB_TXCSRH6_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH6_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH6_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH6_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH6_DT 0x00000001 // Data Toggle - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXMAXP6 register. -// -//***************************************************************************** -#define USB_RXMAXP6_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP6_MAXLOAD_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRL6 register. -// -//***************************************************************************** -#define USB_RXCSRL6_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL6_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL6_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL6_STALL 0x00000020 // Send STALL -#define USB_RXCSRL6_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL6_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL6_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL6_ERROR 0x00000004 // Error -#define USB_RXCSRL6_OVER 0x00000004 // Overrun -#define USB_RXCSRL6_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL6_RXRDY 0x00000001 // Receive Packet Ready - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCSRH6 register. -// -//***************************************************************************** -#define USB_RXCSRH6_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH6_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH6_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH6_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH6_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH6_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH6_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH6_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH6_DT 0x00000002 // Data Toggle -#define USB_RXCSRH6_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXCOUNT6 register. -// -//***************************************************************************** -#define USB_RXCOUNT6_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT6_COUNT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXTYPE6 register. -// -//***************************************************************************** -#define USB_TXTYPE6_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE6_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE6_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE6_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE6_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE6_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE6_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE6_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE6_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE6_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE6_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE6_TEP_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_TXINTERVAL6 +// The following are defines for the bit fields in the MUSB_O_ULPIREGADDR // register. // //***************************************************************************** -#define USB_TXINTERVAL6_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL6_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL6_TXPOLL_S \ - 0 -#define USB_TXINTERVAL6_NAKLMT_S \ - 0 +#define MUSB_ULPIREGADDR_ADDR_M 0x00FF // Register Address +#define MUSB_ULPIREGADDR_ADDR_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXTYPE6 register. -// -//***************************************************************************** -#define USB_RXTYPE6_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE6_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE6_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE6_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE6_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE6_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE6_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE6_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE6_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE6_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE6_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE6_TEP_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RXINTERVAL6 +// The following are defines for the bit fields in the MUSB_O_ULPIREGCTL // register. // //***************************************************************************** -#define USB_RXINTERVAL6_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL6_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL6_NAKLMT_S \ - 0 -#define USB_RXINTERVAL6_TXPOLL_S \ - 0 +#define MUSB_ULPIREGCTL_RDWR 0x0004 // Read/Write Control +#define MUSB_ULPIREGCTL_REGCMPLT 0x0002 // Register Access Complete +#define MUSB_ULPIREGCTL_REGACC 0x0001 // Initiate Register Access //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXMAXP7 register. +// The following are defines for the bit fields in the MUSB_O_EPINFO register. // //***************************************************************************** -#define USB_TXMAXP7_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_TXMAXP7_MAXLOAD_S 0 +#define MUSB_EPINFO_RXEP_M 0x00F0 // RX Endpoints +#define MUSB_EPINFO_TXEP_M 0x000F // TX Endpoints +#define MUSB_EPINFO_RXEP_S 4 +#define MUSB_EPINFO_TXEP_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXCSRL7 register. +// The following are defines for the bit fields in the MUSB_O_RAMINFO register. // //***************************************************************************** -#define USB_TXCSRL7_NAKTO 0x00000080 // NAK Timeout -#define USB_TXCSRL7_CLRDT 0x00000040 // Clear Data Toggle -#define USB_TXCSRL7_STALLED 0x00000020 // Endpoint Stalled -#define USB_TXCSRL7_STALL 0x00000010 // Send STALL -#define USB_TXCSRL7_SETUP 0x00000010 // Setup Packet -#define USB_TXCSRL7_FLUSH 0x00000008 // Flush FIFO -#define USB_TXCSRL7_ERROR 0x00000004 // Error -#define USB_TXCSRL7_UNDRN 0x00000004 // Underrun -#define USB_TXCSRL7_FIFONE 0x00000002 // FIFO Not Empty -#define USB_TXCSRL7_TXRDY 0x00000001 // Transmit Packet Ready +#define MUSB_RAMINFO_DMACHAN_M 0x00F0 // DMA Channels +#define MUSB_RAMINFO_RAMBITS_M 0x000F // RAM Address Bus Width +#define MUSB_RAMINFO_DMACHAN_S 4 +#define MUSB_RAMINFO_RAMBITS_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXCSRH7 register. +// The following are defines for the bit fields in the MUSB_O_CONTIM register. // //***************************************************************************** -#define USB_TXCSRH7_AUTOSET 0x00000080 // Auto Set -#define USB_TXCSRH7_ISO 0x00000040 // Isochronous Transfers -#define USB_TXCSRH7_MODE 0x00000020 // Mode -#define USB_TXCSRH7_DMAEN 0x00000010 // DMA Request Enable -#define USB_TXCSRH7_FDT 0x00000008 // Force Data Toggle -#define USB_TXCSRH7_DMAMOD 0x00000004 // DMA Request Mode -#define USB_TXCSRH7_DTWE 0x00000002 // Data Toggle Write Enable -#define USB_TXCSRH7_DT 0x00000001 // Data Toggle +#define MUSB_CONTIM_WTCON_M 0x00F0 // Connect Wait +#define MUSB_CONTIM_WTID_M 0x000F // Wait ID +#define MUSB_CONTIM_WTCON_S 4 +#define MUSB_CONTIM_WTID_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXMAXP7 register. +// The following are defines for the bit fields in the MUSB_O_VPLEN register. // //***************************************************************************** -#define USB_RXMAXP7_MAXLOAD_M 0x000007FF // Maximum Payload -#define USB_RXMAXP7_MAXLOAD_S 0 +#define MUSB_VPLEN_VPLEN_M 0x00FF // VBUS Pulse Length +#define MUSB_VPLEN_VPLEN_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCSRL7 register. +// The following are defines for the bit fields in the MUSB_O_HSEOF register. // //***************************************************************************** -#define USB_RXCSRL7_CLRDT 0x00000080 // Clear Data Toggle -#define USB_RXCSRL7_STALLED 0x00000040 // Endpoint Stalled -#define USB_RXCSRL7_REQPKT 0x00000020 // Request Packet -#define USB_RXCSRL7_STALL 0x00000020 // Send STALL -#define USB_RXCSRL7_FLUSH 0x00000010 // Flush FIFO -#define USB_RXCSRL7_DATAERR 0x00000008 // Data Error -#define USB_RXCSRL7_NAKTO 0x00000008 // NAK Timeout -#define USB_RXCSRL7_ERROR 0x00000004 // Error -#define USB_RXCSRL7_OVER 0x00000004 // Overrun -#define USB_RXCSRL7_FULL 0x00000002 // FIFO Full -#define USB_RXCSRL7_RXRDY 0x00000001 // Receive Packet Ready +#define MUSB_HSEOF_HSEOFG_M 0x00FF // HIgh-Speed End-of-Frame Gap +#define MUSB_HSEOF_HSEOFG_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCSRH7 register. +// The following are defines for the bit fields in the MUSB_O_FSEOF register. // //***************************************************************************** -#define USB_RXCSRH7_AUTOCL 0x00000080 // Auto Clear -#define USB_RXCSRH7_ISO 0x00000040 // Isochronous Transfers -#define USB_RXCSRH7_AUTORQ 0x00000040 // Auto Request -#define USB_RXCSRH7_DMAEN 0x00000020 // DMA Request Enable -#define USB_RXCSRH7_PIDERR 0x00000010 // PID Error -#define USB_RXCSRH7_DISNYET 0x00000010 // Disable NYET -#define USB_RXCSRH7_DMAMOD 0x00000008 // DMA Request Mode -#define USB_RXCSRH7_DTWE 0x00000004 // Data Toggle Write Enable -#define USB_RXCSRH7_DT 0x00000002 // Data Toggle -#define USB_RXCSRH7_INCOMPRX 0x00000001 // Incomplete RX Transmission - // Status +#define MUSB_FSEOF_FSEOFG_M 0x00FF // Full-Speed End-of-Frame Gap +#define MUSB_FSEOF_FSEOFG_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXCOUNT7 register. +// The following are defines for the bit fields in the MUSB_O_LSEOF register. // //***************************************************************************** -#define USB_RXCOUNT7_COUNT_M 0x00001FFF // Receive Packet Count -#define USB_RXCOUNT7_COUNT_S 0 +#define MUSB_LSEOF_LSEOFG_M 0x00FF // Low-Speed End-of-Frame Gap +#define MUSB_LSEOF_LSEOFG_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXTYPE7 register. +// The following are defines for the bit fields in the MUSB_O_CSRL0 register. // //***************************************************************************** -#define USB_TXTYPE7_SPEED_M 0x000000C0 // Operating Speed -#define USB_TXTYPE7_SPEED_DFLT 0x00000000 // Default -#define USB_TXTYPE7_SPEED_HIGH 0x00000040 // High -#define USB_TXTYPE7_SPEED_FULL 0x00000080 // Full -#define USB_TXTYPE7_SPEED_LOW 0x000000C0 // Low -#define USB_TXTYPE7_PROTO_M 0x00000030 // Protocol -#define USB_TXTYPE7_PROTO_CTRL 0x00000000 // Control -#define USB_TXTYPE7_PROTO_ISOC 0x00000010 // Isochronous -#define USB_TXTYPE7_PROTO_BULK 0x00000020 // Bulk -#define USB_TXTYPE7_PROTO_INT 0x00000030 // Interrupt -#define USB_TXTYPE7_TEP_M 0x0000000F // Target Endpoint Number -#define USB_TXTYPE7_TEP_S 0 +#define MUSB_CSRL0_NAKTO 0x0080 // NAK Timeout +#define MUSB_CSRL0_SETENDC 0x0080 // Setup End Clear +#define MUSB_CSRL0_STATUS 0x0040 // STATUS Packet +#define MUSB_CSRL0_RXRDYC 0x0040 // RXRDY Clear +#define MUSB_CSRL0_REQPKT 0x0020 // Request Packet +#define MUSB_CSRL0_STALL 0x0020 // Send Stall +#define MUSB_CSRL0_SETEND 0x0010 // Setup End +#define MUSB_CSRL0_ERROR 0x0010 // Error +#define MUSB_CSRL0_DATAEND 0x0008 // Data End +#define MUSB_CSRL0_SETUP 0x0008 // Setup Packet +#define MUSB_CSRL0_STALLED 0x0004 // Endpoint Stalled +#define MUSB_CSRL0_TXRDY 0x0002 // Transmit Packet Ready +#define MUSB_CSRL0_RXRDY 0x0001 // Receive Packet Ready //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXINTERVAL7 -// register. +// The following are defines for the bit fields in the MUSB_O_CSRH0 register. // //***************************************************************************** -#define USB_TXINTERVAL7_TXPOLL_M \ - 0x000000FF // TX Polling -#define USB_TXINTERVAL7_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_TXINTERVAL7_NAKLMT_S \ - 0 -#define USB_TXINTERVAL7_TXPOLL_S \ - 0 +#define MUSB_CSRH0_DISPING 0x0008 // PING Disable +#define MUSB_CSRH0_DTWE 0x0004 // Data Toggle Write Enable +#define MUSB_CSRH0_DT 0x0002 // Data Toggle +#define MUSB_CSRH0_FLUSH 0x0001 // Flush FIFO //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXTYPE7 register. +// The following are defines for the bit fields in the MUSB_O_TYPE0 register. // //***************************************************************************** -#define USB_RXTYPE7_SPEED_M 0x000000C0 // Operating Speed -#define USB_RXTYPE7_SPEED_DFLT 0x00000000 // Default -#define USB_RXTYPE7_SPEED_HIGH 0x00000040 // High -#define USB_RXTYPE7_SPEED_FULL 0x00000080 // Full -#define USB_RXTYPE7_SPEED_LOW 0x000000C0 // Low -#define USB_RXTYPE7_PROTO_M 0x00000030 // Protocol -#define USB_RXTYPE7_PROTO_CTRL 0x00000000 // Control -#define USB_RXTYPE7_PROTO_ISOC 0x00000010 // Isochronous -#define USB_RXTYPE7_PROTO_BULK 0x00000020 // Bulk -#define USB_RXTYPE7_PROTO_INT 0x00000030 // Interrupt -#define USB_RXTYPE7_TEP_M 0x0000000F // Target Endpoint Number -#define USB_RXTYPE7_TEP_S 0 +#define MUSB_TYPE0_SPEED_M 0x00C0 // Operating Speed +#define MUSB_TYPE0_SPEED_HIGH 0x0040 // High +#define MUSB_TYPE0_SPEED_FULL 0x0080 // Full +#define MUSB_TYPE0_SPEED_LOW 0x00C0 // Low //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXINTERVAL7 -// register. -// -//***************************************************************************** -#define USB_RXINTERVAL7_TXPOLL_M \ - 0x000000FF // RX Polling -#define USB_RXINTERVAL7_NAKLMT_M \ - 0x000000FF // NAK Limit -#define USB_RXINTERVAL7_NAKLMT_S \ - 0 -#define USB_RXINTERVAL7_TXPOLL_S \ - 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAINTR register. -// -//***************************************************************************** -#define USB_DMAINTR_CH7 0x00000080 // Channel 7 DMA Interrupt -#define USB_DMAINTR_CH6 0x00000040 // Channel 6 DMA Interrupt -#define USB_DMAINTR_CH5 0x00000020 // Channel 5 DMA Interrupt -#define USB_DMAINTR_CH4 0x00000010 // Channel 4 DMA Interrupt -#define USB_DMAINTR_CH3 0x00000008 // Channel 3 DMA Interrupt -#define USB_DMAINTR_CH2 0x00000004 // Channel 2 DMA Interrupt -#define USB_DMAINTR_CH1 0x00000002 // Channel 1 DMA Interrupt -#define USB_DMAINTR_CH0 0x00000001 // Channel 0 DMA Interrupt - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACTL0 register. -// -//***************************************************************************** -#define USB_DMACTL0_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL0_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL0_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL0_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL0_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL0_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL0_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL0_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL0_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL0_DIR 0x00000002 // DMA Direction -#define USB_DMACTL0_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL0_EP_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAADDR0 register. -// -//***************************************************************************** -#define USB_DMAADDR0_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR0_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT0 -// register. -// -//***************************************************************************** -#define USB_DMACOUNT0_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT0_COUNT_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACTL1 register. -// -//***************************************************************************** -#define USB_DMACTL1_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL1_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL1_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL1_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL1_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL1_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL1_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL1_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL1_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL1_DIR 0x00000002 // DMA Direction -#define USB_DMACTL1_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL1_EP_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAADDR1 register. -// -//***************************************************************************** -#define USB_DMAADDR1_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR1_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT1 -// register. -// -//***************************************************************************** -#define USB_DMACOUNT1_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT1_COUNT_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACTL2 register. -// -//***************************************************************************** -#define USB_DMACTL2_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL2_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL2_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL2_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL2_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL2_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL2_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL2_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL2_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL2_DIR 0x00000002 // DMA Direction -#define USB_DMACTL2_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL2_EP_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAADDR2 register. -// -//***************************************************************************** -#define USB_DMAADDR2_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR2_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT2 -// register. -// -//***************************************************************************** -#define USB_DMACOUNT2_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT2_COUNT_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACTL3 register. +// The following are defines for the bit fields in the MUSB_O_NAKLMT register. // //***************************************************************************** -#define USB_DMACTL3_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL3_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL3_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL3_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL3_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL3_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL3_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL3_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL3_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL3_DIR 0x00000002 // DMA Direction -#define USB_DMACTL3_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL3_EP_S 4 +#define MUSB_NAKLMT_NAKLMT_M 0x001F // EP0 NAK Limit +#define MUSB_NAKLMT_NAKLMT_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMAADDR3 register. +// The following are defines for the bit fields in the MUSB_O_TXCSRL1 register. // //***************************************************************************** -#define USB_DMAADDR3_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR3_ADDR_S 2 +#define MUSB_TXCSRL1_NAKTO 0x0080 // NAK Timeout +#define MUSB_TXCSRL1_CLRDT 0x0040 // Clear Data Toggle +#define MUSB_TXCSRL1_STALLED 0x0020 // Endpoint Stalled +#define MUSB_TXCSRL1_STALL 0x0010 // Send STALL +#define MUSB_TXCSRL1_SETUP 0x0010 // Setup Packet +#define MUSB_TXCSRL1_FLUSH 0x0008 // Flush FIFO +#define MUSB_TXCSRL1_ERROR 0x0004 // Error +#define MUSB_TXCSRL1_UNDRN 0x0004 // Underrun +#define MUSB_TXCSRL1_FIFONE 0x0002 // FIFO Not Empty +#define MUSB_TXCSRL1_TXRDY 0x0001 // Transmit Packet Ready //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACOUNT3 -// register. +// The following are defines for the bit fields in the MUSB_O_TXCSRH1 register. // //***************************************************************************** -#define USB_DMACOUNT3_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT3_COUNT_S 2 +#define MUSB_TXCSRH1_AUTOSET 0x0080 // Auto Set +#define MUSB_TXCSRH1_ISO 0x0040 // Isochronous Transfers +#define MUSB_TXCSRH1_MODE 0x0020 // Mode +#define MUSB_TXCSRH1_DMAEN 0x0010 // DMA Request Enable +#define MUSB_TXCSRH1_FDT 0x0008 // Force Data Toggle +#define MUSB_TXCSRH1_DMAMOD 0x0004 // DMA Request Mode +#define MUSB_TXCSRH1_DTWE 0x0002 // Data Toggle Write Enable +#define MUSB_TXCSRH1_DT 0x0001 // Data Toggle //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACTL4 register. +// The following are defines for the bit fields in the MUSB_O_RXCSRL1 register. // //***************************************************************************** -#define USB_DMACTL4_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL4_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL4_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL4_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL4_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL4_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL4_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL4_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL4_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL4_DIR 0x00000002 // DMA Direction -#define USB_DMACTL4_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL4_EP_S 4 +#define MUSB_RXCSRL1_CLRDT 0x0080 // Clear Data Toggle +#define MUSB_RXCSRL1_STALLED 0x0040 // Endpoint Stalled +#define MUSB_RXCSRL1_STALL 0x0020 // Send STALL +#define MUSB_RXCSRL1_REQPKT 0x0020 // Request Packet +#define MUSB_RXCSRL1_FLUSH 0x0010 // Flush FIFO +#define MUSB_RXCSRL1_DATAERR 0x0008 // Data Error +#define MUSB_RXCSRL1_NAKTO 0x0008 // NAK Timeout +#define MUSB_RXCSRL1_OVER 0x0004 // Overrun +#define MUSB_RXCSRL1_ERROR 0x0004 // Error +#define MUSB_RXCSRL1_FULL 0x0002 // FIFO Full +#define MUSB_RXCSRL1_RXRDY 0x0001 // Receive Packet Ready //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMAADDR4 register. +// The following are defines for the bit fields in the MUSB_O_RXCSRH1 register. // //***************************************************************************** -#define USB_DMAADDR4_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR4_ADDR_S 2 +#define MUSB_RXCSRH1_AUTOCL 0x0080 // Auto Clear +#define MUSB_RXCSRH1_AUTORQ 0x0040 // Auto Request +#define MUSB_RXCSRH1_ISO 0x0040 // Isochronous Transfers +#define MUSB_RXCSRH1_DMAEN 0x0020 // DMA Request Enable +#define MUSB_RXCSRH1_DISNYET 0x0010 // Disable NYET +#define MUSB_RXCSRH1_PIDERR 0x0010 // PID Error +#define MUSB_RXCSRH1_DMAMOD 0x0008 // DMA Request Mode +#define MUSB_RXCSRH1_DTWE 0x0004 // Data Toggle Write Enable +#define MUSB_RXCSRH1_DT 0x0002 // Data Toggle +#define MUSB_RXCSRH1_INCOMPRX 0x0001 // Incomplete RX Transmission Status //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACOUNT4 -// register. +// The following are defines for the bit fields in the MUSB_O_TXTYPE1 register. // //***************************************************************************** -#define USB_DMACOUNT4_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT4_COUNT_S 2 +#define MUSB_TXTYPE1_SPEED_M 0x00C0 // Operating Speed +#define MUSB_TXTYPE1_SPEED_DFLT 0x0000 // Default +#define MUSB_TXTYPE1_SPEED_HIGH 0x0040 // High +#define MUSB_TXTYPE1_SPEED_FULL 0x0080 // Full +#define MUSB_TXTYPE1_SPEED_LOW 0x00C0 // Low +#define MUSB_TXTYPE1_PROTO_M 0x0030 // Protocol +#define MUSB_TXTYPE1_PROTO_CTRL 0x0000 // Control +#define MUSB_TXTYPE1_PROTO_ISOC 0x0010 // Isochronous +#define MUSB_TXTYPE1_PROTO_BULK 0x0020 // Bulk +#define MUSB_TXTYPE1_PROTO_INT 0x0030 // Interrupt +#define MUSB_TXTYPE1_TEP_M 0x000F // Target Endpoint Number +#define MUSB_TXTYPE1_TEP_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACTL5 register. -// -//***************************************************************************** -#define USB_DMACTL5_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL5_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL5_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL5_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL5_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL5_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL5_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL5_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL5_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL5_DIR 0x00000002 // DMA Direction -#define USB_DMACTL5_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL5_EP_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAADDR5 register. -// -//***************************************************************************** -#define USB_DMAADDR5_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR5_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT5 +// The following are defines for the bit fields in the MUSB_O_TXINTERVAL1 // register. // //***************************************************************************** -#define USB_DMACOUNT5_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT5_COUNT_S 2 +#define MUSB_TXINTERVAL1_NAKLMT_M 0x00FF // NAK Limit +#define MUSB_TXINTERVAL1_TXPOLL_M 0x00FF // TX Polling +#define MUSB_TXINTERVAL1_TXPOLL_S 0 +#define MUSB_TXINTERVAL1_NAKLMT_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACTL6 register. +// The following are defines for the bit fields in the MUSB_O_RXTYPE1 register. // //***************************************************************************** -#define USB_DMACTL6_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL6_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL6_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL6_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified - // length -#define USB_DMACTL6_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or - // unspecified length -#define USB_DMACTL6_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL6_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL6_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL6_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL6_DIR 0x00000002 // DMA Direction -#define USB_DMACTL6_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL6_EP_S 4 +#define MUSB_RXTYPE1_SPEED_M 0x00C0 // Operating Speed +#define MUSB_RXTYPE1_SPEED_DFLT 0x0000 // Default +#define MUSB_RXTYPE1_SPEED_HIGH 0x0040 // High +#define MUSB_RXTYPE1_SPEED_FULL 0x0080 // Full +#define MUSB_RXTYPE1_SPEED_LOW 0x00C0 // Low +#define MUSB_RXTYPE1_PROTO_M 0x0030 // Protocol +#define MUSB_RXTYPE1_PROTO_CTRL 0x0000 // Control +#define MUSB_RXTYPE1_PROTO_ISOC 0x0010 // Isochronous +#define MUSB_RXTYPE1_PROTO_BULK 0x0020 // Bulk +#define MUSB_RXTYPE1_PROTO_INT 0x0030 // Interrupt +#define MUSB_RXTYPE1_TEP_M 0x000F // Target Endpoint Number +#define MUSB_RXTYPE1_TEP_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMAADDR6 register. -// -//***************************************************************************** -#define USB_DMAADDR6_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR6_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT6 +// The following are defines for the bit fields in the MUSB_O_RXINTERVAL1 // register. // //***************************************************************************** -#define USB_DMACOUNT6_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT6_COUNT_S 2 +#define MUSB_RXINTERVAL1_TXPOLL_M 0x00FF // RX Polling +#define MUSB_RXINTERVAL1_NAKLMT_M 0x00FF // NAK Limit +#define MUSB_RXINTERVAL1_TXPOLL_S 0 +#define MUSB_RXINTERVAL1_NAKLMT_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_DMACTL7 register. +// The following are defines for the bit fields in the MUSB_O_DMACTL0 register. // //***************************************************************************** -#define USB_DMACTL7_BRSTM_M 0x00000600 // Burst Mode -#define USB_DMACTL7_BRSTM_ANY 0x00000000 // Bursts of unspecified length -#define USB_DMACTL7_BRSTM_INC4 0x00000200 // INCR4 or unspecified length -#define USB_DMACTL7_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified +#define MUSB_DMACTL0_BRSTM_M 0x0600 // Burst Mode +#define MUSB_DMACTL0_BRSTM_ANY 0x0000 // Bursts of unspecified length +#define MUSB_DMACTL0_BRSTM_INC4 0x0200 // INCR4 or unspecified length +#define MUSB_DMACTL0_BRSTM_INC8 0x0400 // INCR8, INCR4 or unspecified // length -#define USB_DMACTL7_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or +#define MUSB_DMACTL0_BRSTM_INC16 0x0600 // INCR16, INCR8, INCR4 or // unspecified length -#define USB_DMACTL7_ERR 0x00000100 // Bus Error Bit -#define USB_DMACTL7_EP_M 0x000000F0 // Endpoint number -#define USB_DMACTL7_IE 0x00000008 // DMA Interrupt Enable -#define USB_DMACTL7_MODE 0x00000004 // DMA Transfer Mode -#define USB_DMACTL7_DIR 0x00000002 // DMA Direction -#define USB_DMACTL7_ENABLE 0x00000001 // DMA Transfer Enable -#define USB_DMACTL7_EP_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMAADDR7 register. -// -//***************************************************************************** -#define USB_DMAADDR7_ADDR_M 0xFFFFFFFC // DMA Address -#define USB_DMAADDR7_ADDR_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DMACOUNT7 -// register. -// -//***************************************************************************** -#define USB_DMACOUNT7_COUNT_M 0xFFFFFFFC // DMA Count -#define USB_DMACOUNT7_COUNT_S 2 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT1 -// register. -// -//***************************************************************************** -#define USB_RQPKTCOUNT1_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT1_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT2 -// register. -// -//***************************************************************************** -#define USB_RQPKTCOUNT2_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT2_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT3 -// register. -// -//***************************************************************************** -#define USB_RQPKTCOUNT3_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT3_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT4 -// register. -// -//***************************************************************************** -#define USB_RQPKTCOUNT4_COUNT_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT4_COUNT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT5 -// register. -// -//***************************************************************************** -#define USB_RQPKTCOUNT5_COUNT_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT5_COUNT_S 0 +#define MUSB_DMACTL0_ERR 0x0100 // Bus Error Bit +#define MUSB_DMACTL0_EP_M 0x00F0 // Endpoint number +#define MUSB_DMACTL0_IE 0x0008 // DMA Interrupt Enable +#define MUSB_DMACTL0_MODE 0x0004 // DMA Transfer Mode +#define MUSB_DMACTL0_DIR 0x0002 // DMA Direction +#define MUSB_DMACTL0_ENABLE 0x0001 // DMA Transfer Enable +#define MUSB_DMACTL0_EP_S 4 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT6 -// register. +// The following are defines for the bit fields in the MUSB_O_DMAADDR0 register. // //***************************************************************************** -#define USB_RQPKTCOUNT6_COUNT_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT6_COUNT_S 0 +#define MUSB_DMAADDR0_ADDR_M 0xFFFFFFFC // DMA Address +#define MUSB_DMAADDR0_ADDR_S 2 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RQPKTCOUNT7 +// The following are defines for the bit fields in the MUSB_O_DMACOUNT0 // register. // //***************************************************************************** -#define USB_RQPKTCOUNT7_COUNT_M 0x0000FFFF // Block Transfer Packet Count -#define USB_RQPKTCOUNT7_COUNT_S 0 +#define MUSB_DMACOUNT0_COUNT_M 0xFFFFFFFC // DMA Count +#define MUSB_DMACOUNT0_COUNT_S 2 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_RXDPKTBUFDIS -// register. +// The following are defines for the bit fields in the MUSB_O_CTO register. // //***************************************************************************** -#define USB_RXDPKTBUFDIS_EP7 0x00000080 // EP7 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP6 0x00000040 // EP6 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP5 0x00000020 // EP5 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP4 0x00000010 // EP4 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP3 0x00000008 // EP3 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP2 0x00000004 // EP2 RX Double-Packet Buffer - // Disable -#define USB_RXDPKTBUFDIS_EP1 0x00000002 // EP1 RX Double-Packet Buffer - // Disable +#define MUSB_CTO_CCTV_M 0xFFFF // Configurable Chirp Timeout Value +#define MUSB_CTO_CCTV_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_TXDPKTBUFDIS -// register. +// The following are defines for the bit fields in the MUSB_O_HHSRTN register. // //***************************************************************************** -#define USB_TXDPKTBUFDIS_EP7 0x00000080 // EP7 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP6 0x00000040 // EP6 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP5 0x00000020 // EP5 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP4 0x00000010 // EP4 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP3 0x00000008 // EP3 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP2 0x00000004 // EP2 TX Double-Packet Buffer - // Disable -#define USB_TXDPKTBUFDIS_EP1 0x00000002 // EP1 TX Double-Packet Buffer - // Disable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_CTO register. -// -//***************************************************************************** -#define USB_CTO_CCTV_M 0x0000FFFF // Configurable Chirp Timeout Value -#define USB_CTO_CCTV_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_HHSRTN register. -// -//***************************************************************************** -#define USB_HHSRTN_HHSRTN_M 0x0000FFFF // HIgh Speed to UTM Operating +#define MUSB_HHSRTN_HHSRTN_M 0xFFFF // HIgh Speed to UTM Operating // Delay -#define USB_HHSRTN_HHSRTN_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_HSBT register. -// -//***************************************************************************** -#define USB_HSBT_HSBT_M 0x0000000F // High Speed Timeout Adder -#define USB_HSBT_HSBT_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LPMATTR register. -// -//***************************************************************************** -#define USB_LPMATTR_ENDPT_M 0x0000F000 // Endpoint -#define USB_LPMATTR_RMTWAK 0x00000100 // Remote Wake -#define USB_LPMATTR_HIRD_M 0x000000F0 // Host Initiated Resume Duration -#define USB_LPMATTR_LS_M 0x0000000F // Link State -#define USB_LPMATTR_LS_L1 0x00000001 // Sleep State (L1) -#define USB_LPMATTR_ENDPT_S 12 -#define USB_LPMATTR_HIRD_S 4 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LPMCNTRL register. -// -//***************************************************************************** -#define USB_LPMCNTRL_NAK 0x00000010 // LPM NAK -#define USB_LPMCNTRL_EN_M 0x0000000C // LPM Enable -#define USB_LPMCNTRL_EN_NONE 0x00000000 // LPM and Extended transactions - // are not supported. In this case, - // the USB does not respond to LPM - // transactions and LPM - // transactions cause a timeout -#define USB_LPMCNTRL_EN_EXT 0x00000004 // LPM is not supported but - // extended transactions are - // supported. In this case, the USB - // does respond to an LPM - // transaction with a STALL -#define USB_LPMCNTRL_EN_LPMEXT 0x0000000C // The USB supports LPM extended - // transactions. In this case, the - // USB responds with a NYET or an - // ACK as determined by the value - // of TXLPM and other conditions -#define USB_LPMCNTRL_RES 0x00000002 // LPM Resume -#define USB_LPMCNTRL_TXLPM 0x00000001 // Transmit LPM Transaction Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LPMIM register. -// -//***************************************************************************** -#define USB_LPMIM_ERR 0x00000020 // LPM Error Interrupt Mask -#define USB_LPMIM_RES 0x00000010 // LPM Resume Interrupt Mask -#define USB_LPMIM_NC 0x00000008 // LPM NC Interrupt Mask -#define USB_LPMIM_ACK 0x00000004 // LPM ACK Interrupt Mask -#define USB_LPMIM_NY 0x00000002 // LPM NY Interrupt Mask -#define USB_LPMIM_STALL 0x00000001 // LPM STALL Interrupt Mask - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LPMRIS register. -// -//***************************************************************************** -#define USB_LPMRIS_ERR 0x00000020 // LPM Interrupt Status -#define USB_LPMRIS_RES 0x00000010 // LPM Resume Interrupt Status -#define USB_LPMRIS_NC 0x00000008 // LPM NC Interrupt Status -#define USB_LPMRIS_ACK 0x00000004 // LPM ACK Interrupt Status -#define USB_LPMRIS_NY 0x00000002 // LPM NY Interrupt Status -#define USB_LPMRIS_LPMST 0x00000001 // LPM STALL Interrupt Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_LPMFADDR register. -// -//***************************************************************************** -#define USB_LPMFADDR_ADDR_M 0x0000007F // LPM Function Address -#define USB_LPMFADDR_ADDR_S 0 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPC register. -// -//***************************************************************************** -#define USB_EPC_PFLTACT_M 0x00000300 // Power Fault Action -#define USB_EPC_PFLTACT_UNCHG 0x00000000 // Unchanged -#define USB_EPC_PFLTACT_TRIS 0x00000100 // Tristate -#define USB_EPC_PFLTACT_LOW 0x00000200 // Low -#define USB_EPC_PFLTACT_HIGH 0x00000300 // High -#define USB_EPC_PFLTAEN 0x00000040 // Power Fault Action Enable -#define USB_EPC_PFLTSEN_HIGH 0x00000020 // Power Fault Sense -#define USB_EPC_PFLTEN 0x00000010 // Power Fault Input Enable -#define USB_EPC_EPENDE 0x00000004 // EPEN Drive Enable -#define USB_EPC_EPEN_M 0x00000003 // External Power Supply Enable - // Configuration -#define USB_EPC_EPEN_LOW 0x00000000 // Power Enable Active Low -#define USB_EPC_EPEN_HIGH 0x00000001 // Power Enable Active High -#define USB_EPC_EPEN_VBLOW 0x00000002 // Power Enable High if VBUS Low - // (OTG only) -#define USB_EPC_EPEN_VBHIGH 0x00000003 // Power Enable High if VBUS High - // (OTG only) - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPCRIS register. -// -//***************************************************************************** -#define USB_EPCRIS_PF 0x00000001 // USB Power Fault Interrupt Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPCIM register. -// -//***************************************************************************** -#define USB_EPCIM_PF 0x00000001 // USB Power Fault Interrupt Mask - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_EPCISC register. -// -//***************************************************************************** -#define USB_EPCISC_PF 0x00000001 // USB Power Fault Interrupt Status - // and Clear - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DRRIS register. -// -//***************************************************************************** -#define USB_DRRIS_RESUME 0x00000001 // RESUME Interrupt Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DRIM register. -// -//***************************************************************************** -#define USB_DRIM_RESUME 0x00000001 // RESUME Interrupt Mask - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_DRISC register. -// -//***************************************************************************** -#define USB_DRISC_RESUME 0x00000001 // RESUME Interrupt Status and - // Clear - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_GPCS register. -// -//***************************************************************************** -#define USB_GPCS_DEVMOD_M 0x00000007 // Device Mode -#define USB_GPCS_DEVMOD_OTG 0x00000000 // Use USB0VBUS and USB0ID pin -#define USB_GPCS_DEVMOD_HOST 0x00000002 // Force USB0VBUS and USB0ID low -#define USB_GPCS_DEVMOD_DEV 0x00000003 // Force USB0VBUS and USB0ID high -#define USB_GPCS_DEVMOD_HOSTVBUS \ - 0x00000004 // Use USB0VBUS and force USB0ID - // low -#define USB_GPCS_DEVMOD_DEVVBUS 0x00000005 // Use USB0VBUS and force USB0ID - // high - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_VDC register. -// -//***************************************************************************** -#define USB_VDC_VBDEN 0x00000001 // VBUS Droop Enable - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_VDCRIS register. -// -//***************************************************************************** -#define USB_VDCRIS_VD 0x00000001 // VBUS Droop Raw Interrupt Status - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_VDCIM register. -// -//***************************************************************************** -#define USB_VDCIM_VD 0x00000001 // VBUS Droop Interrupt Mask - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_VDCISC register. -// -//***************************************************************************** -#define USB_VDCISC_VD 0x00000001 // VBUS Droop Interrupt Status and - // Clear - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_PP register. -// -//***************************************************************************** -#define USB_PP_ECNT_M 0x0000FF00 // Endpoint Count -#define USB_PP_USB_M 0x000000C0 // USB Capability -#define USB_PP_USB_DEVICE 0x00000040 // DEVICE -#define USB_PP_USB_HOSTDEVICE 0x00000080 // HOST -#define USB_PP_USB_OTG 0x000000C0 // OTG -#define USB_PP_ULPI 0x00000020 // ULPI Present -#define USB_PP_PHY 0x00000010 // PHY Present -#define USB_PP_TYPE_M 0x0000000F // Controller Type -#define USB_PP_TYPE_0 0x00000000 // The first-generation USB - // controller -#define USB_PP_TYPE_1 0x00000001 // The second-generation USB - // controller revision -#define USB_PP_ECNT_S 8 - -//***************************************************************************** -// -// The following are defines for the bit fields in the USB_O_PC register. -// -//***************************************************************************** -#define USB_PC_ULPIEN 0x00010000 // ULPI Enable +#define MUSB_HHSRTN_HHSRTN_S 0 //***************************************************************************** // -// The following are defines for the bit fields in the USB_O_CC register. +// The following are defines for the bit fields in the MUSB_O_HSBT register. // //***************************************************************************** -#define USB_CC_CLKEN 0x00000200 // USB Clock Enable -#define USB_CC_CSD 0x00000100 // Clock Source/Direction -#define USB_CC_CLKDIV_M 0x0000000F // PLL Clock Divisor -#define USB_CC_CLKDIV_S 0 +#define MUSB_HSBT_HSBT_M 0x000F // High Speed Timeout Adder +#define MUSB_HSBT_HSBT_S 0 #ifdef __cplusplus } diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index e3fa51e31..a15431937 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -277,6 +277,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; (void) ep_addr; + // TODO implement dcd_edpt_close() +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index b880c2870..75b29faf3 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -335,6 +335,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; (void) ep_addr; + // TODO implement dcd_edpt_close() +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cff328418..6eea1ab32 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -4,7 +4,6 @@ * Copyright (c) 2019 Nathan Conrad * * Portions: - * Copyright (c) 2016 STMicroelectronics * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2022 Simon Küppers (skuep) * Copyright (c) 2022 HiFiPhile @@ -114,8 +113,6 @@ #include "device/dcd.h" #if defined(TUP_USBIP_FSDEV_STM32) - // Undefine to reduce the dependence on HAL - #undef USE_HAL_DRIVER #include "fsdev_stm32.h" #elif defined(TUP_USBIP_FSDEV_CH32) #include "fsdev_ch32.h" @@ -126,12 +123,6 @@ #include "fsdev_type.h" //--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ - - - -//--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -155,7 +146,6 @@ typedef struct { static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; - static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ @@ -165,7 +155,7 @@ static uint8_t remoteWakeCountdown; // When wake is requested // into the stack. static void handle_bus_reset(uint8_t rhport); static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); -static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir); +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location @@ -179,6 +169,10 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy static void edpt0_open(uint8_t rhport); +TU_ATTR_ALWAYS_INLINE static inline void edpt0_prepare_setup(void) { + btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); +} + //--------------------------------------------------------------------+ // Inline helper //--------------------------------------------------------------------+ @@ -220,10 +214,11 @@ void dcd_init(uint8_t rhport) { // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. - ep_write(i, 0u); + ep_write(i, 0u, false); } - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | + USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; handle_bus_reset(rhport); // Enable pull-up if supported @@ -279,13 +274,9 @@ static void handle_bus_reset(uint8_t rhport) { // Handle CTR interrupt for the TX/IN direction static void handle_ctr_tx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) & USB_EPREG_MASK; - - // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? - TU_VERIFY(ep_reg & USB_EP_CTR_TX, ); + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - uint8_t ep_addr = (ep_reg & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { @@ -301,123 +292,81 @@ static void handle_ctr_tx(uint32_t ep_id) { } if (xfer->total_len != xfer->queued_len) { - dcd_transmit_packet(xfer, ep_id); // also clear CTR bit + dcd_transmit_packet(xfer, ep_id); } else { - dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } +} + +static void handle_ctr_setup(uint32_t ep_id) { + uint16_t rx_count = btable_get_count(ep_id, BTABLE_BUF_RX); + uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); + + dcd_read_packet_memory(setup_packet, rx_addr, rx_count); - // Clear CTR TX and reserved CTR RX - ep_reg = (ep_reg & ~USB_EP_CTR_TX) | USB_EP_CTR_RX; + // Clear CTR RX if another setup packet arrived before this, it will be discarded + ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); - ep_write(ep_id, ep_reg); + // Setup packet should always be 8 bytes. If not, we probably missed the packet + if (rx_count == 8) { + dcd_event_setup_received(0, (uint8_t*) setup_packet, true); + // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 + } else { + // Missed setup packet !!! + TU_BREAKPOINT(); + edpt0_prepare_setup(); } } // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { -#ifdef FSDEV_BUS_32BIT - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code - * also takes time, so we'll wait 60 cycles (count = 20). - * - Since Low Speed mode is not supported/popular, we will ignore it for now. - * - * Note: this errata also seems to apply to G0, U5, H5 etc. - */ - volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } -#endif - - uint32_t ep_reg = ep_read(ep_id); - - // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? - TU_VERIFY(ep_reg & USB_EP_CTR_RX, ); - ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; // Clear CTR RX and reserved CTR TX - + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; + bool const is_iso = ep_is_iso(ep_reg); + xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); - if (ep_reg & USB_EP_SETUP) { - uint32_t count = btable_get_count(ep_id, BTABLE_BUF_RX); - // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) { - uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); - uint32_t setup_packet[2]; - dcd_read_packet_memory(setup_packet, rx_addr, 8); - dcd_event_setup_received(0, (uint8_t*) setup_packet, true); - - // Reset EP to NAK (in case it had been stalling) - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + uint8_t buf_id; + if (is_iso) { + buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered + } else { + buf_id = BTABLE_BUF_RX; + } + uint16_t const rx_count = btable_get_count(ep_id, buf_id); + uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); - ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_IN, 1); - ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_OUT, 1); - } else { - ep_reg &= USB_EPREG_MASK; // reversed all toggle - } + if (xfer->ff) { + dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); } else { - ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status + dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); + } + xfer->queued_len += rx_count; - bool const is_iso = ep_is_iso(ep_reg); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); + if ((rx_count < xfer->max_packet_size) || (xfer->queued_len >= xfer->total_len)) { + // all bytes received or short packet - uint8_t buf_id; - if (is_iso) { - buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered - } else { - buf_id = BTABLE_BUF_RX; - } - uint32_t rx_count = btable_get_count(ep_id, buf_id); - uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); + // For ch32v203: reset rx bufsize to mps to prevent race condition to cause PMAOVR (occurs with msc write10) + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, xfer->max_packet_size); - if (rx_count != 0) { - if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); - } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); - } + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); - xfer->queued_len = (uint16_t)(xfer->queued_len + rx_count); - } - - if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - uint8_t const ep_addr = ep_num; - // all bytes received or short packet - dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - - if (ep_num == 0) { - // prepared for status packet - btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - } - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); - } else { - // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always - if (!is_iso) { - uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); - } - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + // ch32 seems to unconditionally accept ZLP on EP0 OUT, which can incorrectly use queued_len of previous + // transfer. So reset total_len and queued_len to 0. + xfer->total_len = xfer->queued_len = 0; + } else { + // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always + if (!is_iso) { + uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ep_write(ep_id, ep_reg, false); } - - ep_write(ep_id, ep_reg); } void dcd_int_handler(uint8_t rhport) { uint32_t int_status = FSDEV_REG->ISTR; - // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP - // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; - // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) - - // The ST driver loops here on the CTR bit, but that loop has been moved into the - // dcd_ep_ctr_handler(), so less need to loop here. The other interrupts shouldn't - // be triggered repeatedly. /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ if (int_status & USB_ISTR_SOF) { @@ -465,16 +414,51 @@ void dcd_int_handler(uint8_t rhport) { } // loop to handle all pending CTR interrupts - while (int_status & USB_ISTR_CTR) { - uint32_t const ep_id = int_status & USB_ISTR_EP_ID; + while (FSDEV_REG->ISTR & USB_ISTR_CTR) { + // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt + uint32_t const ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + uint32_t const ep_reg = ep_read(ep_id); - if ((int_status & USB_ISTR_DIR) == 0U) { - handle_ctr_tx(ep_id); // TX/IN - } else { - handle_ctr_rx(ep_id); // RX/OUT or both (RX/TX !!) + if (ep_reg & USB_EP_CTR_RX) { + #ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata may also apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + #endif + + if (ep_reg & USB_EP_SETUP) { + handle_ctr_setup(ep_id); // CTR will be clear after copied setup packet + } else { + ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); + handle_ctr_rx(ep_id); + } } - int_status = FSDEV_REG->ISTR; + if (ep_reg & USB_EP_CTR_TX) { + ep_write_clear_ctr(ep_id, TUSB_DIR_IN); + handle_ctr_tx(ep_id); + } + } + + if (int_status & USB_ISTR_PMAOVR) { + TU_BREAKPOINT(); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; } } @@ -493,6 +477,8 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req uint8_t const dev_addr = (uint8_t)request->wValue; FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); } + + edpt0_prepare_setup(); } /*** @@ -577,29 +563,27 @@ void edpt0_open(uint8_t rhport) { btable_set_addr(0, BTABLE_BUF_RX, pma_addr0); btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); - uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; + uint32_t ep_reg = ep_read(0) & ~USB_EPREG_MASK; // only get toggle bits ep_reg |= USB_EP_CONTROL; - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit - // prepare for setup packet - btable_set_rx_bufsize(0, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - - ep_write(0, ep_reg); + edpt0_prepare_setup(); // prepare for setup packet + ep_write(0, ep_reg, false); } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); - uint32_t ep_reg = FSDEV_REG->ep[ep_idx].reg & ~USB_EPREG_MASK; - ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_RX | USB_EP_CTR_TX; + uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_TX | USB_EP_CTR_RX; // Set type switch (desc_ep->bmAttributes.xfer) { @@ -623,8 +607,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { xfer->max_packet_size = packet_size; xfer->ep_idx = ep_idx; - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); - ep_reg = ep_add_dtog(ep_reg, dir, 0); + ep_change_status(&ep_reg, dir, EP_STAT_NAK); + ep_change_dtog(&ep_reg, dir, 0); // reserve other direction toggle bits if (dir == TUSB_DIR_IN) { @@ -633,18 +617,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); return true; } -void dcd_edpt_close_all(uint8_t rhport) -{ - (void)rhport; +void dcd_edpt_close_all(uint8_t rhport) { + dcd_int_disable(rhport); for (uint32_t i = 1; i < FSDEV_EP_COUNT; i++) { // Reset endpoint - ep_write(i, 0); + ep_write(i, 0, false); // Clear EP allocation status ep_alloc_status[i].ep_num = 0xFF; ep_alloc_status[i].ep_type = 0xFF; @@ -652,6 +635,8 @@ void dcd_edpt_close_all(uint8_t rhport) ep_alloc_status[i].allocated[1] = false; } + dcd_int_enable(rhport); + // Reset PMA allocation ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; } @@ -665,10 +650,11 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, for smaller devices double buffering occupy too much space. */ - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); #if FSDEV_PMA_SIZE > 1024u + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); uint16_t pma_addr2 = pma_addr >> 16; #else + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); uint16_t pma_addr2 = pma_addr; #endif @@ -685,21 +671,21 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; xfer->max_packet_size = tu_edpt_packet_size(desc_ep); - uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; - ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ep_reg = ep_add_dtog(ep_reg, dir, 0); - ep_reg = ep_add_dtog(ep_reg, 1-dir, 1); + uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX; + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ep_change_dtog(&ep_reg, dir, 0); + ep_change_dtog(&ep_reg, (tusb_dir_t)(1 - dir), 1); - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); return true; } @@ -707,7 +693,8 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint16_t ep_reg = ep_read(ep_ix) | EP_CTR_TXRX; + uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR + bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; @@ -717,28 +704,25 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { buf_id = BTABLE_BUF_TX; } uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); - btable_set_count(ep_ix, buf_id, len); if (xfer->ff) { dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); } else { dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); + xfer->queued_len += len; - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_VALID); - ep_reg = ep_clear_ctr(ep_reg, TUSB_DIR_IN); + btable_set_count(ep_ix, buf_id, len); + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); - dcd_int_disable(0); - ep_write(ep_ix, ep_reg); if (is_iso) { xfer->iso_in_sending = true; } - dcd_int_enable(0); + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits + ep_write(ep_ix, ep_reg, true); } -static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { (void) rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); @@ -747,10 +731,10 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); - uint16_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX; - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); // keep CTR TX, clear CTR RX - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_VALID); + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); + + uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); @@ -759,7 +743,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } - ep_write(ep_idx, ep_reg); + ep_change_status(&ep_reg, dir, EP_STAT_VALID); + ep_write(ep_idx, ep_reg, true); } return true; @@ -767,7 +752,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->buffer = buffer; @@ -780,7 +765,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->buffer = NULL; @@ -794,302 +779,196 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx); - ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_STALL); + ep_change_status(&ep_reg, dir, EP_STAT_STALL); - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx) | EP_CTR_TXRX; + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); + ep_change_status(&ep_reg, dir, EP_STAT_NAK); } - ep_reg = ep_add_dtog(ep_reg, dir, 0); // Reset to DATA0 - - ep_write(ep_idx, ep_reg); + ep_change_dtog(&ep_reg, dir, 0); // Reset to DATA0 + ep_write(ep_idx, ep_reg, true); } -#ifdef FSDEV_BUS_32BIT -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { - const uint8_t *src8 = src; - volatile uint32_t *pma32 = (volatile uint32_t *)(USB_PMAADDR + dst); - - for (uint32_t n = wNBytes / 4; n > 0; --n) { - *pma32++ = tu_unaligned_read32(src8); - src8 += 4; - } - - uint16_t odd = wNBytes & 0x03; - if (odd) { - uint32_t wrVal = *src8; - odd--; - - if (odd) { - wrVal |= *++src8 << 8; - odd--; - - if (odd) { - wrVal |= *++src8 << 16; - } - } - - *pma32 = wrVal; - } +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ - return true; -} +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - uint8_t *dst8 = dst; - volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; - for (uint32_t n = wNBytes / 4; n > 0; --n) { - tu_unaligned_write32(dst8, *src32++); - dst8 += 4; + while (n_write--) { + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; + pma_buf++; } - uint16_t odd = wNBytes & 0x03; + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); if (odd) { - uint32_t rdVal = *src32; - - *dst8 = tu_u32_byte0(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte1(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte2(rdVal); - } + fsdev_bus_t temp = 0; + for(uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); } + pma_buf->value = temp; } return true; } -#else -// Packet buffer access can only be 8- or 16-bit. -/** - * @brief Copy a buffer from user memory area to packet memory area (PMA). - * This uses un-aligned for user memory and 16-bit access for packet memory. - * @param dst, byte address in PMA; must be 16-bit aligned - * @param src pointer to user memory area. - * @param wPMABufAddr address into PMA. - * @param nbytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - uint32_t n16 = (uint32_t)nbytes >> 1U; - const uint8_t *src8 = src; - fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * dst); - - while (n16--) { - pma16->u16 = tu_unaligned_read16(src8); - src8 += 2; - pma16++; - } - - if (nbytes & 0x01) { - pma16->u16 = (uint16_t) *src8; - } - - return true; -} - -/** - * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses unaligned for system memory and 16-bit access of packet memory - * @param nbytes no. of bytes to be copied. - * @retval None - */ +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - uint32_t n16 = (uint32_t)nbytes >> 1U; - fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * src); + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); uint8_t *dst8 = (uint8_t *)dst; - while (n16--) { - uint16_t temp16 = pma16->u16; - tu_unaligned_write16(dst8, temp16); - dst8 += 2; - pma16++; + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; + pma_buf++; } - if (nbytes & 0x01) { - *dst8++ = tu_u16_low(pma16->u16); + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } } return true; } -#endif - -/** - * @brief Copy from FIFO to packet memory area (PMA). - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ +// Write to PMA from FIFO static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { + if (wNBytes == 0) return true; + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); - uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t const cnt_total = cnt_lin + cnt_wrap; // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part - // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit) -#ifdef FSDEV_BUS_32BIT - if ((cnt_lin & 0x03) && cnt_wrap) { - // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x03); - dst += cnt_lin & ~0x03; + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t const *src8 = (uint8_t const*) info.ptr_lin; - // Copy last linear bytes & first wrapped bytes to buffer - uint32_t i; - uint8_t tmp[4]; - for (i = 0; i < (cnt_lin & 0x03); i++) { - tmp[i] = ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i]; - } - uint32_t wCnt = cnt_wrap; - for (; i < 4 && wCnt > 0; i++, wCnt--) { - tmp[i] = *(uint8_t *)info.ptr_wrap; - info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; - } - - // Write unaligned buffer - dcd_write_packet_memory(dst, &tmp, 4); - dst += 4; + // write even linear part + dcd_write_packet_memory(dst, src8, lin_even); + dst += lin_even; + src8 += lin_even; - // Copy rest of wrapped byte - if (wCnt) { - dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); + if (lin_odd == 0) { + src8 = (uint8_t const*) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp = 0; + uint16_t i; + for(i = 0; i < lin_odd; i++) { + temp |= *src8++ << (i * 8); } - } -#else - if ((cnt_lin & 0x01) && cnt_wrap) { - // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x01); - dst += cnt_lin & ~0x01; - - // Copy last linear byte & first wrapped byte - uint16_t tmp = ((uint8_t *)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t *)info.ptr_wrap)[0]) << 8U); - dcd_write_packet_memory(dst, &tmp, 2); - dst += 2; - // Copy rest of wrapped byte - dcd_write_packet_memory(dst, ((uint8_t *)info.ptr_wrap) + 1, cnt_wrap - 1); - } -#endif - else { - // Copy linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin); - dst += info.len_lin; - - if (info.len_wrap) { - // Copy wrapped byte - dcd_write_packet_memory(dst, info.ptr_wrap, cnt_wrap); + src8 = (uint8_t const*) info.ptr_wrap; + for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + temp |= *src8++ << (i * 8); } + + dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); + dst += FSDEV_BUS_SIZE; } - tu_fifo_advance_read_pointer(ff, cnt_lin + cnt_wrap); + // write the rest of the wrapped part + dcd_write_packet_memory(dst, src8, cnt_wrap); + tu_fifo_advance_read_pointer(ff, cnt_total); return true; } -/** - * @brief Copy a buffer from user packet memory area (PMA) to FIFO. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ +// Read from PMA to FIFO static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { + if (wNBytes == 0) return true; + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part tu_fifo_buffer_info_t info; tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); - uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_total = cnt_lin + cnt_wrap; - // We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part - // To ensure PMA is always access aligned (src aligned to 16 or 32 bit) -#ifdef FSDEV_BUS_32BIT - if ((cnt_lin & 0x03) && cnt_wrap) { - // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x03); - src += cnt_lin & ~0x03; - - // Copy last linear bytes & first wrapped bytes - uint8_t tmp[4]; - dcd_read_packet_memory(tmp, src, 4); - src += 4; - - uint32_t i; - for (i = 0; i < (cnt_lin & 0x03); i++) { - ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i] = tmp[i]; - } - uint32_t wCnt = cnt_wrap; - for (; i < 4 && wCnt > 0; i++, wCnt--) { - *(uint8_t *)info.ptr_wrap = tmp[i]; - info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; - } + // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - // Copy rest of wrapped byte - if (wCnt) { - dcd_read_packet_memory(info.ptr_wrap, src, wCnt); - } - } -#else - if ((cnt_lin & 0x01) && cnt_wrap) { - // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x01); - src += cnt_lin & ~0x01; + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t *dst8 = (uint8_t *) info.ptr_lin; - // Copy last linear byte & first wrapped byte - uint8_t tmp[2]; - dcd_read_packet_memory(tmp, src, 2); - src += 2; + // read even linear part + dcd_read_packet_memory(dst8, src, lin_even); + dst8 += lin_even; + src += lin_even; - ((uint8_t *)info.ptr_lin)[cnt_lin - 1] = tmp[0]; - ((uint8_t *)info.ptr_wrap)[0] = tmp[1]; + if (lin_odd == 0) { + dst8 = (uint8_t *) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp; + dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); + src += FSDEV_BUS_SIZE; - // Copy rest of wrapped byte - dcd_read_packet_memory(((uint8_t *)info.ptr_wrap) + 1, src, cnt_wrap - 1); - } -#endif - else { - // Copy linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin); - src += cnt_lin; + uint16_t i; + for (i = 0; i < lin_odd; i++) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } - if (info.len_wrap) { - // Copy wrapped byte - dcd_read_packet_memory(info.ptr_wrap, src, cnt_wrap); + dst8 = (uint8_t *) info.ptr_wrap; + for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; } } - tu_fifo_advance_write_pointer(ff, cnt_lin + cnt_wrap); + // read the rest of the wrapped part + dcd_read_packet_memory(dst8, src, cnt_wrap); + tu_fifo_advance_write_pointer(ff, cnt_total); return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 8c0961bb9..518197c47 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -54,22 +54,8 @@ #endif #define FSDEV_PMA_SIZE (512u) -#define FSDEV_REG_BASE 0x40005C00UL - -#define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */ -#define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */ -#define USB ((USB_TypeDef *)USB_BASE) - -/******************************************************************************/ -/* */ -/* USB Device General registers */ -/* */ -/******************************************************************************/ -#define USB_CNTR (USB_BASE + 0x40U) /*!< Control register */ -#define USB_ISTR (USB_BASE + 0x44U) /*!< Interrupt status register */ -#define USB_FNR (USB_BASE + 0x48U) /*!< Frame number register */ -#define USB_DADDR (USB_BASE + 0x4CU) /*!< Device address register */ -#define USB_BTABLE (USB_BASE + 0x50U) /*!< Buffer Table address register */ +#define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) +#define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) /**************************** ISTR interrupt events *************************/ #define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index bb2c72fd1..99fe8d55f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -82,12 +82,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" - #define FSDEV_BUS_32BIT #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -100,7 +97,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -110,17 +106,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 #include "stm32h5xx.h" - #define FSDEV_BUS_32BIT - - #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) - #define USB_DRD_BASE USB_DRD_FS_BASE - #endif - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -133,7 +121,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -144,9 +131,8 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" #define FSDEV_PMA_SIZE (1024u) - /* ST provided header has incorrect value */ - #undef USB_PMAADDR - #define USB_PMAADDR USB1_PMAADDR + /* ST provided header has incorrect value of USB_PMAADDR */ + #define FSDEV_PMA_BASE USB1_PMAADDR #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" @@ -162,13 +148,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -181,7 +163,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -194,6 +175,10 @@ // This includes U0 #endif +//--------------------------------------------------------------------+ +// Register and PMA Base Address +//--------------------------------------------------------------------+ +#ifndef FSDEV_REG_BASE #if defined(USB_BASE) #define FSDEV_REG_BASE USB_BASE #elif defined(USB_DRD_BASE) @@ -203,6 +188,17 @@ #else #error "FSDEV_REG_BASE not defined" #endif +#endif + +#ifndef FSDEV_PMA_BASE +#if defined(USB_PMAADDR) + #define FSDEV_PMA_BASE USB_PMAADDR +#elif defined(USB_DRD_PMAADDR) + #define FSDEV_PMA_BASE USB_DRD_PMAADDR +#else + #error "FSDEV_PMA_BASE not defined" +#endif +#endif // This checks if the device has "LPM" #if defined(USB_ISTR_L1REQ) diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index e4a0f3f28..cf36576bb 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -1,9 +1,8 @@ /* * The MIT License (MIT) * - * Copyright(c) 2016 STMicroelectronics * Copyright(c) N Conrad - * Copyright (c) 2024, hathach (tinyusb.org) + * Copyright(c) 2024, 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 @@ -23,6 +22,7 @@ * 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_FSDEV_TYPE_H @@ -49,19 +49,35 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // For purposes of accessing the packet #if FSDEV_PMA_SIZE == 512 - #define FSDEV_PMA_STRIDE (2u) // 1x16 bit access scheme - #define pma_aligned TU_ATTR_ALIGNED(4) + // 1x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 2 + #define pma_access_scheme TU_ATTR_ALIGNED(4) #elif FSDEV_PMA_SIZE == 1024 - #define FSDEV_PMA_STRIDE (1u) // 2x16 bit access scheme - #define pma_aligned + // 2x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme #elif FSDEV_PMA_SIZE == 2048 - #ifndef FSDEV_BUS_32BIT - #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" - #endif - #define FSDEV_PMA_STRIDE (1u) // 32 bit access scheme - #define pma_aligned + // 32 bit access scheme + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme #endif +// The fsdev_bus_t type can be used for both register and PMA access necessities +#ifdef FSDEV_BUS_32BIT + typedef uint32_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) +#else + typedef uint16_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) +#endif + +enum { + FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), +}; + //--------------------------------------------------------------------+ // BTable Typedef //--------------------------------------------------------------------+ @@ -75,13 +91,12 @@ enum { // Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either // 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +// 0: TX (IN), 1: RX (OUT) typedef union { - // 0: TX (IN), 1: RX (OUT) - - // strictly 16-bit access (could be 32-bit aligned) + // data is strictly 16-bit access (address could be 32-bit aligned) struct { - volatile pma_aligned uint16_t addr; - volatile pma_aligned uint16_t count; + volatile pma_access_scheme uint16_t addr; + volatile pma_access_scheme uint16_t count; } ep16[FSDEV_EP_COUNT][2]; // strictly 32-bit access @@ -93,11 +108,13 @@ typedef union { TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) typedef struct { - volatile pma_aligned uint16_t u16; -} fsdev_pma16_t; + volatile pma_access_scheme fsdev_bus_t value; +} fsdev_pma_buf_t; + +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) //--------------------------------------------------------------------+ // Registers Typedef @@ -106,13 +123,6 @@ typedef struct { // volatile 32-bit aligned #define _va32 volatile TU_ATTR_ALIGNED(4) -// The fsdev_bus_t type can be used for both register and PMA access necessities -#ifdef FSDEV_BUS_32BIT -typedef uint32_t fsdev_bus_t; -#else -typedef uint16_t fsdev_bus_t; -#endif - typedef struct { struct { _va32 fsdev_bus_t reg; @@ -154,9 +164,6 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define USB_EP_CTR_TX_Pos 7u #endif - -#define EP_CTR_TXRX (USB_EP_CTR_TX | USB_EP_CTR_RX) - typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, @@ -173,24 +180,36 @@ typedef enum { // - DTOG and STAT are write 1 to toggle //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; -} - TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { return FSDEV_REG->ep[ep_id].reg; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { - return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { + if (need_exclusive) { + dcd_int_disable(0); + } + + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + + if (need_exclusive) { + dcd_int_enable(0); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ep_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + ep_write(ep_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { - return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { - return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { @@ -219,7 +238,7 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t #endif } -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { uint16_t count; #ifdef FSDEV_BUS_32BIT count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); @@ -249,22 +268,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size if (size > 62) { block_in_bytes = 32; *blsize = 1; + *num_block = tu_div_ceil(size, 32); } else { block_in_bytes = 2; *blsize = 0; + *num_block = tu_div_ceil(size, 2); } - *num_block = tu_div_ceil(size, block_in_bytes); - return (*num_block) * block_in_bytes; } -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { +TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { uint8_t blsize, num_block; (void) pma_align_buffer_size(wCount, &blsize, &num_block); /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + if (bl_nb == 0) { + // zlp but 0 is invalid value, set blsize to 1 (32 bytes) + // Note: lower value can cause PMAOVR on setup with ch32v203 + bl_nb = 1 << 15; + } #ifdef FSDEV_BUS_32BIT uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; @@ -273,6 +297,7 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u #else FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; #endif + } #ifdef __cplusplus diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 12d610bd6..25ee507c1 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -102,6 +102,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return false; } +// Allocate packet buffer used by ISO endpoints +// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +// Configure and enable an ISO endpoint according to descriptor +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 8005f5f7b..6b60bc657 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -332,6 +332,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; (void) ep_addr; + // TODO implement dcd_edpt_close() +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 58628a8bb..8f40e3349 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -436,6 +436,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; (void) ep_addr; + // TODO implement dcd_edpt_close() +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; diff --git a/src/tusb_option.h b/src/tusb_option.h index f2cc284dc..fb0209023 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -188,6 +188,12 @@ #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series #define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series +// Analog Devices +#define OPT_MCU_MAX32690 2400 ///< ADI MAX32690 +#define OPT_MCU_MAX32666 2401 ///< ADI MAX32666/5 +#define OPT_MCU_MAX32650 2402 ///< ADI MAX32650/1/2 +#define OPT_MCU_MAX78002 2403 ///< ADI MAX78002 + // 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) |
