-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(teardown_test): Added the test_app for teardowning the cdc de…
…vice
- Loading branch information
Showing
7 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# The following lines of boilerplate have to be in your project's | ||
# CMakeLists in this exact order for cmake to work correctly | ||
cmake_minimum_required(VERSION 3.16) | ||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
|
||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on. | ||
set(COMPONENTS main) | ||
|
||
project(test_app_teardown_device) |
4 changes: 4 additions & 0 deletions
4
device/esp_tinyusb/test_apps/teardown_device/main/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
idf_component_register(SRC_DIRS . | ||
INCLUDE_DIRS . | ||
REQUIRES unity | ||
WHOLE_ARCHIVE) |
5 changes: 5 additions & 0 deletions
5
device/esp_tinyusb/test_apps/teardown_device/main/idf_component.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## IDF Component Manager Manifest File | ||
dependencies: | ||
espressif/esp_tinyusb: | ||
version: "*" | ||
override_path: "../../../" |
62 changes: 62 additions & 0 deletions
62
device/esp_tinyusb/test_apps/teardown_device/main/test_app_main.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include "unity.h" | ||
#include "unity_test_runner.h" | ||
#include "unity_test_utils_memory.h" | ||
|
||
void app_main(void) | ||
{ | ||
/* | ||
_ _ _ | ||
| | (_) | | | ||
___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__ | ||
/ _ \/ __| '_ \| __| | '_ \| | | | | | / __| '_ \ | ||
| __/\__ \ |_) | |_| | | | | |_| | |_| \__ \ |_) | | ||
\___||___/ .__/ \__|_|_| |_|\__, |\__,_|___/_.__/ | ||
| |______ __/ | | ||
|_|______| |___/ | ||
_____ _____ _____ _____ | ||
|_ _| ___/ ___|_ _| | ||
| | | |__ \ `--. | | | ||
| | | __| `--. \ | | | ||
| | | |___/\__/ / | | | ||
\_/ \____/\____/ \_/ | ||
*/ | ||
|
||
printf(" _ _ _ \n"); | ||
printf(" | | (_) | | \n"); | ||
printf(" ___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__ \n"); | ||
printf(" / _ \\/ __| '_ \\| __| | '_ \\| | | | | | / __| '_ \\ \n"); | ||
printf("| __/\\__ \\ |_) | |_| | | | | |_| | |_| \\__ \\ |_) |\n"); | ||
printf(" \\___||___/ .__/ \\__|_|_| |_|\\__, |\\__,_|___/_.__/ \n"); | ||
printf(" | |______ __/ | \n"); | ||
printf(" |_|______| |___/ \n"); | ||
printf(" _____ _____ _____ _____ \n"); | ||
printf("|_ _| ___/ ___|_ _| \n"); | ||
printf(" | | | |__ \\ `--. | | \n"); | ||
printf(" | | | __| `--. \\ | | \n"); | ||
printf(" | | | |___/\\__/ / | | \n"); | ||
printf(" \\_/ \\____/\\____/ \\_/ \n"); | ||
|
||
unity_utils_setup_heap_record(80); | ||
unity_utils_set_leak_level(128); | ||
unity_run_menu(); | ||
} | ||
|
||
/* setUp runs before every test */ | ||
void setUp(void) | ||
{ | ||
unity_utils_record_free_mem(); | ||
} | ||
|
||
/* tearDown runs after every test */ | ||
void tearDown(void) | ||
{ | ||
unity_utils_evaluate_leaks(); | ||
} |
163 changes: 163 additions & 0 deletions
163
device/esp_tinyusb/test_apps/teardown_device/main/test_teardown.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "soc/soc_caps.h" | ||
// #if SOC_USB_OTG_SUPPORTED | ||
|
||
// | ||
#include <stdio.h> | ||
#include <string.h> | ||
// | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
// | ||
#include "esp_system.h" | ||
#include "esp_log.h" | ||
#include "esp_err.h" | ||
// | ||
#include "unity.h" | ||
#include "tinyusb.h" | ||
#include "tusb_cdc_acm.h" | ||
|
||
static const char *TEARDOWN_CMD = "teardown"; | ||
// Delay between device connection, required for the Host to handle device disconnection/connection without errors | ||
#define TEARDOWN_DELAY_MS 2000 | ||
#define TEARDOWN_AMOUNT 10 | ||
|
||
static const tusb_desc_device_t cdc_device_descriptor = { | ||
.bLength = sizeof(cdc_device_descriptor), | ||
.bDescriptorType = TUSB_DESC_DEVICE, | ||
.bcdUSB = 0x0200, | ||
.bDeviceClass = TUSB_CLASS_MISC, | ||
.bDeviceSubClass = MISC_SUBCLASS_COMMON, | ||
.bDeviceProtocol = MISC_PROTOCOL_IAD, | ||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, | ||
.idVendor = USB_ESPRESSIF_VID, | ||
.idProduct = 0x4002, | ||
.bcdDevice = 0x0100, | ||
.iManufacturer = 0x01, | ||
.iProduct = 0x02, | ||
.iSerialNumber = 0x03, | ||
.bNumConfigurations = 0x01 | ||
}; | ||
|
||
static const uint16_t cdc_desc_config_len = TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN; | ||
static const uint8_t cdc_desc_configuration[] = { | ||
TUD_CONFIG_DESCRIPTOR(1, 4, 0, cdc_desc_config_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), | ||
TUD_CDC_DESCRIPTOR(0, 4, 0x81, 8, 0x02, 0x82, (TUD_OPT_HIGH_SPEED ? 512 : 64)), | ||
}; | ||
|
||
#if (TUD_OPT_HIGH_SPEED) | ||
static const tusb_desc_device_qualifier_t device_qualifier = { | ||
.bLength = sizeof(tusb_desc_device_qualifier_t), | ||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, | ||
.bcdUSB = 0x0200, | ||
.bDeviceClass = TUSB_CLASS_MISC, | ||
.bDeviceSubClass = MISC_SUBCLASS_COMMON, | ||
.bDeviceProtocol = MISC_PROTOCOL_IAD, | ||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, | ||
.bNumConfigurations = 0x01, | ||
.bReserved = 0 | ||
}; | ||
#endif // TUD_OPT_HIGH_SPEED | ||
|
||
static QueueHandle_t rx_queue; | ||
static uint8_t rx_buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1]; | ||
|
||
typedef struct { | ||
int itf; // Interface number | ||
uint8_t data[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1]; // Data buffer | ||
size_t len; // Number of bytes received | ||
} rx_pkt_t; | ||
|
||
static void test_rx_enqueue_pkt(int itf, uint8_t *buf, size_t size) | ||
{ | ||
rx_pkt_t rx_pkt = { | ||
.itf = itf, | ||
.len = size, | ||
}; | ||
memcpy(rx_pkt.data, buf, size); | ||
xQueueSend(rx_queue, &rx_pkt, 0); | ||
} | ||
|
||
static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) | ||
{ | ||
size_t rx_size = 0; | ||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_cdcacm_read(itf, rx_buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size)); | ||
test_rx_enqueue_pkt(itf, rx_buf, rx_size); | ||
} | ||
|
||
/** | ||
* @brief TinyUSB Teardown specific testcase | ||
*/ | ||
TEST_CASE("tinyusb_teardown", "[esp_tinyusb][teardown]") | ||
{ | ||
rx_pkt_t rx_pkt; | ||
// Create FreeRTOS primitives | ||
rx_queue = xQueueCreate(5, sizeof(rx_pkt_t)); | ||
TEST_ASSERT(rx_queue); | ||
|
||
// TinyUSB driver configuration | ||
const tinyusb_config_t tusb_cfg = { | ||
.device_descriptor = &cdc_device_descriptor, | ||
.string_descriptor = NULL, | ||
.string_descriptor_count = 0, | ||
.external_phy = false, | ||
#if (TUD_OPT_HIGH_SPEED) | ||
.fs_configuration_descriptor = cdc_desc_configuration, | ||
.hs_configuration_descriptor = cdc_desc_configuration, | ||
.qualifier_descriptor = &device_qualifier, | ||
#else | ||
.configuration_descriptor = cdc_desc_configuration, | ||
#endif // TUD_OPT_HIGH_SPEED | ||
}; | ||
|
||
// TinyUSB ACM Driver configuration | ||
tinyusb_config_cdcacm_t acm_cfg = { | ||
.usb_dev = TINYUSB_USBDEV_0, | ||
.cdc_port = TINYUSB_CDC_ACM_0, | ||
.rx_unread_buf_sz = 64, | ||
.callback_rx = &tinyusb_cdc_rx_callback, | ||
.callback_rx_wanted_char = NULL, | ||
.callback_line_state_changed = NULL, | ||
.callback_line_coding_changed = NULL | ||
}; | ||
int attempts = TEARDOWN_AMOUNT; | ||
while (1) { | ||
vTaskDelay(pdMS_TO_TICKS(TEARDOWN_DELAY_MS)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); | ||
// Init CDC 0 | ||
TEST_ASSERT_FALSE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_init(&acm_cfg)); | ||
TEST_ASSERT_TRUE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); | ||
|
||
// Wait for the pytest poke | ||
while (1) { | ||
if (xQueueReceive(rx_queue, &rx_pkt, portMAX_DELAY)) { | ||
if (rx_pkt.len) { | ||
/* echoed back */ | ||
TEST_ASSERT_EQUAL(rx_pkt.len, tinyusb_cdcacm_write_queue(rx_pkt.itf, rx_pkt.data, rx_pkt.len)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_cdcacm_write_flush(rx_pkt.itf, pdMS_TO_TICKS(100))); | ||
if (strncmp(TEARDOWN_CMD, (const char *) rx_pkt.data, rx_pkt.len) == 0) { | ||
// Wait for the host | ||
attempts--; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
vTaskDelay(pdMS_TO_TICKS(TEARDOWN_DELAY_MS)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_cdcacm_unregister_callback(TINYUSB_CDC_ACM_0, CDC_EVENT_RX)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_deinit(TINYUSB_CDC_ACM_0)); | ||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); | ||
} | ||
// Remove primitives | ||
vQueueDelete(rx_queue); | ||
// All attempts should be completed | ||
TEST_ASSERT_EQUAL(0, attempts); | ||
} | ||
|
||
// #endif |
92 changes: 92 additions & 0 deletions
92
device/esp_tinyusb/test_apps/teardown_device/pytest_teardown_device.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import pytest | ||
from pytest_embedded_idf.dut import IdfDut | ||
import serial | ||
# import serial.tools.list_ports | ||
from serial.tools.list_ports import comports | ||
# import time | ||
from time import sleep | ||
from time import time | ||
|
||
|
||
@pytest.mark.esp32s2 | ||
@pytest.mark.esp32s3 | ||
@pytest.mark.esp32p4 | ||
@pytest.mark.usb_device | ||
|
||
def find_tusb_cdc(vid, pid): | ||
ports = comports() | ||
for cdc in ports: | ||
if cdc.vid == vid and cdc.pid == pid: | ||
return cdc.device | ||
return None | ||
|
||
def wait_for_tusb_cdc(vid, pid, timeout=30): | ||
start_time = time() | ||
while time() - start_time < timeout: | ||
tusb_cdc = find_tusb_cdc(vid, pid) | ||
if tusb_cdc: | ||
return tusb_cdc | ||
sleep(0.5) # Check every 0.5 seconds | ||
return None | ||
|
||
def teardown_device(amount): | ||
TUSB_VID = 0x303A # Espressif TinyUSB VID | ||
TUSB_PID = 0x4002 # Espressif TinyUSB VID | ||
|
||
# Command to send and expected response | ||
COMMAND = "teardown" | ||
EXPECTED_RESPONSE = "teardown" | ||
|
||
# Number of iterations, must be equal to ITERATIONS in the test application | ||
ITERATIONS = amount | ||
|
||
for i in range(ITERATIONS): | ||
print(f"Iteration {i+1} of {ITERATIONS}") | ||
|
||
# Wait for the device to appear | ||
print("Waiting for the device to connect...") | ||
tusb_cdc = wait_for_tusb_cdc(TUSB_VID, TUSB_PID) | ||
if not tusb_cdc: | ||
print("Error: Device did not appear within the timeout period.") | ||
break | ||
|
||
try: | ||
# Open the serial port | ||
with serial.Serial(port=tusb_cdc, baudrate=9600, timeout=1) as cdc: | ||
print(f"Opened port: {tusb_cdc}") | ||
|
||
# Send the 'teardown' command | ||
cdc.write(COMMAND.encode('utf-8')) | ||
print(f"Sent command: {COMMAND.strip()}") | ||
|
||
# Wait for the response | ||
res = cdc.readline().decode('utf-8').strip() | ||
print(f"Received response: {res}") | ||
|
||
# Check if the response matches the expected response | ||
if res == EXPECTED_RESPONSE: | ||
print("Response matches expected value.") | ||
else: | ||
print("Error: Response does not match expected value.") | ||
|
||
except tusb_cdc.SerialException as e: | ||
print(f"Error communicating with the serial port: {e}") | ||
break | ||
|
||
# Wait for the device to disconnect | ||
print("Waiting for the device to disconnect...") | ||
while find_tusb_cdc(TUSB_VID, TUSB_PID): | ||
sleep(0.5) # Check every 0.5 seconds | ||
|
||
print("Finished all iterations.") | ||
|
||
def test_usb_teardown_device(dut) -> None: | ||
dut.expect_exact('Press ENTER to see the list of tests.') | ||
dut.write('[teardown]') | ||
dut.expect_exact('TinyUSB: TinyUSB Driver installed') | ||
sleep(2) # Some time for the OS to enumerate our USB device | ||
teardown_device(10) # Teardown tusb device 10 times | ||
|
16 changes: 16 additions & 0 deletions
16
device/esp_tinyusb/test_apps/teardown_device/sdkconfig.defaults
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Configure TinyUSB, it will be used to mock USB devices | ||
CONFIG_TINYUSB_CDC_ENABLED=y | ||
CONFIG_TINYUSB_CDC_COUNT=1 | ||
|
||
# Disable watchdogs, they'd get triggered during unity interactive menu | ||
CONFIG_ESP_INT_WDT=n | ||
CONFIG_ESP_TASK_WDT=n | ||
|
||
# Run-time checks of Heap and Stack | ||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y | ||
CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y | ||
CONFIG_COMPILER_STACK_CHECK=y | ||
|
||
CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y | ||
|
||
CONFIG_COMPILER_CXX_EXCEPTIONS=y |