Initial project setup
This commit is contained in:
@@ -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_dconn_detection)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRC_DIRS .
|
||||
INCLUDE_DIRS .
|
||||
REQUIRES unity
|
||||
WHOLE_ARCHIVE)
|
||||
@@ -0,0 +1,5 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb:
|
||||
version: "*"
|
||||
override_path: "../../../"
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "unity.h"
|
||||
#include "tinyusb.h"
|
||||
#include "tusb_tasks.h"
|
||||
|
||||
#define DEVICE_DETACH_TEST_ROUNDS 10
|
||||
#define DEVICE_DETACH_ROUND_DELAY_MS 1000
|
||||
|
||||
#if (CONFIG_IDF_TARGET_ESP32P4)
|
||||
#define USB_SRP_BVALID_IN_IDX USB_SRP_BVALID_PAD_IN_IDX
|
||||
#endif // CONFIG_IDF_TARGET_ESP32P4
|
||||
|
||||
/* TinyUSB descriptors
|
||||
********************************************************************* */
|
||||
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN)
|
||||
|
||||
static unsigned int dev_mounted = 0;
|
||||
static unsigned int dev_umounted = 0;
|
||||
|
||||
static uint8_t const test_configuration_descriptor[] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
};
|
||||
|
||||
static const tusb_desc_device_t test_device_descriptor = {
|
||||
.bLength = sizeof(test_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 = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers
|
||||
.idProduct = 0x4002,
|
||||
.bcdDevice = 0x100,
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
// Invoked when device is mounted
|
||||
void tud_mount_cb(void)
|
||||
{
|
||||
/**
|
||||
* @attention Tests relying on this callback only pass on Linux USB Host!
|
||||
*
|
||||
* This callback is issued after SetConfiguration command from USB Host.
|
||||
* However, Windows issues SetConfiguration only after a USB driver was assigned to the device.
|
||||
* So in case you are implementing a Vendor Specific class, or your device has 0 interfaces, this callback is not issued on Windows host.
|
||||
*/
|
||||
printf("%s\n", __FUNCTION__);
|
||||
dev_mounted++;
|
||||
}
|
||||
|
||||
// Invoked when device is unmounted
|
||||
void tud_umount_cb(void)
|
||||
{
|
||||
printf("%s\n", __FUNCTION__);
|
||||
dev_umounted++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TinyUSB Disconnect Detection test case
|
||||
*
|
||||
* This is specific artificial test for verifying the disconnection detection event.
|
||||
* Normally, this event comes as a result of detaching USB device from the port and disappearing the VBUS voltage.
|
||||
* In this test case, we use GPIO matrix and connect the signal to the ZERO or ONE constant inputs.
|
||||
* Connection to constant ONE input emulates the attachment to the USB Host port (appearing VBUS).
|
||||
* Connection to constant ZERO input emulates the detachment from the USB Host port (removing VBUS).
|
||||
*
|
||||
* Test logic:
|
||||
* - Install TinyUSB Device stack without any class
|
||||
* - In cycle:
|
||||
* - Emulate the detachment, get the tud_umount_cb(), increase the dev_umounted value
|
||||
* - Emulate the attachment, get the tud_mount_cb(), increase the dev_mounted value
|
||||
* - Verify that dev_umounted == dev_mounted
|
||||
* - Verify that dev_mounted == DEVICE_DETACH_TEST_ROUNDS, where DEVICE_DETACH_TEST_ROUNDS - amount of rounds
|
||||
* - Uninstall TinyUSB Device stack
|
||||
*
|
||||
*/
|
||||
TEST_CASE("dconn_detection", "[esp_tinyusb][dconn]")
|
||||
{
|
||||
unsigned int rounds = DEVICE_DETACH_TEST_ROUNDS;
|
||||
|
||||
// Install TinyUSB driver
|
||||
const tinyusb_config_t tusb_cfg = {
|
||||
.device_descriptor = &test_device_descriptor,
|
||||
.string_descriptor = NULL,
|
||||
.string_descriptor_count = 0,
|
||||
.external_phy = false,
|
||||
#if (TUD_OPT_HIGH_SPEED)
|
||||
.fs_configuration_descriptor = test_configuration_descriptor,
|
||||
.hs_configuration_descriptor = test_configuration_descriptor,
|
||||
.qualifier_descriptor = &device_qualifier,
|
||||
#else
|
||||
.configuration_descriptor = test_configuration_descriptor,
|
||||
#endif // TUD_OPT_HIGH_SPEED
|
||||
};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg));
|
||||
|
||||
dev_mounted = 0;
|
||||
dev_umounted = 0;
|
||||
|
||||
while (rounds--) {
|
||||
// LOW to emulate disconnect USB device
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS));
|
||||
// HIGH to emulate connect USB device
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS));
|
||||
}
|
||||
|
||||
// Verify
|
||||
TEST_ASSERT_EQUAL(dev_umounted, dev_mounted);
|
||||
TEST_ASSERT_EQUAL(DEVICE_DETACH_TEST_ROUNDS, dev_mounted);
|
||||
|
||||
// Cleanup
|
||||
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall());
|
||||
}
|
||||
#endif // SOC_USB_OTG_SUPPORTED
|
||||
@@ -0,0 +1,13 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
|
||||
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32p4
|
||||
#@pytest.mark.usb_device Disable in CI: unavailable teardown for P4
|
||||
def test_usb_device_dconn_detection(dut: IdfDut) -> None:
|
||||
dut.run_all_single_board_cases(group='dconn')
|
||||
@@ -0,0 +1,18 @@
|
||||
# Configure TinyUSB, it will be used to mock USB devices
|
||||
CONFIG_TINYUSB_MSC_ENABLED=n
|
||||
CONFIG_TINYUSB_CDC_ENABLED=n
|
||||
CONFIG_TINYUSB_CDC_COUNT=0
|
||||
CONFIG_TINYUSB_HID_COUNT=0
|
||||
|
||||
# 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
|
||||
Reference in New Issue
Block a user