Merge branch 'master' into cdc_ch34x_support
This commit is contained in:
		| @@ -2,7 +2,6 @@ | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2019 Ha Thach (tinyusb.org) | ||||
|  * Copyright (c) 2023 Heiko Kuester (CH34x support) | ||||
|  * | ||||
|  * 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,9 @@ | ||||
|  * THE SOFTWARE. | ||||
|  * | ||||
|  * This file is part of the TinyUSB stack. | ||||
|  * | ||||
|  * Contribution | ||||
|  * - Heiko Kuester: CH34x support | ||||
|  */ | ||||
|  | ||||
| #include "tusb_option.h" | ||||
| @@ -70,6 +72,7 @@ typedef struct { | ||||
|     uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; | ||||
|     CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; | ||||
|   } stream; | ||||
|  | ||||
|   #if CFG_TUH_CDC_CH34X | ||||
|   struct { | ||||
|     uint32_t  baud_rate; | ||||
| @@ -90,6 +93,7 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| //------------- ACM prototypes -------------// | ||||
| static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); | ||||
| static void acm_process_config(tuh_xfer_t* xfer); | ||||
|  | ||||
| static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); | ||||
| @@ -649,8 +653,6 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t | ||||
| // Enumeration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); | ||||
|  | ||||
| static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) | ||||
| { | ||||
|   for(size_t i=0; i<2; i++) | ||||
| @@ -686,7 +688,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d | ||||
|     return acm_open(daddr, itf_desc, max_len); | ||||
|   } | ||||
|   #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X | ||||
|   else if ( 0xff == itf_desc->bInterfaceClass ) | ||||
|   else if ( TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass ) | ||||
|   { | ||||
|     uint16_t vid, pid; | ||||
|     TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); | ||||
|   | ||||
| @@ -75,8 +75,8 @@ | ||||
|   #define _MESS_FAILED() do {} while (0) | ||||
| #endif | ||||
|  | ||||
| // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 | ||||
| #if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) | ||||
| // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55 | ||||
| #if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) | ||||
|   #define TU_BREAKPOINT() do                                                                                \ | ||||
|   {                                                                                                         \ | ||||
|     volatile uint32_t* ARM_CM_DHCSR =  ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ | ||||
|   | ||||
| @@ -152,7 +152,7 @@ void dcd_sof_enable(uint8_t rhport, bool en); | ||||
|  | ||||
| // Invoked when a control transfer's status stage is complete. | ||||
| // 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; | ||||
| void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request); | ||||
|  | ||||
| // Configure endpoint's registers according to descriptor | ||||
| bool dcd_edpt_open            (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); | ||||
|   | ||||
| @@ -38,11 +38,19 @@ | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBD Configuration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| #ifndef CFG_TUD_TASK_QUEUE_SZ | ||||
|   #define CFG_TUD_TASK_QUEUE_SZ   16 | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Callback weak stubs (called if application does not provide) | ||||
| //--------------------------------------------------------------------+ | ||||
| TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { | ||||
|   (void)rhport; | ||||
|   (void)eventid; | ||||
|   (void)in_isr; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Device Data | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -50,10 +58,8 @@ | ||||
| // Invalid driver ID in itf2drv[] ep2drv[][] mapping | ||||
| enum { DRVID_INVALID = 0xFFu }; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   struct TU_ATTR_PACKED | ||||
|   { | ||||
| typedef struct { | ||||
|   struct TU_ATTR_PACKED { | ||||
|     volatile uint8_t connected    : 1; | ||||
|     volatile uint8_t addressed    : 1; | ||||
|     volatile uint8_t suspended    : 1; | ||||
| @@ -85,151 +91,150 @@ tu_static usbd_device_t _usbd_dev; | ||||
| #endif | ||||
|  | ||||
| // Built-in class drivers | ||||
| tu_static usbd_class_driver_t const _usbd_driver[] = | ||||
| { | ||||
|   #if CFG_TUD_CDC | ||||
|   { | ||||
|     DRIVER_NAME("CDC") | ||||
|     .init             = cdcd_init, | ||||
|     .reset            = cdcd_reset, | ||||
|     .open             = cdcd_open, | ||||
|     .control_xfer_cb  = cdcd_control_xfer_cb, | ||||
|     .xfer_cb          = cdcd_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
| tu_static usbd_class_driver_t const _usbd_driver[] = { | ||||
|     #if CFG_TUD_CDC | ||||
|     { | ||||
|         DRIVER_NAME("CDC") | ||||
|         .init             = cdcd_init, | ||||
|         .reset            = cdcd_reset, | ||||
|         .open             = cdcd_open, | ||||
|         .control_xfer_cb  = cdcd_control_xfer_cb, | ||||
|         .xfer_cb          = cdcd_xfer_cb, | ||||
|         .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_MSC | ||||
|   { | ||||
|     DRIVER_NAME("MSC") | ||||
|     .init             = mscd_init, | ||||
|     .reset            = mscd_reset, | ||||
|     .open             = mscd_open, | ||||
|     .control_xfer_cb  = mscd_control_xfer_cb, | ||||
|     .xfer_cb          = mscd_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_MSC | ||||
|     { | ||||
|         DRIVER_NAME("MSC") | ||||
|         .init             = mscd_init, | ||||
|         .reset            = mscd_reset, | ||||
|         .open             = mscd_open, | ||||
|         .control_xfer_cb  = mscd_control_xfer_cb, | ||||
|         .xfer_cb          = mscd_xfer_cb, | ||||
|         .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_HID | ||||
|   { | ||||
|     DRIVER_NAME("HID") | ||||
|     .init             = hidd_init, | ||||
|     .reset            = hidd_reset, | ||||
|     .open             = hidd_open, | ||||
|     .control_xfer_cb  = hidd_control_xfer_cb, | ||||
|     .xfer_cb          = hidd_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_HID | ||||
|     { | ||||
|       DRIVER_NAME("HID") | ||||
|       .init             = hidd_init, | ||||
|       .reset            = hidd_reset, | ||||
|       .open             = hidd_open, | ||||
|       .control_xfer_cb  = hidd_control_xfer_cb, | ||||
|       .xfer_cb          = hidd_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_AUDIO | ||||
|   { | ||||
|     DRIVER_NAME("AUDIO") | ||||
|     .init             = audiod_init, | ||||
|     .reset            = audiod_reset, | ||||
|     .open             = audiod_open, | ||||
|     .control_xfer_cb  = audiod_control_xfer_cb, | ||||
|     .xfer_cb          = audiod_xfer_cb, | ||||
|     .sof              = audiod_sof_isr | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_AUDIO | ||||
|     { | ||||
|       DRIVER_NAME("AUDIO") | ||||
|       .init             = audiod_init, | ||||
|       .reset            = audiod_reset, | ||||
|       .open             = audiod_open, | ||||
|       .control_xfer_cb  = audiod_control_xfer_cb, | ||||
|       .xfer_cb          = audiod_xfer_cb, | ||||
|       .sof              = audiod_sof_isr | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_VIDEO | ||||
|   { | ||||
|     DRIVER_NAME("VIDEO") | ||||
|     .init             = videod_init, | ||||
|     .reset            = videod_reset, | ||||
|     .open             = videod_open, | ||||
|     .control_xfer_cb  = videod_control_xfer_cb, | ||||
|     .xfer_cb          = videod_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_VIDEO | ||||
|     { | ||||
|       DRIVER_NAME("VIDEO") | ||||
|       .init             = videod_init, | ||||
|       .reset            = videod_reset, | ||||
|       .open             = videod_open, | ||||
|       .control_xfer_cb  = videod_control_xfer_cb, | ||||
|       .xfer_cb          = videod_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_MIDI | ||||
|   { | ||||
|     DRIVER_NAME("MIDI") | ||||
|     .init             = midid_init, | ||||
|     .open             = midid_open, | ||||
|     .reset            = midid_reset, | ||||
|     .control_xfer_cb  = midid_control_xfer_cb, | ||||
|     .xfer_cb          = midid_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_MIDI | ||||
|     { | ||||
|       DRIVER_NAME("MIDI") | ||||
|       .init             = midid_init, | ||||
|       .open             = midid_open, | ||||
|       .reset            = midid_reset, | ||||
|       .control_xfer_cb  = midid_control_xfer_cb, | ||||
|       .xfer_cb          = midid_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_VENDOR | ||||
|   { | ||||
|     DRIVER_NAME("VENDOR") | ||||
|     .init             = vendord_init, | ||||
|     .reset            = vendord_reset, | ||||
|     .open             = vendord_open, | ||||
|     .control_xfer_cb  = tud_vendor_control_xfer_cb, | ||||
|     .xfer_cb          = vendord_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_VENDOR | ||||
|     { | ||||
|       DRIVER_NAME("VENDOR") | ||||
|       .init             = vendord_init, | ||||
|       .reset            = vendord_reset, | ||||
|       .open             = vendord_open, | ||||
|       .control_xfer_cb  = tud_vendor_control_xfer_cb, | ||||
|       .xfer_cb          = vendord_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_USBTMC | ||||
|   { | ||||
|     DRIVER_NAME("TMC") | ||||
|     .init             = usbtmcd_init_cb, | ||||
|     .reset            = usbtmcd_reset_cb, | ||||
|     .open             = usbtmcd_open_cb, | ||||
|     .control_xfer_cb  = usbtmcd_control_xfer_cb, | ||||
|     .xfer_cb          = usbtmcd_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_USBTMC | ||||
|     { | ||||
|       DRIVER_NAME("TMC") | ||||
|       .init             = usbtmcd_init_cb, | ||||
|       .reset            = usbtmcd_reset_cb, | ||||
|       .open             = usbtmcd_open_cb, | ||||
|       .control_xfer_cb  = usbtmcd_control_xfer_cb, | ||||
|       .xfer_cb          = usbtmcd_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_DFU_RUNTIME | ||||
|   { | ||||
|     DRIVER_NAME("DFU-RUNTIME") | ||||
|     .init             = dfu_rtd_init, | ||||
|     .reset            = dfu_rtd_reset, | ||||
|     .open             = dfu_rtd_open, | ||||
|     .control_xfer_cb  = dfu_rtd_control_xfer_cb, | ||||
|     .xfer_cb          = NULL, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_DFU_RUNTIME | ||||
|     { | ||||
|       DRIVER_NAME("DFU-RUNTIME") | ||||
|       .init             = dfu_rtd_init, | ||||
|       .reset            = dfu_rtd_reset, | ||||
|       .open             = dfu_rtd_open, | ||||
|       .control_xfer_cb  = dfu_rtd_control_xfer_cb, | ||||
|       .xfer_cb          = NULL, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_DFU | ||||
|   { | ||||
|     DRIVER_NAME("DFU") | ||||
|     .init             = dfu_moded_init, | ||||
|     .reset            = dfu_moded_reset, | ||||
|     .open             = dfu_moded_open, | ||||
|     .control_xfer_cb  = dfu_moded_control_xfer_cb, | ||||
|     .xfer_cb          = NULL, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_DFU | ||||
|     { | ||||
|       DRIVER_NAME("DFU") | ||||
|       .init             = dfu_moded_init, | ||||
|       .reset            = dfu_moded_reset, | ||||
|       .open             = dfu_moded_open, | ||||
|       .control_xfer_cb  = dfu_moded_control_xfer_cb, | ||||
|       .xfer_cb          = NULL, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM | ||||
|   { | ||||
|     DRIVER_NAME("NET") | ||||
|     .init             = netd_init, | ||||
|     .reset            = netd_reset, | ||||
|     .open             = netd_open, | ||||
|     .control_xfer_cb  = netd_control_xfer_cb, | ||||
|     .xfer_cb          = netd_xfer_cb, | ||||
|     .sof                  = NULL, | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM | ||||
|     { | ||||
|       DRIVER_NAME("NET") | ||||
|       .init             = netd_init, | ||||
|       .reset            = netd_reset, | ||||
|       .open             = netd_open, | ||||
|       .control_xfer_cb  = netd_control_xfer_cb, | ||||
|       .xfer_cb          = netd_xfer_cb, | ||||
|       .sof                  = NULL, | ||||
|     }, | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUD_BTH | ||||
|   { | ||||
|     DRIVER_NAME("BTH") | ||||
|     .init             = btd_init, | ||||
|     .reset            = btd_reset, | ||||
|     .open             = btd_open, | ||||
|     .control_xfer_cb  = btd_control_xfer_cb, | ||||
|     .xfer_cb          = btd_xfer_cb, | ||||
|     .sof              = NULL | ||||
|   }, | ||||
|   #endif | ||||
|     #if CFG_TUD_BTH | ||||
|     { | ||||
|       DRIVER_NAME("BTH") | ||||
|       .init             = btd_init, | ||||
|       .reset            = btd_reset, | ||||
|       .open             = btd_open, | ||||
|       .control_xfer_cb  = btd_control_xfer_cb, | ||||
|       .xfer_cb          = btd_xfer_cb, | ||||
|       .sof              = NULL | ||||
|     }, | ||||
|     #endif | ||||
| }; | ||||
|  | ||||
| enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; | ||||
| @@ -275,7 +280,7 @@ tu_static osal_queue_t _usbd_q; | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) { | ||||
|   bool ret = osal_queue_send(_usbd_q, event, in_isr); | ||||
|   if (tud_event_hook_cb) tud_event_hook_cb(event->rhport, event->event_id, in_isr); | ||||
|   tud_event_hook_cb(event->rhport, event->event_id, in_isr); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @@ -297,27 +302,23 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, | ||||
| // Debug | ||||
| //--------------------------------------------------------------------+ | ||||
| #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL | ||||
| tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = | ||||
| { | ||||
|   "Invalid"        , | ||||
|   "Bus Reset"      , | ||||
|   "Unplugged"      , | ||||
|   "SOF"            , | ||||
|   "Suspend"        , | ||||
|   "Resume"         , | ||||
|   "Setup Received" , | ||||
|   "Xfer Complete"  , | ||||
|   "Func Call" | ||||
| tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { | ||||
|     "Invalid", | ||||
|     "Bus Reset", | ||||
|     "Unplugged", | ||||
|     "SOF", | ||||
|     "Suspend", | ||||
|     "Resume", | ||||
|     "Setup Received", | ||||
|     "Xfer Complete", | ||||
|     "Func Call" | ||||
| }; | ||||
|  | ||||
| // for usbd_control to print the name of control complete driver | ||||
| void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) | ||||
| { | ||||
|   for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) | ||||
|   { | ||||
|     usbd_class_driver_t const * driver = get_driver(i); | ||||
|     if ( driver && driver->control_xfer_cb == callback ) | ||||
|     { | ||||
| void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { | ||||
|   for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { | ||||
|     usbd_class_driver_t const* driver = get_driver(i); | ||||
|     if (driver && driver->control_xfer_cb == callback) { | ||||
|       TU_LOG_USBD("  %s control complete\r\n", driver->name); | ||||
|       return; | ||||
|     } | ||||
| @@ -329,43 +330,36 @@ void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) | ||||
| //--------------------------------------------------------------------+ | ||||
| // Application API | ||||
| //--------------------------------------------------------------------+ | ||||
| tusb_speed_t tud_speed_get(void) | ||||
| { | ||||
| tusb_speed_t tud_speed_get(void) { | ||||
|   return (tusb_speed_t) _usbd_dev.speed; | ||||
| } | ||||
|  | ||||
| bool tud_connected(void) | ||||
| { | ||||
| bool tud_connected(void) { | ||||
|   return _usbd_dev.connected; | ||||
| } | ||||
|  | ||||
| bool tud_mounted(void) | ||||
| { | ||||
| bool tud_mounted(void) { | ||||
|   return _usbd_dev.cfg_num ? true : false; | ||||
| } | ||||
|  | ||||
| bool tud_suspended(void) | ||||
| { | ||||
| bool tud_suspended(void) { | ||||
|   return _usbd_dev.suspended; | ||||
| } | ||||
|  | ||||
| bool tud_remote_wakeup(void) | ||||
| { | ||||
| bool tud_remote_wakeup(void) { | ||||
|   // only wake up host if this feature is supported and enabled and we are suspended | ||||
|   TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); | ||||
|   TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en); | ||||
|   dcd_remote_wakeup(_usbd_rhport); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool tud_disconnect(void) | ||||
| { | ||||
| bool tud_disconnect(void) { | ||||
|   TU_VERIFY(dcd_disconnect); | ||||
|   dcd_disconnect(_usbd_rhport); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool tud_connect(void) | ||||
| { | ||||
| bool tud_connect(void) { | ||||
|   TU_VERIFY(dcd_connect); | ||||
|   dcd_connect(_usbd_rhport); | ||||
|   return true; | ||||
|   | ||||
| @@ -147,7 +147,7 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); | ||||
| TU_ATTR_WEAK void tud_resume_cb(void); | ||||
|  | ||||
| // Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext() | ||||
| TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); | ||||
| void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); | ||||
|  | ||||
| // Invoked when received control request with VENDOR TYPE | ||||
| TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); | ||||
|   | ||||
| @@ -32,24 +32,32 @@ | ||||
| #include "tusb.h" | ||||
| #include "device/usbd_pvt.h" | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Callback weak stubs (called if application does not provide) | ||||
| //--------------------------------------------------------------------+ | ||||
| TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { | ||||
|   (void) rhport; | ||||
|   (void) request; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL | ||||
| extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); | ||||
| #endif | ||||
|  | ||||
| enum | ||||
| { | ||||
| enum { | ||||
|   EDPT_CTRL_OUT = 0x00, | ||||
|   EDPT_CTRL_IN  = 0x80 | ||||
|   EDPT_CTRL_IN = 0x80 | ||||
| }; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
| typedef struct { | ||||
|   tusb_control_request_t request; | ||||
|  | ||||
|   uint8_t* buffer; | ||||
|   uint16_t data_len; | ||||
|   uint16_t total_xferred; | ||||
|  | ||||
|   usbd_control_xfer_cb_t complete_cb; | ||||
| } usbd_control_xfer_t; | ||||
|  | ||||
| @@ -63,20 +71,18 @@ tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // Queue ZLP status transaction | ||||
| static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) | ||||
| { | ||||
| static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const* request) { | ||||
|   // Opposite to endpoint in Data Phase | ||||
|   uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; | ||||
|   return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); | ||||
| } | ||||
|  | ||||
| // Status phase | ||||
| bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) | ||||
| { | ||||
|   _ctrl_xfer.request       = (*request); | ||||
|   _ctrl_xfer.buffer        = NULL; | ||||
| bool tud_control_status(uint8_t rhport, tusb_control_request_t const* request) { | ||||
|   _ctrl_xfer.request = (*request); | ||||
|   _ctrl_xfer.buffer = NULL; | ||||
|   _ctrl_xfer.total_xferred = 0; | ||||
|   _ctrl_xfer.data_len      = 0; | ||||
|   _ctrl_xfer.data_len = 0; | ||||
|  | ||||
|   return _status_stage_xact(rhport, request); | ||||
| } | ||||
| @@ -84,16 +90,15 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) | ||||
| // Queue a transaction in Data Stage | ||||
| // Each transaction has up to Endpoint0's max packet size. | ||||
| // This function can also transfer an zero-length packet | ||||
| static bool _data_stage_xact(uint8_t rhport) | ||||
| { | ||||
|   uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); | ||||
| static bool _data_stage_xact(uint8_t rhport) { | ||||
|   uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, | ||||
|                                      CFG_TUD_ENDPOINT0_SIZE); | ||||
|  | ||||
|   uint8_t ep_addr = EDPT_CTRL_OUT; | ||||
|  | ||||
|   if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) | ||||
|   { | ||||
|   if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { | ||||
|     ep_addr = EDPT_CTRL_IN; | ||||
|     if ( xact_len ) { | ||||
|     if (xact_len) { | ||||
|       TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); | ||||
|     } | ||||
|   } | ||||
| @@ -103,29 +108,24 @@ static bool _data_stage_xact(uint8_t rhport) | ||||
|  | ||||
| // Transmit data to/from the control endpoint. | ||||
| // If the request's wLength is zero, a status packet is sent instead. | ||||
| bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) | ||||
| { | ||||
|   _ctrl_xfer.request       = (*request); | ||||
|   _ctrl_xfer.buffer        = (uint8_t*) buffer; | ||||
| bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, void* buffer, uint16_t len) { | ||||
|   _ctrl_xfer.request = (*request); | ||||
|   _ctrl_xfer.buffer = (uint8_t*) buffer; | ||||
|   _ctrl_xfer.total_xferred = 0U; | ||||
|   _ctrl_xfer.data_len      = tu_min16(len, request->wLength); | ||||
|   _ctrl_xfer.data_len = tu_min16(len, request->wLength); | ||||
|  | ||||
|   if (request->wLength > 0U) | ||||
|   { | ||||
|     if(_ctrl_xfer.data_len > 0U) | ||||
|     { | ||||
|   if (request->wLength > 0U) { | ||||
|     if (_ctrl_xfer.data_len > 0U) { | ||||
|       TU_ASSERT(buffer); | ||||
|     } | ||||
|  | ||||
| //    TU_LOG2("  Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); | ||||
|  | ||||
|     // Data stage | ||||
|     TU_ASSERT( _data_stage_xact(rhport) ); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     TU_ASSERT(_data_stage_xact(rhport)); | ||||
|   } else { | ||||
|     // Status stage | ||||
|     TU_ASSERT( _status_stage_xact(rhport, request) ); | ||||
|     TU_ASSERT(_status_stage_xact(rhport, request)); | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| @@ -134,49 +134,42 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBD API | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| void usbd_control_reset(void); | ||||
| void usbd_control_set_request(tusb_control_request_t const *request); | ||||
| void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); | ||||
| bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); | ||||
| void usbd_control_set_request(tusb_control_request_t const* request); | ||||
| void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp); | ||||
| bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); | ||||
|  | ||||
| void usbd_control_reset(void) | ||||
| { | ||||
| void usbd_control_reset(void) { | ||||
|   tu_varclr(&_ctrl_xfer); | ||||
| } | ||||
|  | ||||
| // Set complete callback | ||||
| void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) | ||||
| { | ||||
| void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) { | ||||
|   _ctrl_xfer.complete_cb = fp; | ||||
| } | ||||
|  | ||||
| // for dcd_set_address where DCD is responsible for status response | ||||
| void usbd_control_set_request(tusb_control_request_t const *request) | ||||
| { | ||||
|   _ctrl_xfer.request       = (*request); | ||||
|   _ctrl_xfer.buffer        = NULL; | ||||
| void usbd_control_set_request(tusb_control_request_t const* request) { | ||||
|   _ctrl_xfer.request = (*request); | ||||
|   _ctrl_xfer.buffer = NULL; | ||||
|   _ctrl_xfer.total_xferred = 0; | ||||
|   _ctrl_xfer.data_len      = 0; | ||||
|   _ctrl_xfer.data_len = 0; | ||||
| } | ||||
|  | ||||
| // callback when a transaction complete on | ||||
| // - DATA stage of control endpoint or | ||||
| // - Status stage | ||||
| bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) | ||||
| { | ||||
| bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { | ||||
|   (void) result; | ||||
|  | ||||
|   // Endpoint Address is opposite to direction bit, this is Status Stage complete event | ||||
|   if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) | ||||
|   { | ||||
|   if (tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction) { | ||||
|     TU_ASSERT(0 == xferred_bytes); | ||||
|  | ||||
|     // invoke optional dcd hook if available | ||||
|     if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); | ||||
|     dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); | ||||
|  | ||||
|     if (_ctrl_xfer.complete_cb) | ||||
|     { | ||||
|     if (_ctrl_xfer.complete_cb) { | ||||
|       // TODO refactor with usbd_driver_print_control_complete_name | ||||
|       _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); | ||||
|     } | ||||
| @@ -184,8 +177,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) | ||||
|   { | ||||
|   if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) { | ||||
|     TU_VERIFY(_ctrl_xfer.buffer); | ||||
|     memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); | ||||
|     TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2); | ||||
| @@ -196,15 +188,14 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result | ||||
|  | ||||
|   // Data Stage is complete when all request's length are transferred or | ||||
|   // a short packet is sent including zero-length packet. | ||||
|   if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) | ||||
|   { | ||||
|   if ((_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || | ||||
|       (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE)) { | ||||
|     // DATA stage is complete | ||||
|     bool is_ok = true; | ||||
|  | ||||
|     // invoke complete callback if set | ||||
|     // callback can still stall control in status phase e.g out data does not make sense | ||||
|     if ( _ctrl_xfer.complete_cb ) | ||||
|     { | ||||
|     if (_ctrl_xfer.complete_cb) { | ||||
|       #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL | ||||
|       usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); | ||||
|       #endif | ||||
| @@ -212,21 +203,17 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result | ||||
|       is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); | ||||
|     } | ||||
|  | ||||
|     if ( is_ok ) | ||||
|     { | ||||
|     if (is_ok) { | ||||
|       // Send status | ||||
|       TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); | ||||
|     }else | ||||
|     { | ||||
|       TU_ASSERT(_status_stage_xact(rhport, &_ctrl_xfer.request)); | ||||
|     } else { | ||||
|       // Stall both IN and OUT control endpoint | ||||
|       dcd_edpt_stall(rhport, EDPT_CTRL_OUT); | ||||
|       dcd_edpt_stall(rhport, EDPT_CTRL_IN); | ||||
|     } | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|   } else { | ||||
|     // More data to transfer | ||||
|     TU_ASSERT( _data_stage_xact(rhport) ); | ||||
|     TU_ASSERT(_data_stage_xact(rhport)); | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
|   | ||||
| @@ -435,9 +435,12 @@ static void hub_port_get_status_complete (tuh_xfer_t* xfer) | ||||
|     // Other changes are: L1 state | ||||
|     // TODO clear change | ||||
|  | ||||
|     // prepare for next hub status | ||||
|     // TODO continue with status_change, or maybe we can do it again with status | ||||
|     hub_edpt_status_xfer(daddr); | ||||
|     else | ||||
|     { | ||||
|       // prepare for next hub status | ||||
|       // TODO continue with status_change, or maybe we can do it again with status | ||||
|       hub_edpt_status_xfer(daddr); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										128
									
								
								src/host/usbh.c
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								src/host/usbh.c
									
									
									
									
									
								
							| @@ -36,7 +36,6 @@ | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBH Configuration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| #ifndef CFG_TUH_TASK_QUEUE_SZ | ||||
|   #define CFG_TUH_TASK_QUEUE_SZ   16 | ||||
| #endif | ||||
| @@ -45,12 +44,19 @@ | ||||
|   #define CFG_TUH_INTERFACE_MAX   8 | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Callback weak stubs (called if application does not provide) | ||||
| //--------------------------------------------------------------------+ | ||||
| TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { | ||||
|   (void) rhport; | ||||
|   (void) eventid; | ||||
|   (void) in_isr; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBH-HCD common data structure | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
| typedef struct { | ||||
|   // port | ||||
|   uint8_t rhport; | ||||
|   uint8_t hub_addr; | ||||
| @@ -112,60 +118,58 @@ typedef struct { | ||||
| //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL | ||||
|   #define DRIVER_NAME(_name)    .name = _name, | ||||
| #else | ||||
|   #define DRIVER_NAME(_name) | ||||
| #endif | ||||
|  | ||||
| static usbh_class_driver_t const usbh_class_drivers[] = | ||||
| { | ||||
|   #if CFG_TUH_CDC | ||||
| static usbh_class_driver_t const usbh_class_drivers[] = { | ||||
|     #if CFG_TUH_CDC | ||||
|     { | ||||
|       DRIVER_NAME("CDC") | ||||
|       .init       = cdch_init, | ||||
|       .open       = cdch_open, | ||||
|       .set_config = cdch_set_config, | ||||
|       .xfer_cb    = cdch_xfer_cb, | ||||
|       .close      = cdch_close | ||||
|         DRIVER_NAME("CDC") | ||||
|         .init       = cdch_init, | ||||
|         .open       = cdch_open, | ||||
|         .set_config = cdch_set_config, | ||||
|         .xfer_cb    = cdch_xfer_cb, | ||||
|         .close      = cdch_close | ||||
|     }, | ||||
|   #endif | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUH_MSC | ||||
|     #if CFG_TUH_MSC | ||||
|     { | ||||
|       DRIVER_NAME("MSC") | ||||
|       .init       = msch_init, | ||||
|       .open       = msch_open, | ||||
|       .set_config = msch_set_config, | ||||
|       .xfer_cb    = msch_xfer_cb, | ||||
|       .close      = msch_close | ||||
|         DRIVER_NAME("MSC") | ||||
|         .init       = msch_init, | ||||
|         .open       = msch_open, | ||||
|         .set_config = msch_set_config, | ||||
|         .xfer_cb    = msch_xfer_cb, | ||||
|         .close      = msch_close | ||||
|     }, | ||||
|   #endif | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUH_HID | ||||
|     #if CFG_TUH_HID | ||||
|     { | ||||
|       DRIVER_NAME("HID") | ||||
|       .init       = hidh_init, | ||||
|       .open       = hidh_open, | ||||
|       .set_config = hidh_set_config, | ||||
|       .xfer_cb    = hidh_xfer_cb, | ||||
|       .close      = hidh_close | ||||
|         DRIVER_NAME("HID") | ||||
|         .init       = hidh_init, | ||||
|         .open       = hidh_open, | ||||
|         .set_config = hidh_set_config, | ||||
|         .xfer_cb    = hidh_xfer_cb, | ||||
|         .close      = hidh_close | ||||
|     }, | ||||
|   #endif | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUH_HUB | ||||
|     #if CFG_TUH_HUB | ||||
|     { | ||||
|       DRIVER_NAME("HUB") | ||||
|       .init       = hub_init, | ||||
|       .open       = hub_open, | ||||
|       .set_config = hub_set_config, | ||||
|       .xfer_cb    = hub_xfer_cb, | ||||
|       .close      = hub_close | ||||
|         DRIVER_NAME("HUB") | ||||
|         .init       = hub_init, | ||||
|         .open       = hub_open, | ||||
|         .set_config = hub_set_config, | ||||
|         .xfer_cb    = hub_xfer_cb, | ||||
|         .close      = hub_close | ||||
|     }, | ||||
|   #endif | ||||
|     #endif | ||||
|  | ||||
|   #if CFG_TUH_VENDOR | ||||
|     #if CFG_TUH_VENDOR | ||||
|     { | ||||
|       DRIVER_NAME("VENDOR") | ||||
|       .init       = cush_init, | ||||
| @@ -173,7 +177,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = | ||||
|       .xfer_cb    = cush_isr, | ||||
|       .close      = cush_close | ||||
|     } | ||||
|   #endif | ||||
|     #endif | ||||
| }; | ||||
|  | ||||
| enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; | ||||
| @@ -233,8 +237,7 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; | ||||
| // Control transfers: since most controllers do not support multiple control transfers | ||||
| // on multiple devices concurrently and control transfers are not used much except for | ||||
| // enumeration, we will only execute control transfers one at a time. | ||||
| CFG_TUH_MEM_SECTION struct | ||||
| { | ||||
| CFG_TUH_MEM_SECTION struct { | ||||
|   CFG_TUH_MEM_ALIGN tusb_control_request_t request; | ||||
|   uint8_t* buffer; | ||||
|   tuh_xfer_cb_t complete_cb; | ||||
| @@ -268,7 +271,7 @@ TU_ATTR_WEAK void osal_task_delay(uint32_t msec) { | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { | ||||
|   bool ret = osal_queue_send(_usbh_q, event, in_isr); | ||||
|   if (tuh_event_hook_cb) tuh_event_hook_cb(event->rhport, event->event_id, in_isr); | ||||
|   tuh_event_hook_cb(event->rhport, event->event_id, in_isr); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @@ -367,17 +370,14 @@ bool tuh_init(uint8_t controller_id) { | ||||
|   tu_memclr(_usbh_devices, sizeof(_usbh_devices)); | ||||
|   tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); | ||||
|  | ||||
|   for(uint8_t i=0; i<TOTAL_DEVICES; i++) | ||||
|   { | ||||
|   for(uint8_t i=0; i<TOTAL_DEVICES; i++) { | ||||
|     clear_device(&_usbh_devices[i]); | ||||
|   } | ||||
|  | ||||
|   // Class drivers | ||||
|   for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) | ||||
|   { | ||||
|     usbh_class_driver_t const * driver = get_driver(drv_id); | ||||
|     if ( driver ) | ||||
|     { | ||||
|   for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { | ||||
|     usbh_class_driver_t const* driver = get_driver(drv_id); | ||||
|     if (driver) { | ||||
|       TU_LOG_USBH("%s init\r\n", driver->name); | ||||
|       driver->init(); | ||||
|     } | ||||
| @@ -456,7 +456,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { | ||||
|  | ||||
|         #if CFG_TUH_HUB | ||||
|         // TODO remove | ||||
|         if ( event.connection.hub_addr != 0) { | ||||
|         if ( event.connection.hub_addr != 0 && event.connection.hub_port != 0) { | ||||
|           // done with hub, waiting for next data on status pipe | ||||
|           (void) hub_edpt_status_xfer( event.connection.hub_addr ); | ||||
|         } | ||||
| @@ -545,8 +545,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { | ||||
| // Control transfer | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| static void _control_blocking_complete_cb(tuh_xfer_t* xfer) | ||||
| { | ||||
| static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { | ||||
|   // update result | ||||
|   *((xfer_result_t*) xfer->user_data) = xfer->result; | ||||
| } | ||||
| @@ -625,21 +624,18 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) | ||||
| { | ||||
| TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { | ||||
|   (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); | ||||
|   _ctrl_xfer.stage = stage; | ||||
|   (void) osal_mutex_unlock(_usbh_mutex); | ||||
| } | ||||
|  | ||||
| static void _xfer_complete(uint8_t daddr, xfer_result_t result) | ||||
| { | ||||
| static void _xfer_complete(uint8_t daddr, xfer_result_t result) { | ||||
|   TU_LOG_USBH("\r\n"); | ||||
|  | ||||
|   // duplicate xfer since user can execute control transfer within callback | ||||
|   tusb_control_request_t const request = _ctrl_xfer.request; | ||||
|   tuh_xfer_t xfer_temp = | ||||
|   { | ||||
|   tuh_xfer_t xfer_temp = { | ||||
|     .daddr       = daddr, | ||||
|     .ep_addr     = 0, | ||||
|     .result      = result, | ||||
| @@ -652,8 +648,7 @@ static void _xfer_complete(uint8_t daddr, xfer_result_t result) | ||||
|  | ||||
|   _set_control_xfer_stage(CONTROL_STAGE_IDLE); | ||||
|  | ||||
|   if (xfer_temp.complete_cb) | ||||
|   { | ||||
|   if (xfer_temp.complete_cb) { | ||||
|     xfer_temp.complete_cb(&xfer_temp); | ||||
|   } | ||||
| } | ||||
| @@ -710,17 +705,16 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result | ||||
| // | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| bool tuh_edpt_xfer(tuh_xfer_t* xfer) | ||||
| { | ||||
|   uint8_t const daddr   = xfer->daddr; | ||||
| bool tuh_edpt_xfer(tuh_xfer_t* xfer) { | ||||
|   uint8_t const daddr = xfer->daddr; | ||||
|   uint8_t const ep_addr = xfer->ep_addr; | ||||
|  | ||||
|   TU_VERIFY(daddr && ep_addr); | ||||
|  | ||||
|   TU_VERIFY(usbh_edpt_claim(daddr, ep_addr)); | ||||
|  | ||||
|   if ( !usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, (uint16_t) xfer->buflen, xfer->complete_cb, xfer->user_data) ) | ||||
|   { | ||||
|   if (!usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, (uint16_t) xfer->buflen, | ||||
|                                     xfer->complete_cb, xfer->user_data)) { | ||||
|     usbh_edpt_release(daddr, ep_addr); | ||||
|     return false; | ||||
|   } | ||||
|   | ||||
| @@ -94,7 +94,7 @@ TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); | ||||
| TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); | ||||
|  | ||||
| // Invoked when there is a new usb event, which need to be processed by tuh_task()/tuh_task_ext() | ||||
| TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); | ||||
| void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // APPLICATION API | ||||
|   | ||||
| @@ -157,6 +157,7 @@ static ohci_ed_t * const p_ed_head[] = | ||||
|  | ||||
| static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); | ||||
| static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); | ||||
| static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBH-HCD API | ||||
| @@ -345,7 +346,7 @@ static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) | ||||
|   tu_memclr(p_td, sizeof(ohci_gtd_t)); | ||||
|  | ||||
|   p_td->used = 1; | ||||
|   p_td->expected_bytes = total_bytes; | ||||
|   gtd_get_extra_data(p_td)->expected_bytes = total_bytes; | ||||
|  | ||||
|   p_td->buffer_rounding = 1; // less than queued length is not a error | ||||
|   p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO; | ||||
| @@ -610,6 +611,15 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) | ||||
|   } | ||||
| } | ||||
|  | ||||
| static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { | ||||
|   if ( gtd_is_control(gtd) ) { | ||||
|     uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]); | ||||
|     return &ohci_data.gtd_extra_control[idx]; | ||||
|   }else { | ||||
|     return &ohci_data.gtd_extra[gtd - ohci_data.gtd_pool]; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) | ||||
| { | ||||
|   // 5.2.9 OHCI sample code | ||||
| @@ -641,8 +651,7 @@ static void done_queue_isr(uint8_t hostid) | ||||
|     if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) | ||||
|     { | ||||
|       ohci_ed_t * const ed  = gtd_get_ed(qtd); | ||||
|  | ||||
|       uint32_t const xferred_bytes = qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); | ||||
|       uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); | ||||
|  | ||||
|       // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. | ||||
|       // When there is a error resulting this ED is halted, and this EP still has other queued TD | ||||
| @@ -651,7 +660,7 @@ static void done_queue_isr(uint8_t hostid) | ||||
|       // --> HC will not process Control list (due to service ratio when Bulk list not empty) | ||||
|       // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt | ||||
|       // the TailP must be set back to NULL for processing remaining TDs | ||||
|       if ((event != XFER_RESULT_SUCCESS)) | ||||
|       if (event != XFER_RESULT_SUCCESS) | ||||
|       { | ||||
|         ed->td_tail &= 0x0Ful; | ||||
|         ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue | ||||
|   | ||||
| @@ -45,6 +45,9 @@ enum { | ||||
| #define ED_MAX       (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX) | ||||
| #define GTD_MAX      ED_MAX | ||||
|  | ||||
| // tinyUSB's OHCI implementation caps number of EDs to 8 bits | ||||
| TU_VERIFY_STATIC (ED_MAX <= 256, "Reduce CFG_TUH_DEVICE_MAX or CFG_TUH_ENDPOINT_MAX"); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // OHCI Data Structure | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -70,9 +73,8 @@ typedef struct TU_ATTR_ALIGNED(16) | ||||
| { | ||||
| 	// Word 0 | ||||
| 	uint32_t used                    : 1; | ||||
| 	uint32_t index                   : 4;  // endpoint index the td belongs to, or device address in case of control xfer | ||||
|   uint32_t expected_bytes          : 13; // TODO available for hcd | ||||
|  | ||||
|   uint32_t index                   : 8; // endpoint index the gtd belongs to, or device address in case of control xfer | ||||
|   uint32_t                         : 9; // can be used | ||||
|   uint32_t buffer_rounding         : 1; | ||||
|   uint32_t pid                     : 2; | ||||
|   uint32_t delay_interrupt         : 3; | ||||
| @@ -152,9 +154,12 @@ typedef struct TU_ATTR_ALIGNED(32) | ||||
|  | ||||
| TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); | ||||
|  | ||||
| typedef struct { | ||||
|   uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits | ||||
| } gtd_extra_data_t; | ||||
|  | ||||
| // structure with member alignment required from large to small | ||||
| typedef struct TU_ATTR_ALIGNED(256) | ||||
| { | ||||
| typedef struct TU_ATTR_ALIGNED(256) { | ||||
|   ohci_hcca_t hcca; | ||||
|  | ||||
|   ohci_ed_t bulk_head_ed; // static bulk head (dummy) | ||||
| @@ -164,14 +169,17 @@ typedef struct TU_ATTR_ALIGNED(256) | ||||
|   struct { | ||||
|     ohci_ed_t ed; | ||||
|     ohci_gtd_t gtd; | ||||
|   }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; | ||||
|   } control[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1]; | ||||
|  | ||||
|   //  ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 | ||||
|   ohci_ed_t ed_pool[ED_MAX]; | ||||
|   ohci_gtd_t gtd_pool[GTD_MAX]; | ||||
|  | ||||
|   volatile uint16_t frame_number_hi; | ||||
|   // extra data needed by TDs that can't fit in the TD struct | ||||
|   gtd_extra_data_t gtd_extra_control[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1]; | ||||
|   gtd_extra_data_t gtd_extra[GTD_MAX]; | ||||
|  | ||||
|   volatile uint16_t frame_number_hi; | ||||
| } ohci_data_t; | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
|   | ||||
| @@ -128,8 +128,8 @@ | ||||
| #  define DCD_STM32_BTABLE_BASE 0U | ||||
| #endif | ||||
|  | ||||
| #ifndef DCD_STM32_BTABLE_LENGTH | ||||
| #  define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) | ||||
| #ifndef DCD_STM32_BTABLE_SIZE | ||||
| #  define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE) | ||||
| #endif | ||||
|  | ||||
| /*************************************************** | ||||
| @@ -137,7 +137,7 @@ | ||||
|  */ | ||||
|  | ||||
| TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT, "Only 8 endpoints supported on the hardware"); | ||||
| TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LENGTH), "BTABLE does not fit in PMA RAM"); | ||||
| TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_SIZE)) <= (FSDEV_PMA_SIZE), "BTABLE does not fit in PMA RAM"); | ||||
| TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -559,7 +559,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) | ||||
|       // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) | ||||
|       pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); | ||||
|       pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|       dcd_event_setup_received(0, (uint8_t*)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); | ||||
| #else | ||||
|       // The setup_received function uses memcpy, so this must first copy the setup data into | ||||
| @@ -673,13 +673,13 @@ void dcd_int_handler(uint8_t rhport) { | ||||
|  | ||||
|   /* 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) { | ||||
|     USB->ISTR &=~USB_ISTR_SOF; | ||||
|     USB->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; | ||||
|     dcd_event_sof(0, USB->FNR & USB_FNR_FN, true); | ||||
|   } | ||||
|  | ||||
|   if(int_status & USB_ISTR_RESET) { | ||||
|     // USBRST is start of reset. | ||||
|     USB->ISTR &=~USB_ISTR_RESET; | ||||
|     USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; | ||||
|     dcd_handle_bus_reset(); | ||||
|     dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); | ||||
|     return; // Don't do the rest of the things here; perhaps they've been cleared? | ||||
| @@ -697,7 +697,7 @@ void dcd_int_handler(uint8_t rhport) { | ||||
|     USB->CNTR &= ~USB_CNTR_LPMODE; | ||||
|     USB->CNTR &= ~USB_CNTR_FSUSP; | ||||
|  | ||||
|     USB->ISTR &=~USB_ISTR_WKUP; | ||||
|     USB->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; | ||||
|     dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); | ||||
|   } | ||||
|  | ||||
| @@ -711,7 +711,7 @@ void dcd_int_handler(uint8_t rhport) { | ||||
|     USB->CNTR |= USB_CNTR_LPMODE; | ||||
|  | ||||
|     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ | ||||
|     USB->ISTR &=~USB_ISTR_SUSP; | ||||
|     USB->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; | ||||
|     dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); | ||||
|   } | ||||
|  | ||||
| @@ -724,7 +724,7 @@ void dcd_int_handler(uint8_t rhport) { | ||||
|     { | ||||
|       remoteWakeCountdown--; | ||||
|     } | ||||
|     USB->ISTR &=~USB_ISTR_ESOF; | ||||
|     USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -786,7 +786,7 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length) | ||||
|   } | ||||
|  | ||||
|   // Ensure allocated buffer is aligned | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   length = (length + 3) & ~0x03; | ||||
| #else | ||||
|   length = (length + 1) & ~0x01; | ||||
| @@ -798,7 +798,7 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length) | ||||
|   ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer | ||||
|  | ||||
|   // Verify no overflow | ||||
|   TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF); | ||||
|   TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF); | ||||
|  | ||||
|   epXferCtl->pma_ptr = addr; | ||||
|   epXferCtl->pma_alloc_size = length; | ||||
| @@ -1227,7 +1227,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) | ||||
|   } | ||||
| } | ||||
|  | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
| static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) | ||||
| { | ||||
|   const uint8_t* srcVal = src; | ||||
| @@ -1283,7 +1283,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui | ||||
|   __IO uint16_t *pdwVal; | ||||
|  | ||||
|   srcVal = src; | ||||
|   pdwVal = &pma[PMA_STRIDE*(dst>>1)]; | ||||
|   pdwVal = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; | ||||
|  | ||||
|   while (n--) | ||||
|   { | ||||
| @@ -1291,7 +1291,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui | ||||
|     srcVal++; | ||||
|     temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)) ; | ||||
|     *pdwVal = temp2; | ||||
|     pdwVal += PMA_STRIDE; | ||||
|     pdwVal += FSDEV_PMA_STRIDE; | ||||
|     srcVal++; | ||||
|   } | ||||
|  | ||||
| @@ -1323,7 +1323,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN | ||||
|   // 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 PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   if((cnt_lin & 0x03) && cnt_wrap) | ||||
|   { | ||||
|     // Copy first linear part | ||||
| @@ -1386,7 +1386,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
| static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) | ||||
| { | ||||
|   uint8_t* dstVal = dst; | ||||
| @@ -1434,13 +1434,13 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t | ||||
|   __IO const uint16_t *pdwVal; | ||||
|   uint32_t temp; | ||||
|  | ||||
|   pdwVal = &pma[PMA_STRIDE*(src>>1)]; | ||||
|   pdwVal = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; | ||||
|   uint8_t *dstVal = (uint8_t*)dst; | ||||
|  | ||||
|   while (n--) | ||||
|   { | ||||
|     temp = *pdwVal; | ||||
|     pdwVal += PMA_STRIDE; | ||||
|     pdwVal += FSDEV_PMA_STRIDE; | ||||
|     *dstVal++ = ((temp >> 0) & 0xFF); | ||||
|     *dstVal++ = ((temp >> 8) & 0xFF); | ||||
|   } | ||||
| @@ -1448,7 +1448,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t | ||||
|   if (wNBytes & 0x01) | ||||
|   { | ||||
|     temp = *pdwVal; | ||||
|     pdwVal += PMA_STRIDE; | ||||
|     pdwVal += FSDEV_PMA_STRIDE; | ||||
|     *dstVal++ = ((temp >> 0) & 0xFF); | ||||
|   } | ||||
|   return true; | ||||
| @@ -1475,7 +1475,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB | ||||
|   // 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 PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   if((cnt_lin & 0x03) && cnt_wrap) | ||||
|   { | ||||
|     // Copy first linear part | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
|  | ||||
| // This file contains source copied from ST's HAL, and thus should have their copyright statement. | ||||
|  | ||||
| // PMA_LENGTH is PMA buffer size in bytes. | ||||
| // FSDEV_PMA_SIZE is PMA buffer size in bytes. | ||||
| // On 512-byte devices, access with a stride of two words (use every other 16-bit address) | ||||
| // On 1024-byte devices, access with a stride of one word (use every 16-bit address) | ||||
|  | ||||
| @@ -37,7 +37,7 @@ | ||||
|  | ||||
| #if CFG_TUSB_MCU == OPT_MCU_STM32F0 | ||||
|   #include "stm32f0xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|   // F0x2 models are crystal-less | ||||
|   // All have internal D+ pull-up | ||||
|   // 070RB:    2 x 16 bits/word memory     LPM Support, BCD Support | ||||
| @@ -45,7 +45,7 @@ | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 | ||||
|   #include "stm32f1xx.h" | ||||
|   #define PMA_LENGTH (512u) | ||||
|   #define FSDEV_PMA_SIZE (512u) | ||||
|   // NO internal Pull-ups | ||||
|   //         *B, and *C:    2 x 16 bits/word | ||||
|  | ||||
| @@ -56,7 +56,7 @@ | ||||
|       defined(STM32F303xB) || defined(STM32F303xC) || \ | ||||
|       defined(STM32F373xC) | ||||
|   #include "stm32f3xx.h" | ||||
|   #define PMA_LENGTH (512u) | ||||
|   #define FSDEV_PMA_SIZE (512u) | ||||
|   // NO internal Pull-ups | ||||
|   //         *B, and *C:    1 x 16 bits/word | ||||
|   // PMA dedicated to USB (no sharing with CAN) | ||||
| @@ -65,27 +65,27 @@ | ||||
|       defined(STM32F302xD) || defined(STM32F302xE) || \ | ||||
|       defined(STM32F303xD) || defined(STM32F303xE) | ||||
|   #include "stm32f3xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|   // NO internal Pull-ups | ||||
|   // *6, *8, *D, and *E:    2 x 16 bits/word     LPM Support | ||||
|   // When CAN clock is enabled, USB can use first 768 bytes ONLY. | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 | ||||
|   #include "stm32l0xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 | ||||
|   #include "stm32l1xx.h" | ||||
|   #define PMA_LENGTH (512u) | ||||
|   #define FSDEV_PMA_SIZE (512u) | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32G4 | ||||
|   #include "stm32g4xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 | ||||
|   #include "stm32g0xx.h" | ||||
|   #define PMA_32BIT_ACCESS | ||||
|   #define PMA_LENGTH (2048u) | ||||
|   #define FSDEV_BUS_32BIT | ||||
|   #define FSDEV_PMA_SIZE (2048u) | ||||
|   #undef USB_PMAADDR | ||||
|   #define USB_PMAADDR USB_DRD_PMAADDR | ||||
|   #define USB_TypeDef USB_DRD_TypeDef | ||||
| @@ -112,8 +112,8 @@ | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 | ||||
|   #include "stm32h5xx.h" | ||||
|   #define PMA_32BIT_ACCESS | ||||
|   #define PMA_LENGTH (2048u) | ||||
|   #define FSDEV_BUS_32BIT | ||||
|   #define FSDEV_PMA_SIZE (2048u) | ||||
|   #undef USB_PMAADDR | ||||
|   #define USB_PMAADDR USB_DRD_PMAADDR | ||||
|   #define USB_TypeDef USB_DRD_TypeDef | ||||
| @@ -141,18 +141,18 @@ | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32WB | ||||
|   #include "stm32wbxx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|   /* ST provided header has incorrect value */ | ||||
|   #undef USB_PMAADDR | ||||
|   #define USB_PMAADDR USB1_PMAADDR | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 | ||||
|   #include "stm32l4xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 | ||||
|   #include "stm32l5xx.h" | ||||
|   #define PMA_LENGTH (1024u) | ||||
|   #define FSDEV_PMA_SIZE (1024u) | ||||
|  | ||||
|   #ifndef USB_PMAADDR | ||||
|     #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) | ||||
| @@ -164,24 +164,28 @@ | ||||
| #endif | ||||
|  | ||||
| // For purposes of accessing the packet | ||||
| #if ((PMA_LENGTH) == 512u) | ||||
|   #define PMA_STRIDE  (2u) | ||||
| #elif ((PMA_LENGTH) == 1024u) | ||||
|   #define PMA_STRIDE  (1u) | ||||
| #if ((FSDEV_PMA_SIZE) == 512u) | ||||
|   #define FSDEV_PMA_STRIDE  (2u) | ||||
| #elif ((FSDEV_PMA_SIZE) == 1024u) | ||||
|   #define FSDEV_PMA_STRIDE  (1u) | ||||
| #endif | ||||
|  | ||||
| // The fsdev_bus_t type can be used for both register and PMA access necessities | ||||
| // For type-safety create a new macro for the volatile address of PMAADDR | ||||
| // The compiler should warn us if we cast it to a non-volatile type? | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
| typedef uint32_t fsdev_bus_t; | ||||
| static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; | ||||
|  | ||||
| #else | ||||
| typedef uint16_t fsdev_bus_t; | ||||
| // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) | ||||
| static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) | ||||
| { | ||||
|   size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; | ||||
|   total_word_offset *= PMA_STRIDE; | ||||
|   total_word_offset *= FSDEV_PMA_STRIDE; | ||||
|   return &(pma[total_word_offset]); | ||||
| } | ||||
|  | ||||
| @@ -212,7 +216,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si | ||||
| /* SetENDPOINT */ | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); | ||||
|   *reg = wRegValue; | ||||
| @@ -224,7 +228,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, ui | ||||
|  | ||||
| /* GetENDPOINT */ | ||||
| TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); | ||||
| #else | ||||
| @@ -279,7 +283,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, | ||||
|   */ | ||||
| TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; | ||||
| #else | ||||
| @@ -290,7 +294,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USB | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; | ||||
| #else | ||||
| @@ -317,7 +321,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   return pma32[2*bEpIdx] & 0x0000FFFFu ; | ||||
| #else | ||||
| @@ -327,7 +331,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   return pma32[2*bEpIdx + 1] & 0x0000FFFFu; | ||||
| #else | ||||
| @@ -337,7 +341,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); | ||||
| #else | ||||
| @@ -347,7 +351,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USB | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); | ||||
| #else | ||||
| @@ -357,7 +361,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USB | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); | ||||
| #else | ||||
| @@ -368,7 +372,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, u | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) | ||||
| { | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); | ||||
| #else | ||||
| @@ -380,7 +384,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, u | ||||
| TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t blocksize, uint32_t numblocks) | ||||
| { | ||||
|   /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ | ||||
| #ifdef PMA_32BIT_ACCESS | ||||
| #ifdef FSDEV_BUS_32BIT | ||||
|   (void) USBx; | ||||
|   pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); | ||||
| #else | ||||
|   | ||||
| @@ -149,7 +149,7 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { | ||||
|     // https://community.st.com/t5/stm32cubemx-mcus/why-stm32h743-usb-fs-doesn-t-work-if-freertos-tickless-idle/m-p/349480#M18867 | ||||
|     // H7 running on full-speed phy need to disable ULPI clock in sleep mode. | ||||
|     // Otherwise, USB won't work when mcu executing WFI/WFE instruction i.e tick-less RTOS. | ||||
|     // Note: there may be other family that is affected by this, but only H7 is tested so far | ||||
|     // Note: there may be other family that is affected by this, but only H7 and F7 is tested so far | ||||
|     #if defined(USB_OTG_FS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB2OTGFSULPILPEN) | ||||
|     if ( USB_OTG_FS_PERIPH_BASE == (uint32_t) dwc2 ) { | ||||
|       RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB2OTGFSULPILPEN; | ||||
| @@ -161,6 +161,13 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { | ||||
|       RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB1OTGHSULPILPEN; | ||||
|     } | ||||
|     #endif | ||||
|  | ||||
|     #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_OTGHSULPILPEN) | ||||
|     if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) { | ||||
|       RCC->AHB1LPENR &= ~RCC_AHB1LPENR_OTGHSULPILPEN; | ||||
|     } | ||||
|     #endif | ||||
|  | ||||
|   } else { | ||||
| #if CFG_TUSB_MCU != OPT_MCU_STM32U5 | ||||
|     // Disable FS PHY, TODO on U5A5 (dwc2 4.11a) 16th bit is 'Host CDP behavior enable' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach