diff --git a/tests/test/test_osal_none.c b/tests/test/test_osal_none.c index e9c1eb16..aebf1545 100644 --- a/tests/test/test_osal_none.c +++ b/tests/test/test_osal_none.c @@ -241,25 +241,47 @@ void flow_control_error_handler(void) statements[5]++; } +tusb_error_t sample_flow_control_subtask2(void) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + statements[0]++; + + osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + SUBTASK_ASSERT(TUSB_ERROR_NONE == error); + statements[1]++; + + osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + SUBTASK_ASSERT_STATUS(error); + statements[2]++; + + osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + SUBTASK_ASSERT_STATUS_WITH_HANDLER(error, flow_control_error_handler()); + statements[3]++; + + OSAL_SUBTASK_END +} + +tusb_error_t sample_flow_control_subtask(void) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + OSAL_SUBTASK_INVOKED_AND_WAIT (sample_flow_control_subtask2()); + + OSAL_SUBTASK_END +} + tusb_error_t sample_task_flow_control(void) { tusb_error_t error; OSAL_TASK_LOOP_BEGIN - statements[0]++; - - osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); - TASK_ASSERT(TUSB_ERROR_NONE == error); - statements[1]++; - - osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); - TASK_ASSERT_STATUS(error); - statements[2]++; - - osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_NORMAL, &error); - TASK_ASSERT_STATUS_WITH_HANDLER(error, flow_control_error_handler()); - statements[3]++; + OSAL_SUBTASK_INVOKED_AND_WAIT ( sample_flow_control_subtask() ); OSAL_TASK_LOOP_END } diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c index a5d48071..f366c9ad 100644 --- a/tinyusb/host/usbh.c +++ b/tinyusb/host/usbh.c @@ -155,12 +155,8 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, tusb_std_request_t cons osal_semaphore_wait(usbh_devices[dev_addr].control.sem_hdl, OSAL_TIMEOUT_NORMAL, &error); // careful of local variable without static // TODO make handler for this function general purpose - SUBTASK_ASSERT_STATUS_WITH_HANDLER(error || usbh_devices[dev_addr].control.pipe_status == TUSB_INTERFACE_STATUS_ERROR, + SUBTASK_ASSERT_WITH_HANDLER(TUSB_ERROR_NONE == error && usbh_devices[dev_addr].control.pipe_status != TUSB_INTERFACE_STATUS_ERROR, tusbh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL) ); -// if ( TUSB_ERROR_NONE != error || usbh_devices[dev_addr].control.pipe_status == TUSB_INTERFACE_STATUS_ERROR) -// { -// tusbh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL); -// } OSAL_SUBTASK_END } @@ -267,194 +263,187 @@ OSAL_TASK_FUNCTION(usbh_enumeration_task) osal_queue_receive(enum_queue_hdl, &enum_entry, OSAL_TIMEOUT_WAIT_FOREVER, &error); - if( hcd_port_connect_status(enum_entry.core_id) ) // ensure device is still plugged - { - usbh_devices[0].core_id = enum_entry.core_id; // TODO refractor integrate to device_pool - usbh_devices[0].hub_addr = enum_entry.hub_addr; - usbh_devices[0].hub_port = enum_entry.hub_port; - usbh_devices[0].speed = enum_entry.speed; + SUBTASK_ASSERT( hcd_port_connect_status(enum_entry.core_id) ); // ensure device is still plugged + usbh_devices[0].core_id = enum_entry.core_id; // TODO refractor integrate to device_pool + usbh_devices[0].hub_addr = enum_entry.hub_addr; + usbh_devices[0].hub_port = enum_entry.hub_port; + usbh_devices[0].speed = enum_entry.speed; - if( TUSB_ERROR_NONE == usbh_pipe_control_open(0, 8) ) - { - usbh_devices[0].state = TUSB_DEVICE_STATE_ADDRESSED; + SUBTASK_ASSERT_STATUS( usbh_pipe_control_open(0, 8) ); + usbh_devices[0].state = TUSB_DEVICE_STATE_ADDRESSED; - #ifndef _TEST_ - // TODO finalize delay after reset, hack delay 100 ms, otherwise speed is detected as LOW in most cases - volatile uint32_t delay_us = 10000; - delay_us *= (SystemCoreClock / 1000000) / 3; - while(delay_us--); - #endif +#ifndef _TEST_ + // TODO finalize delay after reset, hack delay 100 ms, otherwise speed is detected as LOW in most cases + volatile uint32_t delay_us = 10000; + delay_us *= (SystemCoreClock / 1000000) / 3; + while(delay_us--); +#endif - //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( - 0, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_DEVICE << 8), - .wLength = 8 - }, - enum_data_buffer - ) - ); - - hcd_port_reset( usbh_devices[0].core_id ); // reset port after 8 byte descriptor - - //------------- Set new address -------------// - new_addr = get_new_address(); - if (new_addr <= TUSB_CFG_HOST_DEVICE_MAX) // TODO notify application we reach max devices + //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( + 0, + &(tusb_std_request_t) { - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( - 0, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_HOST_TO_DEV, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_SET_ADDRESS, - .wValue = new_addr - }, - NULL - ) - ); + .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_DEVICE << 8), + .wLength = 8 + }, + enum_data_buffer + ) + ); - //------------- update port info & close control pipe of addr0 -------------// - usbh_devices[new_addr].core_id = usbh_devices[0].core_id; - usbh_devices[new_addr].hub_addr = usbh_devices[0].hub_addr; - usbh_devices[new_addr].hub_port = usbh_devices[0].hub_port; - usbh_devices[new_addr].speed = usbh_devices[0].speed; - usbh_devices[new_addr].state = TUSB_DEVICE_STATE_ADDRESSED; + hcd_port_reset( usbh_devices[0].core_id ); // reset port after 8 byte descriptor - usbh_pipe_control_close(0); - usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; + //------------- Set new address -------------// + new_addr = get_new_address(); + SUBTASK_ASSERT(new_addr <= TUSB_CFG_HOST_DEVICE_MAX); // TODO notify application we reach max devices - // open control pipe for new address - if ( TUSB_ERROR_NONE == usbh_pipe_control_open(new_addr, ((tusb_descriptor_device_t*) enum_data_buffer)->bMaxPacketSize0 ) ) + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( + 0, + &(tusb_std_request_t) + { + .bmRequestType = { .direction = TUSB_DIR_HOST_TO_DEV, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_SET_ADDRESS, + .wValue = new_addr + }, + NULL + ) + ); + + //------------- update port info & close control pipe of addr0 -------------// + usbh_devices[new_addr].core_id = usbh_devices[0].core_id; + usbh_devices[new_addr].hub_addr = usbh_devices[0].hub_addr; + usbh_devices[new_addr].hub_port = usbh_devices[0].hub_port; + usbh_devices[new_addr].speed = usbh_devices[0].speed; + usbh_devices[new_addr].state = TUSB_DEVICE_STATE_ADDRESSED; + + usbh_pipe_control_close(0); + usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; + + // open control pipe for new address + SUBTASK_ASSERT_STATUS ( usbh_pipe_control_open(new_addr, ((tusb_descriptor_device_t*) enum_data_buffer)->bMaxPacketSize0 ) ); + + //------------- Get full device descriptor -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( + new_addr, + &(tusb_std_request_t) + { + .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_DEVICE << 8), + .wLength = 18 + }, + enum_data_buffer + ) + ); + + // update device info TODO alignment issue + usbh_devices[new_addr].vendor_id = ((tusb_descriptor_device_t*) enum_data_buffer)->idVendor; + usbh_devices[new_addr].product_id = ((tusb_descriptor_device_t*) enum_data_buffer)->idProduct; + usbh_devices[new_addr].configure_count = ((tusb_descriptor_device_t*) enum_data_buffer)->bNumConfigurations; + + configure_selected = get_configure_number_for_device((tusb_descriptor_device_t*) enum_data_buffer); + SUBTASK_ASSERT(configure_selected <= usbh_devices[new_addr].configure_count); // TODO notify application when invalid configuration + + //------------- Get 9 bytes of configuration descriptor -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( + new_addr, + &(tusb_std_request_t) + { + .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), + .wLength = 9 + }, + enum_data_buffer + ) + ); + SUBTASK_ASSERT_WITH_HANDLER( TUSB_CFG_HOST_ENUM_BUFFER_SIZE > ((tusb_descriptor_configuration_t*)enum_data_buffer)->wTotalLength, + tusbh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG, NULL) ); + + //------------- Get full configuration descriptor -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( + new_addr, + &(tusb_std_request_t) + { + .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), + .wLength = ((tusb_descriptor_configuration_t*) enum_data_buffer)->wTotalLength + }, + enum_data_buffer + ) + ); + + // update configuration info + usbh_devices[new_addr].interface_count = ((tusb_descriptor_configuration_t*) enum_data_buffer)->bNumInterfaces; + + //------------- Set Configure -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT ( + usbh_control_xfer_subtask( + new_addr, + &(tusb_std_request_t) { - //------------- Get full device descriptor -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( - new_addr, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_DEVICE << 8), - .wLength = 18 - }, - enum_data_buffer - ) - ); + .bmRequestType = { .direction = TUSB_DIR_HOST_TO_DEV, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_SET_CONFIGURATION, + .wValue = configure_selected + }, + NULL + ) + ); - // update device info TODO alignment issue - usbh_devices[new_addr].vendor_id = ((tusb_descriptor_device_t*) enum_data_buffer)->idVendor; - usbh_devices[new_addr].product_id = ((tusb_descriptor_device_t*) enum_data_buffer)->idProduct; - usbh_devices[new_addr].configure_count = ((tusb_descriptor_device_t*) enum_data_buffer)->bNumConfigurations; + usbh_devices[new_addr].state = TUSB_DEVICE_STATE_CONFIGURED; - configure_selected = get_configure_number_for_device((tusb_descriptor_device_t*) enum_data_buffer); - if(configure_selected <= usbh_devices[new_addr].configure_count) // TODO notify application when invalid configuration - { - //------------- Get 9 bytes of configuration descriptor -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( - new_addr, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), - .wLength = 9 - }, - enum_data_buffer - ) - ); + //------------- parse configuration & install drivers -------------// + p_desc = enum_data_buffer + sizeof(tusb_descriptor_configuration_t); - if ( TUSB_CFG_HOST_ENUM_BUFFER_SIZE <= ((tusb_descriptor_configuration_t*)enum_data_buffer)->wTotalLength ) - { - tusbh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG, NULL); - }else - { - //------------- Get full configuration descriptor -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( - new_addr, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_DEV_TO_HOST, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), - .wLength = ((tusb_descriptor_configuration_t*) enum_data_buffer)->wTotalLength - }, - enum_data_buffer - ) - ); + // parse each interfaces + while( p_desc < enum_data_buffer + ((tusb_descriptor_configuration_t*)enum_data_buffer)->wTotalLength ) + { + // skip until we see interface descriptor + if ( TUSB_DESC_INTERFACE != p_desc[DESCRIPTOR_OFFSET_TYPE] ) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length + }else + { + uint8_t class_code = ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass; + if (class_code == 0) + { + SUBTASK_ASSERT( false ); // corrupted data, abort enumeration + } + // supported class TODO custom class + else if ( class_code < TUSB_CLASS_MAX_CONSEC_NUMBER && usbh_class_drivers[class_code].open_subtask) + { + uint16_t length=0; + OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global) + usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].open_subtask( + new_addr, (tusb_descriptor_interface_t*) p_desc, &length) ); - // update configuration info - usbh_devices[new_addr].interface_count = ((tusb_descriptor_configuration_t*) enum_data_buffer)->bNumInterfaces; - - //------------- Set Configure -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT ( - usbh_control_xfer_subtask( - new_addr, - &(tusb_std_request_t) - { - .bmRequestType = { .direction = TUSB_DIR_HOST_TO_DEV, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, - .bRequest = TUSB_REQUEST_SET_CONFIGURATION, - .wValue = configure_selected - }, - NULL - ) - ); - - usbh_devices[new_addr].state = TUSB_DEVICE_STATE_CONFIGURED; - - //------------- parse configuration & install drivers -------------// - p_desc = enum_data_buffer + sizeof(tusb_descriptor_configuration_t); - - // parse each interfaces - while( p_desc < enum_data_buffer + ((tusb_descriptor_configuration_t*)enum_data_buffer)->wTotalLength ) - { - // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != p_desc[DESCRIPTOR_OFFSET_TYPE] ) - { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length - }else - { - uint8_t class_code = ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass; - - // supported class TODO add custom class - if ( 0 < class_code && class_code < TUSB_CLASS_MAX_CONSEC_NUMBER && usbh_class_drivers[class_code].open_subtask) - { - uint16_t length=0; - OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global) - usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].open_subtask( - new_addr, (tusb_descriptor_interface_t*) p_desc, &length) ); - - if (length == 0) // Interface open failed, for example a subclass is not supported - { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop - // TODO can optimize the length --> open_subtask return a OPEN FAILED status - }else - { - usbh_devices[new_addr].flag_supported_class |= BIT_(((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass); - p_desc += length; - } - } else // unsupported class (not enable or yet implemented) - { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop - } - } - } - - tusbh_device_mount_succeed_cb(new_addr); - } - } + // TODO check class_open_subtask status + if (length == 0) // Interface open failed, for example a subclass is not supported + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + // TODO can optimize the length --> open_subtask return a OPEN FAILED status + }else + { + usbh_devices[new_addr].flag_supported_class |= BIT_(((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass); + p_desc += length; } + } else // unsupported class (not enable or yet implemented) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop } } } + tusbh_device_mount_succeed_cb(new_addr); + OSAL_TASK_LOOP_END } diff --git a/tinyusb/osal/osal_none.h b/tinyusb/osal/osal_none.h index 9b8b16fc..2aaa9b78 100644 --- a/tinyusb/osal/osal_none.h +++ b/tinyusb/osal/osal_none.h @@ -122,35 +122,29 @@ static inline volatile uint32_t osal_tick_get(void) }\ }while(0) -#define OSAL_SUBTASK_BEGIN OSAL_TASK_LOOP_BEGIN -#define OSAL_SUBTASK_END OSAL_TASK_LOOP_END +#define OSAL_SUBTASK_BEGIN OSAL_TASK_LOOP_BEGIN +#define OSAL_SUBTASK_END OSAL_TASK_LOOP_END //------------- Task Assert -------------// #define _TASK_ASSERT_ERROR_HANDLER(error, func_call) \ func_call; TASK_RESTART; return error -#define TASK_ASSERT_STATUS(sts) \ +#define SUBTASK_ASSERT_STATUS(sts) \ ASSERT_DEFINE_WITH_HANDLER(_TASK_ASSERT_ERROR_HANDLER, , tusb_error_t status = (tusb_error_t)(sts),\ TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status]) -#define TASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \ +#define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \ ASSERT_DEFINE_WITH_HANDLER(_TASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\ TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status]) -#define TASK_ASSERT(condition) \ +#define SUBTASK_ASSERT(condition) \ ASSERT_DEFINE_WITH_HANDLER(_TASK_ASSERT_ERROR_HANDLER, , , \ (condition), TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false") -#define TASK_ASSERT_WITH_HANDLER(condition, func_call) \ +#define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \ ASSERT_DEFINE_WITH_HANDLER(_TASK_ASSERT_ERROR_HANDLER, func_call, ,\ condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false") -//------------- Sub Task Assert -------------// -#define SUBTASK_ASSERT_STATUS TASK_ASSERT_STATUS -#define SUBTASK_ASSERT_STATUS_WITH_HANDLER TASK_ASSERT_STATUS_WITH_HANDLER -#define SUBTASK_ASSERT TASK_ASSERT -#define SUBTASK_ASSERT_WITH_HANDLER TASK_ASSERT_WITH_HANDLER - //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+