fix hil host cdc echo test with imxrt and other fast mcu

This commit is contained in:
hathach
2026-04-02 23:30:06 +07:00
parent b3d34cdf89
commit 134e14849b
11 changed files with 89 additions and 92 deletions

View File

@ -26,9 +26,3 @@ add_custom_target(tinyusb_metrics
COMMENT "Generating average code size metrics"
VERBATIM
)
#add_custom_command(TARGET tinyusb_metrics POST_BUILD
# COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../tools/metrics.py compare ${TOP}/cmake-build/cmake-build-${BOARD}/metrics.json ${CMAKE_BINARY_DIR}/metrics.json
# COMMENT "Generating average code size metrics"
# VERBATIM
# )

View File

@ -28,11 +28,13 @@
#include "bsp/board_api.h"
#include "app.h"
static size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
static size_t console_read(uint8_t *buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
if (ch <= 0) { break; }
const int ch = board_getchar();
if (ch < 0) {
break;
}
buf[count] = (uint8_t) ch;
count++;
}
@ -40,46 +42,54 @@ static size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
return count;
}
void cdc_app_task(void) {
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
// loop over all mounted interfaces
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
if (tuh_cdc_mounted(idx)) {
// console --> cdc interfaces
if (count > 0) {
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
static size_t console_write(const uint8_t *buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
if (board_putchar((int)buf[count]) < 0) {
break;
}
count++;
}
return count;
}
// forward from console to usbh
static void console_to_usbh(uint8_t idx) {
uint8_t buf[64];
size_t count = console_read(buf, sizeof(buf));
if (count > 0) {
tuh_cdc_write(idx, buf, count);
}
}
void cdc_app_task(void) {
const uint8_t idx = 0;
// Bidirectional forwarding: console <-> host cdc interfaces
if (!tuh_cdc_mounted(idx)) {
return;
}
// usbh -> uart
uint8_t buf[64];
uint32_t count = tuh_cdc_read(idx, buf, sizeof(buf));
uint32_t wr = 0;
do {
// uart write is slow, while waiting forward uart -> usbh else uart rx can be overflow
if (count) {
wr += console_write(buf + wr, count);
}
console_to_usbh(idx);
} while (wr < count);
tuh_cdc_write_flush(idx);
}
//--------------------------------------------------------------------+
// TinyUSB callbacks
//--------------------------------------------------------------------+
// Invoked when received new data
void tuh_cdc_rx_cb(uint8_t idx) {
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
// forward cdc interfaces -> console
const uint32_t count = tuh_cdc_read(idx, buf, bufsize);
if (count) {
buf[count] = 0;
printf("%s", (char*) buf);
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout);// flush right away, else nanolib will wait for newline
#endif
}
}
// Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {

View File

@ -102,8 +102,11 @@
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
// Increase task event queue to handle rapid bulk transfer completions
#define CFG_TUH_TASK_QUEUE_SZ 64
#define CFG_TUH_HUB 1 // number of supported hubs
#define CFG_TUH_CDC 2 // number of supported CDC devices. also activates CDC ACM
#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API

View File

@ -53,7 +53,7 @@ void cdc_app_init(void) {
}
// helper
static size_t get_console_inputs(uint8_t *buf, size_t bufsize) {
static size_t console_read(uint8_t *buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
@ -75,7 +75,7 @@ static void cdc_app_task(void* param) {
uint32_t const bufsize = sizeof(buf) - 1;
while (1) {
uint32_t count = get_console_inputs(buf, bufsize);
uint32_t count = console_read(buf, bufsize);
buf[count] = 0;
if (count) {

View File

@ -23,39 +23,6 @@
*
*/
/* Example to show how to navigate mass storage device with built-in command line.
* Type help for list of supported commands and syntax (mostly linux commands)
> help
* help
Print list of commands
* cat
Usage: cat [FILE]...
Concatenate FILE(s) to standard output..
* cd
Usage: cd [DIR]...
Change the current directory to DIR.
* cp
Usage: cp SOURCE DEST
Copy SOURCE to DEST.
* ls
Usage: ls [DIR]...
List information about the FILEs (the current directory by default).
* pwd
Usage: pwd
Print the name of the current working directory.
* mkdir
Usage: mkdir DIR...
Create the DIRECTORY(ies), if they do not already exist..
* mv
Usage: mv SOURCE DEST...
Rename SOURCE to DEST.
* rm
Usage: rm [FILE]...
Remove (unlink) the FILE(s).
*/
#include <stdlib.h>
#include <string.h>
#include "bsp/board_api.h"

View File

@ -97,9 +97,17 @@ int sys_read (int fhdl, char *buf, size_t count) {
#else
// Default logging with on-board UART
// Retry to ensure printf/log output is not lost when board_uart_write is non-blocking
int sys_write (int fhdl, const char *buf, size_t count) {
(void) fhdl;
return board_uart_write(buf, (int) count);
int written = 0;
while ((size_t)written < count) {
int wr = board_uart_write(buf + written, (int)(count - (size_t)written));
if (wr > 0) {
written += wr;
}
}
return written;
}
int sys_read (int fhdl, char *buf, size_t count) {
@ -157,10 +165,13 @@ int board_getchar(void) {
return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
}
void board_putchar(int c) {
(void) sys_write(0, (const char*)&c, 1);
int board_putchar(int c) {
if (board_uart_write((const char *)&c, 1)) {
return c;
} else {
return -1;
}
}
//--------------------------------------------------------------------
// FreeRTOS hooks
//--------------------------------------------------------------------

View File

@ -92,10 +92,10 @@ uint32_t board_button_read(void);
// Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16
size_t board_get_unique_id(uint8_t id[], size_t max_len);
// Get characters from UART. Return number of read bytes
// Get characters from UART (non-blocking). Return number of read bytes.
int board_uart_read(uint8_t *buf, int len);
// Send characters to UART. Return number of sent bytes
// Send characters to UART (non-blocking). Return number of sent bytes
int board_uart_write(void const *buf, int len);
//--------------------------------------------------------------------+
@ -153,7 +153,7 @@ static inline void board_delay(uint32_t ms) {
// stdio getchar() is blocking, this is non-blocking version
int board_getchar(void);
void board_putchar(int c);
int board_putchar(int c);
#ifdef __cplusplus
}

View File

@ -162,8 +162,8 @@ int board_getchar(void) {
return getchar();
}
void board_putchar(int c) {
putchar(c);
int board_putchar(int c) {
return putchar(c);
}
void board_init_after_tusb(void) {

View File

@ -229,8 +229,17 @@ int board_uart_read(uint8_t *buf, int len) {
}
int board_uart_write(void const *buf, int len) {
LPUART_WriteBlocking(UART_PORT, (uint8_t const *) buf, len);
return len;
const uint8_t *p = (const uint8_t *)buf;
int count = 0;
while (count < len) {
if (LPUART_GetStatusFlags(UART_PORT) & kLPUART_TxDataRegEmptyFlag) {
LPUART_WriteByte(UART_PORT, p[count]);
count++;
} else {
break;
}
}
return count;
}
#if CFG_TUSB_OS == OPT_OS_NONE

View File

@ -288,8 +288,8 @@ int board_getchar(void) {
return getchar_timeout_us(0);
}
void board_putchar(int c) {
stdio_putchar(c);
int board_putchar(int c) {
return stdio_putchar(c);
}
void board_init_after_tusb(void) {

View File

@ -564,7 +564,7 @@ def test_host_cdc_msc_hid(board):
ser.flush()
# wait until this chunk is echoed back
echo = b''
t_end = time.monotonic() + 5.0
t_end = time.monotonic() + 1.0
while time.monotonic() < t_end and len(echo) < chunk_size:
rd = ser.read(chunk_size - len(echo))
if rd:
@ -1189,7 +1189,7 @@ def test_example(board, f1, example):
print(f'Flashing {fw_name}.elf')
# flash firmware. It may fail randomly, retry a few times
max_rety = 3
max_rety = max_retry
start_s = time.time()
for i in range(max_rety):
ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name)
@ -1269,6 +1269,7 @@ def main():
global verbose
global test_only
global build_dir
global max_retry
duration = time.time()
@ -1278,6 +1279,7 @@ def main():
parser.add_argument('-s', '--skip', action='append', default=[], help='Skip boards from test')
parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified')
parser.add_argument('-B', '--build', default='cmake-build', help='Build folder name (default: cmake-build)')
parser.add_argument('-r', '--retry', type=int, default=3, help='Retry count for failed tests (default: 3)')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
args = parser.parse_args()
@ -1287,6 +1289,7 @@ def main():
verbose = args.verbose
test_only = args.test_only
build_dir = args.build
max_retry = args.retry
# if config file is not found, try to find it in the same directory as this script
if not os.path.exists(config_file):