change(usb_serial_jtag): Add a usb_serial_jtag echo example for how to use usb_serial_jtag APIs,

Closes https://github.com/espressif/esp-idf/issues/12620,
Closes https://github.com/espressif/esp-idf/issues/12605
This commit is contained in:
Cao Sen Miao 2023-11-28 18:50:50 +08:00
parent 93b2297dc1
commit 932d595256
9 changed files with 194 additions and 7 deletions

View File

@ -217,6 +217,14 @@ pytest_examples_esp32c6_generic:
- build_pytest_examples_esp32c6 - build_pytest_examples_esp32c6
tags: [ esp32c6, generic ] tags: [ esp32c6, generic ]
pytest_examples_esp32c6_usj_device:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32c6
needs:
- job: build_pytest_examples_esp32c6
tags: [ esp32c6, usj_device ]
pytest_examples_esp32h2_generic: pytest_examples_esp32h2_generic:
extends: extends:
- .pytest_examples_dir_template - .pytest_examples_dir_template

View File

@ -1,8 +1,6 @@
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# pylint: disable=W0621 # redefined-outer-name # pylint: disable=W0621 # redefined-outer-name
# This file is a pytest root configuration file and provide the following functionalities: # This file is a pytest root configuration file and provide the following functionalities:
# 1. Defines a few fixtures that could be used under the whole project. # 1. Defines a few fixtures that could be used under the whole project.
# 2. Defines a few hook functions. # 2. Defines a few hook functions.
@ -12,7 +10,6 @@
# #
# This is an experimental feature, and if you found any bug or have any question, please report to # This is an experimental feature, and if you found any bug or have any question, please report to
# https://github.com/espressif/pytest-embedded/issues # https://github.com/espressif/pytest-embedded/issues
import logging import logging
import os import os
import re import re
@ -20,10 +17,14 @@ import sys
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from datetime import datetime from datetime import datetime
from fnmatch import fnmatch from fnmatch import fnmatch
from typing import Callable, List, Optional, Tuple from typing import Callable
from typing import List
from typing import Optional
from typing import Tuple
import pytest import pytest
from _pytest.config import Config, ExitCode from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.nodes import Item from _pytest.nodes import Item
@ -31,7 +32,8 @@ from _pytest.python import Function
from _pytest.reports import TestReport from _pytest.reports import TestReport
from _pytest.runner import CallInfo from _pytest.runner import CallInfo
from _pytest.terminal import TerminalReporter from _pytest.terminal import TerminalReporter
from pytest_embedded.plugin import multi_dut_argument, multi_dut_fixture from pytest_embedded.plugin import multi_dut_argument
from pytest_embedded.plugin import multi_dut_fixture
from pytest_embedded.utils import find_by_suffix from pytest_embedded.utils import find_by_suffix
from pytest_embedded_idf.dut import IdfDut from pytest_embedded_idf.dut import IdfDut
@ -138,6 +140,7 @@ ENV_MARKERS = {
'generic_multi_device': 'generic multiple devices whose corresponding gpio pins are connected to each other.', 'generic_multi_device': 'generic multiple devices whose corresponding gpio pins are connected to each other.',
'twai_network': 'multiple runners form a TWAI network.', 'twai_network': 'multiple runners form a TWAI network.',
'sdio_master_slave': 'Test sdio multi board.', 'sdio_master_slave': 'Test sdio multi board.',
'usj_device': 'Test usb_serial_jtag and usb_serial_jtag is used as serial only (not console)',
} }

View File

@ -288,6 +288,14 @@ examples/peripherals/usb:
disable: disable:
- if: SOC_USB_OTG_SUPPORTED != 1 - if: SOC_USB_OTG_SUPPORTED != 1
examples/peripherals/usb_serial_jtag/usb_serial_jtag_echo:
disable:
- if: SOC_USB_SERIAL_JTAG_SUPPORTED != 1
disable_test:
- if: IDF_TARGET in ["esp32s3", "esp32c3", "esp32h2"]
temporary: true
reason: lack of runners. Hardware is similar, test on one target is enough currently.
examples/peripherals/wave_gen: examples/peripherals/wave_gen:
enable: enable:
- if: IDF_TARGET == "esp32" - if: IDF_TARGET == "esp32"

View File

@ -0,0 +1,6 @@
# 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)
project(usb_serial_jtag_echo)

View File

@ -0,0 +1,60 @@
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- |
# USB SERIAL JTAG Echo Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to utilize USB_SERIAL_JTAG interfaces by echoing back to the sender any data received on USB_SERIAL_JTAG.
## How to use example
### Hardware Required
The example can be run on development board that supports usb_serial_jtag, that is based on the Espressif SoC. The board shall be connected to a computer with a single USB cable for flashing and monitoring with UART port. The usb_serial_jtag port on board can be be connected to computer with another USB cable to get the echo.
### Configure the project
Use the command below to configure project using Kconfig menu as showed in the table above.
The default Kconfig values can be changed such as disable the `ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG`
```
idf.py menuconfig
```
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
Type some characters in the terminal connected to the external serial interface. As result you should see echo in the same terminal which you used for typing the characters.
For example, If I type `hi espressif`, `See you again!`, `Echo a very long buffer. Assume this buffer is very large and you can see whole buffer`
And you can get the log with:
```
I (296) main_task: Started on CPU0
I (296) main_task: Calling app_main()
I (296) main_task: Returned from app_main()
I (13346) Recv str: : 0x408117b8 68 69 20 65 73 70 72 65 73 73 69 66 0d 0a |hi espressif..|
I (16606) Recv str: : 0x408117b8 53 65 65 20 79 6f 75 20 61 67 61 69 6e 21 0d 0a |See you again!..|
I (18726) Recv str: : 0x408117b8 45 63 68 6f 20 61 20 76 65 72 79 20 6c 6f 6e 67 |Echo a very long|
I (18726) Recv str: : 0x408117c8 20 62 75 66 66 65 72 2e 20 41 73 73 75 6d 65 20 | buffer. Assume |
I (18726) Recv str: : 0x408117d8 74 68 69 73 20 62 75 66 66 65 72 20 69 73 20 76 |this buffer is v|
I (18736) Recv str: : 0x408117e8 65 72 79 20 6c 61 72 67 65 20 61 6e 64 20 79 6f |ery large and yo|
I (18746) Recv str: : 0x408117b8 75 20 63 61 6e 20 73 65 65 20 77 68 6f 6c 65 20 |u can see whole |
I (18756) Recv str: : 0x408117c8 62 75 66 66 65 72 0d 0a |buffer..|
```
## Troubleshooting
Note that you are not supposed to see the echo in the terminal if usb_serial_jtag port is used for flashing and monitoring.

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "usb_serial_echo_main.c"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/usb_serial_jtag.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_check.h"
#define BUF_SIZE (1024)
#define ECHO_TASK_STACK_SIZE (2048)
static void echo_task(void *arg)
{
// Configure USB SERIAL JTAG
usb_serial_jtag_driver_config_t usb_serial_jtag_config = {
.rx_buffer_size = BUF_SIZE,
.tx_buffer_size = BUF_SIZE,
};
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&usb_serial_jtag_config));
ESP_LOGI("usb_serial_jtag echo", "USB_SERIAL_JTAG init done");
// Configure a temporary buffer for the incoming data
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
if (data == NULL) {
ESP_LOGE("usb_serial_jtag echo", "no memory for data");
return;
}
while (1) {
int len = usb_serial_jtag_read_bytes(data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
// Write data back to the USB SERIAL JTAG
if (len) {
usb_serial_jtag_write_bytes((const char *) data, len, 20 / portTICK_PERIOD_MS);
data[len] = '\0';
ESP_LOG_BUFFER_HEXDUMP("Recv str: ", data, len, ESP_LOG_INFO);
}
}
}
void app_main(void)
{
xTaskCreate(echo_task, "USB SERIAL JTAG_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL);
}

View File

@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
from time import sleep
import pytest
import serial.tools.list_ports
from pytest_embedded import Dut
@pytest.mark.esp32c6 # usb_serial_jtag is very similar, test C6 is enough.
@pytest.mark.usj_device
def test_usb_device_echo_example(dut: Dut) -> None:
dut.expect_exact('USB_SERIAL_JTAG init done')
sleep(2)
ports = list(serial.tools.list_ports.comports())
for p in ports:
if (p.device == '/dev/ttyACM0'): # Get the usb_serial_jtag port
with serial.Serial(p.device) as s:
s.write(b'hi, espressif\n')
sleep(1)
dut.expect_exact('hi, espressif')
res = s.readline()
assert b'hi, espressif' in res
s.write(b'See you again!\n')
sleep(1)
dut.expect_exact('See you again!')
res = s.readline()
assert b'See you again!' in res
s.write(b'Echo a very long buffer. Assume this buffer is very large and you can see whole buffer\n')
sleep(1)
dut.expect_exact('Echo a very long') # 16 bytes a line because we use `ESP_LOG_BUFFER_HEXDUMP` in code.
dut.expect_exact(' buffer. Assume ')
dut.expect_exact('this buffer is v')
dut.expect_exact('ery large and yo')
dut.expect_exact('u can see whole ')
dut.expect_exact('buffer')
res = s.readline()
assert b'Echo a very long buffer. Assume this buffer is very large and you can see whole buffer' in res
s.write(b'64 bytes buffer:-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-\n')
sleep(1)
res = s.readline()
assert b'64 bytes buffer:-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-' in res
return
raise Exception('usb_serial_jtag port not found')

View File

@ -0,0 +1 @@
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y