diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 00d16bc2..3beef45d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ assignees: '' **Set Up** -- **PC OS** e.g Ubuntu 20.04 / Windows 10/ macOS 10.15 +- **PC OS** e.g Ubuntu 20.04 / Windows 10 / macOS 10.15 - **Board** e.g Feather nRF52840 Express (if custom specify your MCUs) - **TinyUSB version** relase version or git hash (preferrably running with master for lastest code) - **Firmware** e.g examples/device/cdc_msc @@ -31,6 +31,5 @@ If applicable, add screenshots, bus capture to help explain your problem. **Log** -If applicable, provide the stack's log (uart/rtt/swo) where the issue occurred, best with comments to explain the actual events. If the log is too long, attach it as txt file instead. - +If applicable, provide the stack's log (uart/rtt/swo) where the issue occurred as attached txt file, best with comments to explain the actual events. Note: To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. More information can be found at [example's readme](/docs/getting_started.md) diff --git a/.gitmodules b/.gitmodules index 79ef8e0a..c0e6f8f9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -121,3 +121,6 @@ [submodule "hw/mcu/nxp/nxp_sdk"] path = hw/mcu/nxp/nxp_sdk url = https://github.com/hathach/nxp_sdk.git +[submodule "hw/mcu/mindmotion/mm32sdk"] + path = hw/mcu/mindmotion/mm32sdk + url = https://github.com/zhangslice/mm32sdk.git diff --git a/examples/make.mk b/examples/make.mk index df8bfd61..9daf60e3 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -5,7 +5,7 @@ # Build directory BUILD := _build/$(BOARD) -PROJECT := $(BOARD)-$(notdir $(CURDIR)) +PROJECT := $(notdir $(CURDIR)) BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR)) # Handy check parameter function diff --git a/hw/mcu/mindmotion/mm32sdk b/hw/mcu/mindmotion/mm32sdk new file mode 160000 index 00000000..b6b99de3 --- /dev/null +++ b/hw/mcu/mindmotion/mm32sdk @@ -0,0 +1 @@ +Subproject commit b6b99de3ab26218784ec158488bdd91377288f94 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index facf86d5..33f1a8ad 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "cdc_host.h" //--------------------------------------------------------------------+ @@ -71,13 +73,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) switch (pipeid) { case CDC_PIPE_NOTIFICATION: - return hcd_edpt_busy(dev_addr, p_cdc->ep_notif ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); case CDC_PIPE_DATA_IN: - return hcd_edpt_busy(dev_addr, p_cdc->ep_in ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); case CDC_PIPE_DATA_OUT: - return hcd_edpt_busy(dev_addr, p_cdc->ep_out ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); default: return false; @@ -101,7 +103,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } @@ -113,7 +115,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5cc9233b..ec14c9c7 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -201,30 +201,73 @@ typedef struct TU_ATTR_PACKED int8_t rx; ///< Delta Rx movement of analog left trigger int8_t ry; ///< Delta Ry movement of analog right trigger uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint16_t buttons; ///< Buttons mask for currently pressed buttons + uint32_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; -/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +/// Standard Gamepad Buttons Bitmap typedef enum { - GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button - GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button - GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button - GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button - GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button - GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button - GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button - GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button - GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button - GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button - GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button - GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button - GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button - GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button -//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button + GAMEPAD_BUTTON_0 = TU_BIT(0), + GAMEPAD_BUTTON_1 = TU_BIT(1), + GAMEPAD_BUTTON_2 = TU_BIT(2), + GAMEPAD_BUTTON_3 = TU_BIT(3), + GAMEPAD_BUTTON_4 = TU_BIT(4), + GAMEPAD_BUTTON_5 = TU_BIT(5), + GAMEPAD_BUTTON_6 = TU_BIT(6), + GAMEPAD_BUTTON_7 = TU_BIT(7), + GAMEPAD_BUTTON_8 = TU_BIT(8), + GAMEPAD_BUTTON_9 = TU_BIT(9), + GAMEPAD_BUTTON_10 = TU_BIT(10), + GAMEPAD_BUTTON_11 = TU_BIT(11), + GAMEPAD_BUTTON_12 = TU_BIT(12), + GAMEPAD_BUTTON_13 = TU_BIT(13), + GAMEPAD_BUTTON_14 = TU_BIT(14), + GAMEPAD_BUTTON_15 = TU_BIT(15), + GAMEPAD_BUTTON_16 = TU_BIT(16), + GAMEPAD_BUTTON_17 = TU_BIT(17), + GAMEPAD_BUTTON_18 = TU_BIT(18), + GAMEPAD_BUTTON_19 = TU_BIT(19), + GAMEPAD_BUTTON_20 = TU_BIT(20), + GAMEPAD_BUTTON_21 = TU_BIT(21), + GAMEPAD_BUTTON_22 = TU_BIT(22), + GAMEPAD_BUTTON_23 = TU_BIT(23), + GAMEPAD_BUTTON_24 = TU_BIT(24), + GAMEPAD_BUTTON_25 = TU_BIT(25), + GAMEPAD_BUTTON_26 = TU_BIT(26), + GAMEPAD_BUTTON_27 = TU_BIT(27), + GAMEPAD_BUTTON_28 = TU_BIT(28), + GAMEPAD_BUTTON_29 = TU_BIT(29), + GAMEPAD_BUTTON_30 = TU_BIT(30), + GAMEPAD_BUTTON_31 = TU_BIT(31), }hid_gamepad_button_bm_t; +/// Standard Gamepad Buttons Naming from Linux input event codes +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h +#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 +#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 + +#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 +#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 + +#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 + +#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 +#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 + +#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 +#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 + +#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 +#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 +#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 +#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 +#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 +#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 +#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 +#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 +#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 +#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 + /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) typedef enum { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 151a3622..e44f282c 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -149,7 +149,7 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, } bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { hid_gamepad_report_t report = { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index beb75588..e2c950dd 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -72,9 +72,9 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi // use template layout report as defined by hid_mouse_report_t bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -// Gamepad: convenient helper to send mouse report if application +// Gamepad: convenient helper to send gamepad report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) @@ -85,7 +85,7 @@ static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -152,7 +152,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } @@ -344,10 +344,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 16 ) ,\ + HID_USAGE_MAX ( 32 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 16 ) ,\ + HID_REPORT_COUNT ( 32 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83f3f303..cde5e23a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "hid_host.h" //--------------------------------------------------------------------+ @@ -199,7 +201,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); // // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); //} //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 205f0fd2..7f98ef9b 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -29,6 +29,8 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "msc_host.h" //--------------------------------------------------------------------+ @@ -109,7 +111,7 @@ bool tuh_msc_mounted(uint8_t dev_addr) bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 3350ed86..889ad7b2 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -51,7 +51,7 @@ #define U32_TO_U8S_BE(u32) TU_U32_BYTE3(u32), TU_U32_BYTE2(u32), TU_U32_BYTE1(u32), TU_U32_BYTE0(u32) #define U32_TO_U8S_LE(u32) TU_U32_BYTE0(u32), TU_U32_BYTE1(u32), TU_U32_BYTE2(u32), TU_U32_BYTE3(u32) -#define TU_BIT(n) (1U << (n)) +#define TU_BIT(n) (1UL << (n)) //--------------------------------------------------------------------+ // Includes diff --git a/src/device/dcd.h b/src/device/dcd.h index 25cfafc4..63e97df9 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -121,20 +121,20 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + // 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); + // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); - -// 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); - // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 49c9279b..cedca540 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1254,8 +1254,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() + // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index bb2267d4..6a4b3095 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -34,7 +34,7 @@ #endif //--------------------------------------------------------------------+ -// Class Drivers +// Class Driver API //--------------------------------------------------------------------+ typedef struct diff --git a/src/host/hcd.h b/src/host/hcd.h index 46209dc4..7a9aadc7 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -137,9 +137,6 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/host/hub.c b/src/host/hub.c index f921027c..b2761184 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -29,6 +29,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) #include "usbh.h" +#include "usbh_classdriver.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ca065340..59246a66 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -24,7 +24,7 @@ * This file is part of the TinyUSB stack. */ -#include "common/tusb_common.h" +#include "tusb_option.h" #if TUSB_OPT_HOST_ENABLED @@ -32,10 +32,9 @@ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "tusb.h" +#include "host/usbh.h" +#include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" @@ -315,8 +314,11 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//------------- Endpoint API -------------// +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -344,6 +346,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -369,11 +372,36 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + usbh_device_t* dev = &_usbh_devices[dev_addr]; - TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); - return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) @@ -420,6 +448,17 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return ret; } +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/host/usbh.h b/src/host/usbh.h index a9790b48..4de6e7ba 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -24,9 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbh USB Host Core (USBH) - * @{ */ - #ifndef _TUSB_USBH_H_ #define _TUSB_USBH_H_ @@ -40,27 +37,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum tusb_interface_status_{ - TUSB_INTERFACE_STATUS_READY = 0, - TUSB_INTERFACE_STATUS_BUSY, - TUSB_INTERFACE_STATUS_COMPLETE, - TUSB_INTERFACE_STATUS_ERROR, - TUSB_INTERFACE_STATUS_INVALID_PARA -} tusb_interface_status_t; - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - uint8_t class_code; - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -101,34 +77,14 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, //--------------------------------------------------------------------+ //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); -/** Callback invoked when device is mounted (configured) */ +// Invoked when device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); -/** Callback invoked when device is unmounted (bus reset/unplugged) */ +/// Invoked when device is unmounted (bus reset/unplugged) TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); -//--------------------------------------------------------------------+ -// CLASS-USBH & INTERNAL API -// TODO move to usbh_pvt.h -//--------------------------------------------------------------------+ - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - #ifdef __cplusplus } #endif -#endif /* _TUSB_USBH_H_ */ - -/** @} */ +#endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h new file mode 100644 index 00000000..07480fe8 --- /dev/null +++ b/src/host/usbh_classdriver.h @@ -0,0 +1,83 @@ +/* + * 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_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + uint8_t class_code; + + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + +// Submit a usb transfer +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index abc7fd25..b3856d6b 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -97,12 +97,6 @@ typedef struct { extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -//--------------------------------------------------------------------+ -// callback from HCD ISR -//--------------------------------------------------------------------+ - - - #ifdef __cplusplus } #endif diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index bcba360b..48788ba0 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -440,18 +440,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); -} - -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c new file mode 100644 index 00000000..59a40dc6 --- /dev/null +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -0,0 +1,471 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 SE TEAM + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) + +#include "reg_usb_otg_fs.h" +#include "mm32_device.h" +#include "hal_conf.h" +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum { + TOK_PID_OUT = 0x1u, + TOK_PID_IN = 0x9u, + TOK_PID_SETUP = 0xDu, +}; + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t head; + struct { + union { + struct { + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; + }; + struct { + uint16_t : 2; + uint16_t bdt_stall: 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; + }; + }; + uint16_t bc : 10; + uint16_t : 6; + }; + }; + uint8_t *addr; +}buffer_descriptor_t; + +TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t state; + struct { + uint32_t max_packet_size :11; + uint32_t : 5; + uint32_t odd : 1; + uint32_t :15; + }; + }; + uint16_t length; + uint16_t remaining; +}endpoint_state_t; + +TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); + +typedef struct +{ + union { + /* [#EP][OUT,IN][EVEN,ODD] */ + buffer_descriptor_t bdt[16][2][2]; + uint16_t bda[512]; + }; + TU_ATTR_ALIGNED(4) union { + endpoint_state_t endpoint[16][2]; + endpoint_state_t endpoint_unified[16 * 2]; + }; + uint8_t setup_packet[8]; + uint8_t addr; +}dcd_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// BDT(Buffer Descriptor Table) must be 256-byte aligned +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; + +TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); + +static void prepare_next_setup_packet(uint8_t rhport) +{ + const unsigned out_odd = _dcd.endpoint[0][0].odd; + const unsigned in_odd = _dcd.endpoint[0][1].odd; + if (_dcd.bdt[0][0][out_odd].own) { + TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); + return; + } + _dcd.bdt[0][0][out_odd].data = 0; + _dcd.bdt[0][0][out_odd ^ 1].data = 1; + _dcd.bdt[0][1][in_odd].data = 1; + _dcd.bdt[0][1][in_odd ^ 1].data = 0; + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.setup_packet, sizeof(_dcd.setup_packet)); +} + +static void process_stall(uint8_t rhport) +{ + if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { + /* clear stall condition of the control pipe */ + prepare_next_setup_packet(rhport); + USB_OTG_FS->EP_CTL[0] &= ~USB_ENDPT_EPSTALL_MASK; + } +} + +static void process_tokdne(uint8_t rhport) +{ + const unsigned s = USB_OTG_FS->STAT; + USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; + + /* fetch pid before discarded by the next steps */ + const unsigned pid = bd->tok_pid; + /* reset values for a next transfer */ + bd->bdt_stall = 0; + bd->dts = 1; + bd->ninc = 0; + bd->keep = 0; + /* update the odd variable to prepare for the next transfer */ + ep->odd = odd ^ 1; + if (pid == TOK_PID_SETUP) { + dcd_event_setup_received(rhport, bd->addr, true); + USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + return; + } + if (s >> 4) { + TU_LOG1("TKDNE %x\r\n", s); + } + + const unsigned bc = bd->bc; + const unsigned remaining = ep->remaining - bc; + if (remaining && bc == ep->max_packet_size) { + /* continue the transferring consecutive data */ + ep->remaining = remaining; + const int next_remaining = remaining - ep->max_packet_size; + if (next_remaining > 0) { + /* prepare to the after next transfer */ + bd->addr += ep->max_packet_size * 2; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + } + return; + } + const unsigned length = ep->length; + dcd_event_xfer_complete(rhport, + ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + length - remaining, XFER_RESULT_SUCCESS, true); + if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { + /* After completion a ZLP of control transfer, + * it prepares for the next steup transfer. */ + if (_dcd.addr) { + /* When the transfer was the SetAddress, + * the device address should be updated here. */ + USB_OTG_FS->ADDR = _dcd.addr; + _dcd.addr = 0; + } + prepare_next_setup_packet(rhport); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; + USB_OTG_FS->ADDR = 0; + USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + + USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; + for (unsigned i = 1; i < 16; ++i) { + USB_OTG_FS->EP_CTL[i] = 0; + } + buffer_descriptor_t *bd = _dcd.bdt[0][0]; + for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + bd->head = 0; + } + const endpoint_state_t ep0 = { + .max_packet_size = CFG_TUD_ENDPOINT0_SIZE, + .odd = 0, + .length = 0, + .remaining = 0, + }; + _dcd.endpoint[0][0] = ep0; + _dcd.endpoint[0][1] = ep0; + tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); + _dcd.addr = 0; + prepare_next_setup_packet(rhport); + USB_OTG_FS->CTL &= ~USB_CTL_ODDRST_MASK; + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); +} + +static void process_bus_inactive(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +} + +static void process_bus_active(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + tu_memclr(&_dcd, sizeof(_dcd)); + USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); + USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); + + dcd_connect(rhport); + NVIC_ClearPendingIRQ(USB_FS_IRQn); +} +#define USB_DEVICE_INTERRUPT_PRIORITY (3U) +void dcd_int_enable(uint8_t rhport) +{ + uint8_t irqNumber; + irqNumber = USB_FS_IRQn; + (void) rhport; + USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); + NVIC_EnableIRQ(USB_FS_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + USB_OTG_FS->INT_ENB = 0; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + _dcd.addr = dev_addr & 0x7F; + /* Response with status first before changing device address */ + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} +extern u32 SystemCoreClock ; +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + unsigned cnt = SystemCoreClock / 100; + USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; + while (cnt--) __NOP(); + USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL = 0; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + + /* No support for control transfer */ + TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); + + ep->max_packet_size = ep_desc->wMaxPacketSize.size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] |= val; + + if (xfer != TUSB_XFER_ISOCHRONOUS) { + bd[odd].dts = 1; + bd[odd].data = 0; + bd[odd ^ 1].dts = 1; + bd[odd ^ 1].data = 1; + } + + return true; +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] &= ~msk; + ep->max_packet_size = 0; + ep->length = 0; + ep->remaining = 0; + bd->head = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + + if (bd->own) { + TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); + return false; /* The last transfer has not completed */ + } + ep->length = total_bytes; + ep->remaining = total_bytes; + + const unsigned mps = ep->max_packet_size; + if (total_bytes > mps) { + buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + /* When total_bytes is greater than the max packet size, + * it prepares to the next transfer to avoid NAK in advance. */ + next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->addr = buffer + mps; + next->own = 1; + } + bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->addr = buffer; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + NVIC_EnableIRQ(USB_FS_IRQn); + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + if (0 == epn) { + USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; + } else { + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + + bd[odd ^ 1].own = 0; + bd[odd ^ 1].data = 1; + bd[odd ^ 1].bdt_stall = 0; + bd[odd].own = 0; + bd[odd].data = 0; + bd[odd].bdt_stall = 0; +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + + uint32_t is = USB_OTG_FS->INT_STAT; + uint32_t msk = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_STAT = is & ~msk; + is &= msk; + if (is & USB_ISTAT_ERROR_MASK) { + /* TODO: */ + uint32_t es = USB_OTG_FS->ERR_STAT; + USB_OTG_FS->ERR_STAT = es; + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + return; + } + + if (is & USB_ISTAT_USBRST_MASK) { + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + process_bus_reset(rhport); + return; + } + if (is & USB_ISTAT_SLEEP_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SLEEP_MASK; + process_bus_inactive(rhport); + return; + } + if (is & USB_ISTAT_RESUME_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_RESUME_MASK; + process_bus_active(rhport); + return; + } + if (is & USB_ISTAT_SOFTOK_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SOFTOK_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + return; + } + if (is & USB_ISTAT_STALL_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_STALL_MASK; + process_stall(rhport); + return; + } + if (is & USB_ISTAT_TOKDNE_MASK) { + process_tokdne(rhport); + return; + } +} + +#endif diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index dbd2cc79..73489c76 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -489,18 +489,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); -} - -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return p_ed->td_head.halted && p_ed->is_stalled; -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 3c62b573..b575c6af 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -515,25 +515,19 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - // EPX is shared, so multiple device addresses and endpoint addresses share that - // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own - // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint - // on that device - pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); - struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); - assert(ep); - bool busy = ep->active; - pico_trace("busy == %d\n", busy); - return busy; -} - -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - panic("hcd_pipe_stalled"); - return false; -} +//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +//{ +// // EPX is shared, so multiple device addresses and endpoint addresses share that +// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own +// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint +// // on that device +// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); +// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); +// assert(ep); +// bool busy = ep->active; +// pico_trace("busy == %d\n", busy); +// return busy; +//} bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index a0263612..31381e6c 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -205,10 +205,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Update hw endpoint struct with info from hardware // after a buff status interrupt - // Get the buffer state and amount of bytes we have - // transferred uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #if TUSB_OPT_HOST_ENABLED // RP2040-E4 @@ -227,6 +224,9 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // end::host_buf_sel_fix[] #endif + // Get tranferred bytes after adjusted buf sel + uint16_t const transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + // We are continuing a transfer here. If we are TX, we have successfullly // sent some data can increase the length we have sent if (!ep->rx) @@ -249,7 +249,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Sometimes the host will send less data than we expect... // If this is a short out transfer update the total length of the transfer // to be the current length - if ((ep->rx) && (transferred_bytes < ep->transfer_size)) + if ((ep->rx) && (transferred_bytes < ep->wMaxPacketSize)) { pico_trace("Short rx transfer\n"); // Reduce total length as this is last packet @@ -289,8 +289,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) { pico_trace("Completed transfer of %d bytes on ep %d %s\n", ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - // Notify caller we are done so it can notify the tinyusb - // stack + // Notify caller we are done so it can notify the tinyusb stack _hw_endpoint_lock_update(ep, -1); return true; } diff --git a/src/tusb_option.h b/src/tusb_option.h index 7e147966..2a75cf51 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -114,6 +114,9 @@ #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 #define OPT_MCU_RX72N 1401 ///< Renesas RX72N +// Mind Motion +#define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 + /** @} */ /** \defgroup group_supported_os Supported RTOS