diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index f06d4df00..b6f87f423 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -1,3 +1,6 @@ +mcu:ESP32S2 +mcu:ESP32S3 +mcu:ESP32P4 mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X diff --git a/examples/host/device_info/src/CMakeLists.txt b/examples/host/device_info/src/CMakeLists.txt new file mode 100644 index 000000000..1908a32c3 --- /dev/null +++ b/examples/host/device_info/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index 0ff4f32e9..6591a0198 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -24,7 +24,7 @@ */ /* Host example will get device descriptors of attached devices and print it out via uart/rtt (logger) as follows: - * Device 1: ID 046d:c52f + * Device 1: ID 046d:c52f SN 11223344 Device Descriptor: bLength 18 bDescriptorType 1 @@ -56,15 +56,20 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -void led_blinking_task(void); + +static uint32_t blink_interval_ms = 1000; + +void led_blinking_task(void* param); static void print_utf16(uint16_t* temp_buf, size_t buf_len); -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - printf("TinyUSB Device Info Example\r\n"); +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void init_freertos_task(void); +#endif +//-------------------------------------------------------------------- +// Main +//-------------------------------------------------------------------- +void init_tinyusb(void) { // init host stack on configured roothub port tusb_rhport_init_t host_init = { .role = TUSB_ROLE_HOST, @@ -75,14 +80,22 @@ int main(void) { if (board_init_after_tusb) { board_init_after_tusb(); } +} +int main(void) { + board_init(); + printf("TinyUSB Device Info Example\r\n"); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + init_freertos_task(); +#else + init_tinyusb(); while (1) { - // tinyusb host task - tuh_task(); + tuh_task(); // tinyusb host task led_blinking_task(); } - return 0; +#endif } /*------------- TinyUSB Callbacks -------------*/ @@ -97,9 +110,20 @@ void tuh_mount_cb(uint8_t daddr) { return; } + uint16_t serial[64]; uint16_t buf[256]; - printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); + printf("Device %u: ID %04x:%04x SN ", daddr, desc_device.idVendor, desc_device.idProduct); + xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial)); + if (XFER_RESULT_SUCCESS != xfer_result) { + serial[0] = 'n'; + serial[1] = '/'; + serial[2] = 'a'; + serial[3] = 0; + } + print_utf16(serial, TU_ARRAY_SIZE(serial)); + printf("\r\n"); + printf("Device Descriptor:\r\n"); printf(" bLength %u\r\n", desc_device.bLength); printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType); @@ -129,37 +153,17 @@ void tuh_mount_cb(uint8_t daddr) { printf("\r\n"); printf(" iSerialNumber %u ", desc_device.iSerialNumber); - xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); - if (XFER_RESULT_SUCCESS == xfer_result) { - print_utf16(buf, TU_ARRAY_SIZE(buf)); - } + printf((char*)serial); // serial is already to UTF-8 printf("\r\n"); printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations); } -/// Invoked when device is unmounted (bus reset/unplugged) +// Invoked when device is unmounted (bus reset/unplugged) void tuh_umount_cb(uint8_t daddr) { printf("Device removed, address = %d\r\n", daddr); } -//--------------------------------------------------------------------+ -// Blinking Task -//--------------------------------------------------------------------+ -void led_blinking_task(void) { - const uint32_t interval_ms = 1000; - static uint32_t start_ms = 0; - - static bool led_state = false; - - // Blink every interval ms - if (board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle -} - //--------------------------------------------------------------------+ // String Descriptor Helper //--------------------------------------------------------------------+ @@ -212,3 +216,88 @@ static void print_utf16(uint16_t* temp_buf, size_t buf_len) { printf("%s", (char*) temp_buf); } + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; + static bool led_state = false; + + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + if (blink_interval_ms == 0) { + vTaskSuspend(NULL); + } else { + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + } +#else + if (blink_interval_ms == 0) { + return; + } + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } +#endif + + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE + +#if TUSB_MCU_VENDOR_ESPRESSIF + #define USB_STACK_SIZE 4096 +#else + // Increase stack size when debug log is enabled + #define USB_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_stack[USB_STACK_SIZE]; +StaticTask_t usb_taskdef; +#endif + +#if TUSB_MCU_VENDOR_ESPRESSIF +void app_main(void) { + main(); +} +#endif + +void usb_host_task(void *param) { + (void) param; + init_tinyusb(); + while (1) { + tuh_task(); + } +} + +void init_freertos_task(void) { +#if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_stack, &usb_taskdef); +#else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if !TUSB_MCU_VENDOR_ESPRESSIF + vTaskStartScheduler(); +#endif +} + +#endif diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h index 2e9731eaf..5190b5b1f 100644 --- a/examples/host/device_info/src/tusb_config.h +++ b/examples/host/device_info/src/tusb_config.h @@ -39,6 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif +// Espressif IDF requires "freertos/" prefix in include path +#if TUSB_MCU_VENDOR_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_OS #define CFG_TUSB_OS OPT_OS_NONE #endif diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 4a0510223..91fe6b67c 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -50,6 +50,7 @@ verbose = False # Path # ------------------------------------------------------------- OPENCOD_ADI_PATH = f'{os.getenv("HOME")}/app/openocd_adi' +TINYUSB_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # get usb serial by id def get_serial_dev(id, vendor_str, product_str, ifnum): @@ -83,7 +84,7 @@ def open_serial_dev(port): # slight delay since kernel may occupy the port briefly time.sleep(0.5) timeout = timeout - 0.5 - ser = serial.Serial(port, timeout=5) + ser = serial.Serial(port, baudrate=115200, timeout=5) break except serial.SerialException: pass @@ -212,6 +213,7 @@ def flash_esptool(board, firmware): flash_args = f.read().strip().replace('\n', ' ') command = (f'esptool.py --chip {idf_target} -p {port} {board["flasher_args"]} ' f'--before=default_reset --after=hard_reset write_flash {flash_args}') + # command = f'echo abc' ret = run_cmd(command, cwd=fw_dir) return ret @@ -228,35 +230,6 @@ def test_dual_host_info_to_device_cdc(board): uid = board['uid'] declared_devs = [f'{d["vid_pid"]}_{d["serial"]}' for d in board['tests']['dev_attached']] - port = get_serial_dev(board["flasher_sn"], None, None, 0) - ser = open_serial_dev(port) - # read from serial, first line should contain vid/pid and serial - data = ser.read(1000) - lines = data.decode('utf-8').splitlines() - enum_dev_sn = [] - for l in lines: - vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) - if vid_pid_sn: - print(f'\r\n {l} ', end='') - enum_dev_sn.append(f'{vid_pid_sn.group(1)}_{vid_pid_sn.group(2)}_{vid_pid_sn.group(3)}') - - if set(declared_devs) != set(enum_dev_sn): - # for pico/pico2 make this test optional - failed_msg = f'Enumerated devices {enum_dev_sn} not match with declared {declared_devs}' - if 'raspberry_pi_pico' in board['name']: - print(f'\r\n {failed_msg} {STATUS_FAILED} ', end='') - else: - assert False, failed_msg - return 0 - - -# ------------------------------------------------------------- -# Tests: host -# ------------------------------------------------------------- -def test_host_cdc_msc_hid(board): - uid = board['uid'] - declared_devs = [f'{d["vid_pid"]}_{d["serial"]}' for d in board['tests']['dev_attached']] - port = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 0) ser = open_serial_dev(port) # read from serial, first line should contain vid/pid and serial @@ -279,8 +252,36 @@ def test_host_cdc_msc_hid(board): return 0 -def test_host_cdc_msc_hid_freertos(board): - test_host_cdc_msc_hid(board) +# ------------------------------------------------------------- +# Tests: host +# ------------------------------------------------------------- +def test_host_device_info(board): + uid = board['uid'] + declared_devs = [f'{d["vid_pid"]}_{d["serial"]}' for d in board['tests']['dev_attached']] + + port = get_serial_dev(board["flasher_sn"], None, None, 0) + ser = open_serial_dev(port) + data = ser.read(1000) + if len(data) == 0: + assert False, 'No data from device' + + lines = data.decode('utf-8').splitlines() + enum_dev_sn = [] + for l in lines: + vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) + if vid_pid_sn: + print(f'\r\n {l} ', end='') + enum_dev_sn.append(f'{vid_pid_sn.group(1)}_{vid_pid_sn.group(2)}_{vid_pid_sn.group(3)}') + + if set(declared_devs) != set(enum_dev_sn): + # for pico/pico2 make this test optional + failed_msg = f'Enumerated devices {enum_dev_sn} not match with declared {declared_devs}' + if 'raspberry_pi_pico' in board['name']: + print(f'\r\n {failed_msg} {STATUS_FAILED} ', end='') + else: + assert False, failed_msg + + return 0 # ------------------------------------------------------------- @@ -454,7 +455,7 @@ def test_board(board): print(f'{name:25} {skip:30} ... Skip') # board_test is added last to disable board's usb - test_list.append('device/board_test') + #test_list.append('device/board_test') err_count = 0 flags_on_list = [""] @@ -466,9 +467,9 @@ def test_board(board): if f1 != "": f1_str = '-' + f1.replace(' ', '-') for test in test_list: - fw_dir = f'cmake-build/cmake-build-{name}{f1_str}/{test}' + fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{test}' if not os.path.exists(fw_dir): - fw_dir = f'examples/cmake-build-{name}{f1_str}/{test}' + fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{test}' fw_name = f'{fw_dir}/{os.path.basename(test)}' print(f'{name+f1_str:40} {test:30} ... ', end='') diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 1b0b7c99a..2d61981f2 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -4,7 +4,8 @@ "name": "espressif_p4_function_ev", "uid": "6055F9F98715", "tests": { - "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos", "host/cdc_msc_hid_freertos"] + "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos", "host/device_info"], + "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002427"}] }, "flasher": "esptool", "flasher_sn": "4ea4f48f6bc3ee11bbb9d00f9e1b1c54", diff --git a/tools/build.py b/tools/build.py index 91d4ebd30..48666adc4 100755 --- a/tools/build.py +++ b/tools/build.py @@ -68,6 +68,7 @@ def get_examples(family): if family == 'espressif': all_examples.append('device/board_test') all_examples.append('device/video_capture') + all_examples.append('host/device_info') all_examples.sort() return all_examples