From 6e463caec046dbba754a2fae4d0f80a3e6665ee7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 15 Nov 2013 16:47:26 +0700 Subject: [PATCH] add semaphore for control xfer for > 64 support for some mcu such as lpc11u/lpc17xx --- demos/device/device_os_none/tusb_config.h | 3 +- tinyusb/device/dcd_lpc_11uxx_13uxx.c | 24 +++--- tinyusb/device/usbd.c | 89 +++++++++++++++-------- tinyusb/device/usbd_dcd.h | 1 + 4 files changed, 73 insertions(+), 44 deletions(-) diff --git a/demos/device/device_os_none/tusb_config.h b/demos/device/device_os_none/tusb_config.h index c3a8bc6dd..1ee286cdb 100644 --- a/demos/device/device_os_none/tusb_config.h +++ b/demos/device/device_os_none/tusb_config.h @@ -85,9 +85,8 @@ #define TUSB_CFG_DEVICE_HID_MOUSE 1 #define TUSB_CFG_DEVICE_HID_GENERIC 0 #define TUSB_CFG_DEVICE_MSC 0 -#define TUSB_CFG_DEVICE_CDC 0 +#define TUSB_CFG_DEVICE_CDC 1 -// TODO LPC11UXX seems not able to DMA > 64 bytes control transfer while LPC13uxx has no problem with that //--------------------------------------------------------------------+ // COMMON CONFIGURATION diff --git a/tinyusb/device/dcd_lpc_11uxx_13uxx.c b/tinyusb/device/dcd_lpc_11uxx_13uxx.c index 164ea834f..72171405a 100644 --- a/tinyusb/device/dcd_lpc_11uxx_13uxx.c +++ b/tinyusb/device/dcd_lpc_11uxx_13uxx.c @@ -241,7 +241,17 @@ void dcd_isr(uint8_t coreid) LPC_USB->DEVCMDSTAT |= CMDSTAT_MASK_SETUP_RECEIVED; dcd_data.qhd[0][1].buff_addr_offset = addr_offset(&dcd_data.setup_request); + } + else if ( int_status & 0x03 ) + { // either control endpoints + endpoint_handle_t edpt_hdl = + { + .coreid = coreid, + .index = BIT_TEST_(int_status, 1) ? 1 : 0 + }; + // FIXME xferred_byte for control xfer is not needed now !!! + usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0); } //------------- Non-Control Endpoints -------------// @@ -265,6 +275,7 @@ void dcd_isr(uint8_t coreid) LPC_USB->EPBUFCFG = BIT_CLR_(LPC_USB->EPBUFCFG , ep_id); // clear double buffering // TODO no way determine if the transfer is failed or not + // FIXME xferred_byte is not correct usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.expected_bytes[ep_id] - dcd_data.qhd[ep_id][0].total_bytes); // only number of bytes in the IOC qtd } @@ -283,19 +294,6 @@ void dcd_pipe_control_stall(uint8_t coreid) dcd_data.qhd[0][0].stall = dcd_data.qhd[1][0].stall = 1; } -// used for data phase only -//tusb_error_t dcd_pipe_control_queue_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length) -//{ -// (void) coreid; -// -// uint8_t const ep_id = dir; // IN : 1, OUT = 0 -// -// dcd_data.qhd[ep_id][0].buff_addr_offset = (length ? addr_offset(p_buffer) : 0 ); -// dcd_data.qhd[ep_id][0].total_bytes = length; -// -//} - -// can be data phase (long data) or status phase tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length) { (void) coreid; diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index b2708251e..5c10f9c5e 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -49,6 +49,13 @@ #include "tusb_descriptors.h" // TODO callback include #include "usbd_dcd.h" +// Some MCUs cannot transfer more than 64 bytes each queue, thus require special task-alike treatment +#if MCU == MCU_LPC11UXX + #define USBD_CONTROL_ONE_PACKET_EACH_XFER // for each Transfer, cannot queue more than packet size + enum { + USBD_COTNROL_MAX_LENGTH_EACH_XFER = 64 + }; +#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -127,75 +134,92 @@ typedef struct { OSAL_TASK_DEF(usbd_task, 150, TUSB_CFG_OS_TASK_PRIO); OSAL_QUEUE_DEF(usbd_queue_def, USBD_TASK_QUEUE_DEPTH, usbd_task_event_t); +OSAL_SEM_DEF(usbd_control_xfer_semaphore_def); static osal_queue_handle_t usbd_queue_hdl; +static osal_semaphore_handle_t usbd_control_xfer_sem_hdl; tusb_error_t usbd_body_subtask(void) { OSAL_SUBTASK_BEGIN + static uint8_t coreid; tusb_error_t error = TUSB_ERROR_NONE; usbd_task_event_t event; osal_queue_receive(usbd_queue_hdl, &event, OSAL_TIMEOUT_WAIT_FOREVER, &error); SUBTASK_ASSERT_STATUS(error); + coreid = event.coreid; + if ( USBD_EVENTID_SETUP_RECEIVED == event.event_id ) - { - usbd_device_info_t *p_device = &usbd_devices[event.coreid]; - tusb_control_request_t* p_request = &p_device->control_request; + { // should copy to setup packet to local variable as the new one may overwrite while we processing here + static tusb_control_request_t control_request; + control_request = usbd_devices[coreid].control_request; //------------- Standard Control such as those in enumeration -------------// - if( TUSB_REQUEST_RECIPIENT_DEVICE == p_request->bmRequestType_bit.recipient && - TUSB_REQUEST_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + if( TUSB_REQUEST_RECIPIENT_DEVICE == control_request.bmRequestType_bit.recipient && + TUSB_REQUEST_TYPE_STANDARD == control_request.bmRequestType_bit.type ) { - if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest ) + if ( TUSB_REQUEST_GET_DESCRIPTOR == control_request.bRequest ) { static uint8_t const * p_buffer = NULL; static uint16_t length = 0; - error = get_descriptor_subtask(event.coreid, p_request, &p_buffer, &length); + error = get_descriptor_subtask(coreid, &control_request, &p_buffer, &length); - dcd_pipe_control_xfer(event.coreid, p_request->bmRequestType_bit.direction, p_buffer, length); // zero length +#ifdef USBD_CONTROL_ONE_PACKET_EACH_XFER + while ( length > USBD_COTNROL_MAX_LENGTH_EACH_XFER && error == TUSB_ERROR_NONE ) + { + usbd_devices[coreid].is_waiting_control_xfer = true; + + dcd_pipe_control_xfer(coreid, control_request.bmRequestType_bit.direction, p_buffer, USBD_COTNROL_MAX_LENGTH_EACH_XFER); // zero length + osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + + length -= USBD_COTNROL_MAX_LENGTH_EACH_XFER; + p_buffer += USBD_COTNROL_MAX_LENGTH_EACH_XFER; + } + usbd_devices[coreid].is_waiting_control_xfer = false; +#endif + + if ( TUSB_ERROR_NONE == error ) + { + dcd_pipe_control_xfer(coreid, control_request.bmRequestType_bit.direction, p_buffer, length); // zero length + } } - else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest ) + else if ( TUSB_REQUEST_SET_ADDRESS == control_request.bRequest ) { - dcd_controller_set_address(event.coreid, (uint8_t) p_request->wValue); - p_device->state = TUSB_DEVICE_STATE_ADDRESSED; + dcd_controller_set_address(coreid, (uint8_t) control_request.wValue); + usbd_devices[coreid].state = TUSB_DEVICE_STATE_ADDRESSED; } - else if ( TUSB_REQUEST_SET_CONFIGURATION == p_request->bRequest ) + else if ( TUSB_REQUEST_SET_CONFIGURATION == control_request.bRequest ) { - usbd_set_configure_received(event.coreid, (uint8_t) p_request->wValue); + usbd_set_configure_received(coreid, (uint8_t) control_request.wValue); }else { error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; } } //------------- Class/Interface Specific Request -------------// - else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == p_request->bmRequestType_bit.recipient) + else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == control_request.bmRequestType_bit.recipient) { - tusb_std_class_code_t class_code = p_device->interface2class[ u16_low_u8(p_request->wIndex) ]; + tusb_std_class_code_t class_code = usbd_devices[coreid].interface2class[ u16_low_u8(control_request.wIndex) ]; if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) && usbd_class_drivers[class_code].control_request ) { - error = usbd_class_drivers[class_code].control_request(event.coreid, p_request); + error = usbd_class_drivers[class_code].control_request(coreid, &control_request); }else { error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; } } //------------- Endpoint Request -------------// - else if ( TUSB_REQUEST_RECIPIENT_ENDPOINT == p_request->bmRequestType_bit.recipient && - TUSB_REQUEST_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + else if ( TUSB_REQUEST_RECIPIENT_ENDPOINT == control_request.bmRequestType_bit.recipient && + TUSB_REQUEST_TYPE_STANDARD == control_request.bmRequestType_bit.type && + TUSB_REQUEST_CLEAR_FEATURE == control_request.bRequest ) { - if ( TUSB_REQUEST_CLEAR_FEATURE == p_request->bRequest ) - { - dcd_pipe_clear_stall(event.coreid, u16_low_u8(p_request->wIndex) ); - } else - { - error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; - } + dcd_pipe_clear_stall(coreid, u16_low_u8(control_request.wIndex) ); } else { error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; @@ -203,11 +227,11 @@ tusb_error_t usbd_body_subtask(void) if(TUSB_ERROR_NONE != error) { // Response with Protocol Stall if request is not supported - dcd_pipe_control_stall(event.coreid); + dcd_pipe_control_stall(coreid); // ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN); }else { // status phase - dcd_pipe_control_xfer(event.coreid, 1-p_request->bmRequestType_bit.direction, NULL, 0); // zero length + dcd_pipe_control_xfer(coreid, 1-control_request.bmRequestType_bit.direction, NULL, 0); // zero length } } @@ -246,6 +270,10 @@ tusb_error_t usbd_init (void) //------------- Task init -------------// usbd_queue_hdl = osal_queue_create( OSAL_QUEUE_REF(usbd_queue_def) ); ASSERT_PTR(usbd_queue_hdl, TUSB_ERROR_OSAL_QUEUE_FAILED); + + usbd_control_xfer_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(usbd_control_xfer_semaphore_def) ); + ASSERT_PTR(usbd_queue_hdl, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); + ASSERT_STATUS( osal_task_create( OSAL_TASK_REF(usbd_task) )); //------------- class init -------------// @@ -351,9 +379,12 @@ void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xfer // usbd_device_info_t *p_device = &usbd_devices[edpt_hdl.coreid]; uint8_t class_index = std_class_code_to_index(edpt_hdl.class_code); - if (class_index == 0) // Control Transfer + if (class_index == 0 ) // Control Transfer { - + if (usbd_devices[edpt_hdl.coreid].is_waiting_control_xfer) + { + osal_semaphore_post( usbd_control_xfer_sem_hdl ); + } }else if (usbd_class_drivers[class_index].isr) { usbd_class_drivers[class_index].isr(edpt_hdl, event, xferred_bytes); diff --git a/tinyusb/device/usbd_dcd.h b/tinyusb/device/usbd_dcd.h index 4a466a112..e72cdf060 100644 --- a/tinyusb/device/usbd_dcd.h +++ b/tinyusb/device/usbd_dcd.h @@ -61,6 +61,7 @@ typedef struct { volatile uint8_t state; + uint8_t is_waiting_control_xfer; // set if task is waiting for control xfer to complete to proceed tusb_control_request_t control_request; uint8_t interface2class[USBD_MAX_INTERFACE]; // determine interface number belongs to which class }usbd_device_info_t;