update host/device_info to build with freertos for espressif board. Add hil test for host/device_info

This commit is contained in:
hathach
2024-11-12 19:00:00 +07:00
parent 65e741937a
commit e391e33492
7 changed files with 173 additions and 69 deletions

View File

@@ -1,3 +1,6 @@
mcu:ESP32S2
mcu:ESP32S3
mcu:ESP32P4
mcu:KINETIS_KL mcu:KINETIS_KL
mcu:LPC175X_6X mcu:LPC175X_6X
mcu:LPC177X_8X mcu:LPC177X_8X

View File

@@ -0,0 +1,4 @@
# This file is for ESP-IDF only
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)

View File

@@ -24,7 +24,7 @@
*/ */
/* Host example will get device descriptors of attached devices and print it out via uart/rtt (logger) as follows: /* 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: Device Descriptor:
bLength 18 bLength 18
bDescriptorType 1 bDescriptorType 1
@@ -56,15 +56,20 @@
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES // 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); static void print_utf16(uint16_t* temp_buf, size_t buf_len);
/*------------- MAIN -------------*/ #if CFG_TUSB_OS == OPT_OS_FREERTOS
int main(void) { void init_freertos_task(void);
board_init(); #endif
printf("TinyUSB Device Info Example\r\n");
//--------------------------------------------------------------------
// Main
//--------------------------------------------------------------------
void init_tinyusb(void) {
// init host stack on configured roothub port // init host stack on configured roothub port
tusb_rhport_init_t host_init = { tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST, .role = TUSB_ROLE_HOST,
@@ -75,14 +80,22 @@ int main(void) {
if (board_init_after_tusb) { if (board_init_after_tusb) {
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) { while (1) {
// tinyusb host task tuh_task(); // tinyusb host task
tuh_task();
led_blinking_task(); led_blinking_task();
} }
return 0; return 0;
#endif
} }
/*------------- TinyUSB Callbacks -------------*/ /*------------- TinyUSB Callbacks -------------*/
@@ -97,9 +110,20 @@ void tuh_mount_cb(uint8_t daddr) {
return; return;
} }
uint16_t serial[64];
uint16_t buf[256]; 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("Device Descriptor:\r\n");
printf(" bLength %u\r\n", desc_device.bLength); printf(" bLength %u\r\n", desc_device.bLength);
printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType); printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType);
@@ -129,37 +153,17 @@ void tuh_mount_cb(uint8_t daddr) {
printf("\r\n"); printf("\r\n");
printf(" iSerialNumber %u ", desc_device.iSerialNumber); printf(" iSerialNumber %u ", desc_device.iSerialNumber);
xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); printf((char*)serial); // serial is already to UTF-8
if (XFER_RESULT_SUCCESS == xfer_result) {
print_utf16(buf, TU_ARRAY_SIZE(buf));
}
printf("\r\n"); printf("\r\n");
printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations); 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) { void tuh_umount_cb(uint8_t daddr) {
printf("Device removed, address = %d\r\n", 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 // String Descriptor Helper
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@@ -212,3 +216,88 @@ static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
printf("%s", (char*) temp_buf); 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

View File

@@ -39,6 +39,11 @@
#error CFG_TUSB_MCU must be defined #error CFG_TUSB_MCU must be defined
#endif #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 #ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE #define CFG_TUSB_OS OPT_OS_NONE
#endif #endif

View File

@@ -50,6 +50,7 @@ verbose = False
# Path # Path
# ------------------------------------------------------------- # -------------------------------------------------------------
OPENCOD_ADI_PATH = f'{os.getenv("HOME")}/app/openocd_adi' 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 # get usb serial by id
def get_serial_dev(id, vendor_str, product_str, ifnum): 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 # slight delay since kernel may occupy the port briefly
time.sleep(0.5) time.sleep(0.5)
timeout = timeout - 0.5 timeout = timeout - 0.5
ser = serial.Serial(port, timeout=5) ser = serial.Serial(port, baudrate=115200, timeout=5)
break break
except serial.SerialException: except serial.SerialException:
pass pass
@@ -212,6 +213,7 @@ def flash_esptool(board, firmware):
flash_args = f.read().strip().replace('\n', ' ') flash_args = f.read().strip().replace('\n', ' ')
command = (f'esptool.py --chip {idf_target} -p {port} {board["flasher_args"]} ' command = (f'esptool.py --chip {idf_target} -p {port} {board["flasher_args"]} '
f'--before=default_reset --after=hard_reset write_flash {flash_args}') f'--before=default_reset --after=hard_reset write_flash {flash_args}')
# command = f'echo abc'
ret = run_cmd(command, cwd=fw_dir) ret = run_cmd(command, cwd=fw_dir)
return ret return ret
@@ -228,35 +230,6 @@ def test_dual_host_info_to_device_cdc(board):
uid = board['uid'] uid = board['uid']
declared_devs = [f'{d["vid_pid"]}_{d["serial"]}' for d in board['tests']['dev_attached']] 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) port = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 0)
ser = open_serial_dev(port) ser = open_serial_dev(port)
# read from serial, first line should contain vid/pid and serial # read from serial, first line should contain vid/pid and serial
@@ -279,8 +252,36 @@ def test_host_cdc_msc_hid(board):
return 0 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') print(f'{name:25} {skip:30} ... Skip')
# board_test is added last to disable board's usb # 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 err_count = 0
flags_on_list = [""] flags_on_list = [""]
@@ -466,9 +467,9 @@ def test_board(board):
if f1 != "": if f1 != "":
f1_str = '-' + f1.replace(' ', '-') f1_str = '-' + f1.replace(' ', '-')
for test in test_list: 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): 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)}' fw_name = f'{fw_dir}/{os.path.basename(test)}'
print(f'{name+f1_str:40} {test:30} ... ', end='') print(f'{name+f1_str:40} {test:30} ... ', end='')

View File

@@ -4,7 +4,8 @@
"name": "espressif_p4_function_ev", "name": "espressif_p4_function_ev",
"uid": "6055F9F98715", "uid": "6055F9F98715",
"tests": { "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": "esptool",
"flasher_sn": "4ea4f48f6bc3ee11bbb9d00f9e1b1c54", "flasher_sn": "4ea4f48f6bc3ee11bbb9d00f9e1b1c54",

View File

@@ -68,6 +68,7 @@ def get_examples(family):
if family == 'espressif': if family == 'espressif':
all_examples.append('device/board_test') all_examples.append('device/board_test')
all_examples.append('device/video_capture') all_examples.append('device/video_capture')
all_examples.append('host/device_info')
all_examples.sort() all_examples.sort()
return all_examples return all_examples