Merge branch 'master' into cdc_ch34x_support

This commit is contained in:
hathach
2024-01-15 16:17:42 +07:00
33 changed files with 988 additions and 701 deletions

View File

@@ -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));

View File

@@ -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 */ \

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
//--------------------------------------------------------------------+

View File

@@ -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

View File

@@ -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

View File

@@ -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'