基于炬芯ATS3089X的usb U盘/usb audio声卡/usb cdc虚拟串口/录音dump到本地功能实现

目前我们做气密性测试,每次录音后,都要插usb数据线,进入U盘模式,手动把录音pcm文件拷贝出来,很麻烦,因此想实现直接启动录音dump, 用一条指令启动录音和dunp, 可以dump Pcm文件到电脑本地

ATS3089P USB 虚拟串口

本功能使用芯片 USB 控制器实现 CDC ACM。开发板 GPIO75/DP、GPIO76/DM 已接到 USB 接口,使用能传输数据的 USB 线连接电脑即可,不需要 USB 转 UART 板,也不需要把 DP/DM 改成 UART 引脚。

使用指令

首次通过现有串口执行:

```text

app usbserial on

```

若当前为 U 盘或 USB 声卡,程序先退出旧模式,再重新枚举为 USB 串口。电脑串口工具选择新出现的 COM 口,设置 **115200、8N1、无硬件流控**,DTR 可以为 0 或 1。这里的波特率是 CDC 参数,实际数据通过 USB 传输。枚举完成后会输出 `CDC console ready`,打开 COM 后按回车可以显示 shell 提示符;原有 `app`、`audio` 等命令可以直接从 USB 输入,日志和命令响应也通过 USB 输出。

设备描述符采用 CDC class 02 / subclass 02,匹配 Windows 内置 Usbser 驱动的自动加载条件,见微软说明(https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-driver-installation-based-on-compatible-ids)。实际设备枚举、串口工具兼容性需要上板验证。

| 指令 | 作用 |

| --- | --- |

| `app usbserial on` | 切换到 USB 串口;未插线时等待连接 |

| `app usbserial off` | 关闭 USB 串口 |

| `app usbserial status` | 查看启用、枚举、DTR、丢弃字节和开机设置 |

| `app usbserial boot on` | 保存开机自动启用 USB 串口 |

| `app usbserial boot off` | 取消开机自动启用 |

| `app udisk on` | 关闭串口/声卡,切换到 U 盘 |

| `app usbaudio on` | 关闭串口/U 盘,切换到 USB 声卡 |

希望以后只插 USB 使用,首次设置:

```text

app usbserial boot on

app usbserial on

```

`boot` 只保存下次启动的偏好,不立即切换当前模式。默认未设置时保持原有启动行为。启用自动串口后,它优先于开机自动进入 U 盘的逻辑;手动切到 U 盘或声卡不修改这个开机偏好。

三种模式互斥,切换后电脑上的旧设备会消失。如果通过 USB 串口输入切换指令,当前 COM 口也会断开;切回串口可用原物理 UART 指令,或在已保存 `boot on` 的情况下重启开发板。U 盘切出前先停止电脑文件传输并安全弹出。

气密性测试:录音并保存到电脑

本次 ATS3089P 固件:`outdir/ats3089p_dev_watch/_firmware/ats3089p_dev_watch_261012_usb_cdc_pcm_debug.fw`;同目录另有完整包 `ats3089p_dev_watch_261012_usb_cdc_pcm.fw`。

如果电脑上已经出现本板的 USB CDC COM 口,直接使用即可,不需要接串口板;可在该 COM 的 shell 中执行一次 `app usbserial boot on`,让以后开机自动进入 CDC。若 CDC 尚未启用,首次仍需通过已有控制入口执行 `app usbserial boot on` 和 `app usbserial on`。以后只需用 USB 数据线连接电脑,在设备管理器中找到 COM 口,无需进入 U 盘模式或手动复制文件。电脑安装 Python 和 `pyserial`:

```text

python -m pip install pyserial

```

在项目目录执行一条命令(把 `COMx` 换成实际端口):

```text

python application/bt_watch/tools/record/usb_pcm_capture.py --port COMx --seconds 10

```

工具通过 CDC 虚拟串口向板子发送 `audio record usb_dump seconds=10`。板子按现有气密性测试参数录制 16 kHz、16 bit、单声道 PCM,录音结束后关闭文件,再把完整 PCM 按长度和 CRC 校验信息传给电脑。工具校验后在电脑端执行命令的当前目录自动选择不覆盖旧文件的名称(`rec.pcm`、`rec1.pcm`、`rec2.pcm`......);板子的 NAND 中也保留本次录音文件。传输在录音**结束后**进行,不是边录边传,因此不会让 USB 发送速度影响采样。

也可以在 CDC 的 shell 中直接执行 `audio record usb_dump seconds=10`;需要由配套上位机工具接收并提取 PCM。若录音已完成而电脑端接收失败,可用以下命令重传**本次开机期间最近一次 `usb_dump` 录音**,无需重新录音:

```text

python application/bt_watch/tools/record/usb_pcm_capture.py --port COMx --export

```

工具会向板子发送 `audio record usb_export`。重启后不能恢复此前的重传目标;普通 `audio record` 录音也不是 `usb_export` 的目标。需要指定电脑端文件名时,可追加 `--output rec_retry.pcm`。

UartAssist 等串口助手的"原样保存接收数据"会把命令回显、传输头尾等内容一起写入文件,所得文件不能直接当作裸 PCM。请使用上述工具完成长度、CRC 校验和自动命名。

每次录音的 PCM/Opus 文件仍保存在板子 NAND 中并自动编号;连续产测时需定期清理旧文件,避免 NAND 空间耗尽。

USB 串口产测 MAC 查询

USB 串口开启并打开 COM 后,使用 ASCII 文本发送:

```text

AT+FTEST=MAC

```

命令必须以回车 `\r`、换行 `\n` 或 `\r\n` 结束;串口工具可以勾选"发送新行"。成功回复一行,末尾为 `\r\n`:

```text

MAC,OK,78:02:B7:13:12:CE

```

上面是格式示例,实际返回开发板正在使用的蓝牙本机 MAC(大写、冒号分隔),与控制器的 `BT_MAC` 配置一致。蓝牙尚未初始化时读取保存的地址;地址缺失或无效时返回 `MAC,ERROR,NOT_READY`。查询不会生成或修改地址。

命令复用现有 shell,USB 接收支持分包,原物理 UART 也可使用。USB 上仍有日志、命令回显和提示符,产测程序按 `MAC,OK,` / `MAC,ERROR,` 响应行识别结果。例如用 Python 的 pyserial 打开已识别的 COM 口并发送:

```python

import re

import time

import serial

with serial.Serial("COM14", 115200, timeout=0.2) as port:

port.dtr = False # DTR is optional; tools that leave it low also work.

port.write(b"AT+FTEST=MAC\r\n")

deadline = time.monotonic() + 3

received = bytearray()

while time.monotonic() < deadline:

received.extend(port.read(256))

match = re.search(rb"MAC,OK,(0-9A-F{2}(?::0-9A-F{2}){5})\r\n", received)

if match:

print("USB RX/TX OK, MAC:", match.group(1).decode("ascii"))

break

if b"MAC,ERROR,NOT_READY\r\n" in received:

raise RuntimeError("Board MAC is not ready")

else:

raise TimeoutError("No MAC response from the USB serial port")

```

状态和限制

  • 正常枚举后应看到 `enabled=1 configured=1 owner=3`,DTR 为 0 或 1 均能收发。`owner`:0 空闲、1 U 盘、2 声卡、3 串口。

  • `enabled=1 configured=0` 表示已选择串口模式但尚未完成枚举;检查数据线、连接和电脑设备管理器。

  • `configured=1 DTR=0` 表示电脑已枚举且 DTR 为低,不代表收发不可用。

  • 日志队列 4096 字节,队列满时丢弃新日志并累加 `dropped`,避免电脑不读取拖住系统。未枚举、挂起或关闭串口功能时丢弃日志。不要同时从 USB 和物理 UART 输入命令,以免字符混入同一命令行。

  • 覆盖应用运行阶段的日志;ROM、Bootloader 和 CDC 启动前的日志仍需物理 UART。USB 串口启用期间持有唤醒锁,调试后可执行 `off` 允许系统恢复休眠。

  • USB 线拔插后会等待重新枚举,电脑端可能需要重新打开 COM 口。PCM 导出只在执行 `audio record usb_dump` 或 `audio record usb_export` 时启动。

  • 手动开启串口、U 盘或声卡时,模式保持到关闭或切换;U 盘也支持电脑安全弹出退出。拔线后可执行 `app udisk off` 退出 U 盘并重新挂载设备文件系统。

261010 枚举修复

`log_26_9_29.txt` 中执行 `app usbserial on` 后,状态一直为 `configured=0`,电源日志一直报告 `dc5v:0 <OUT>`。当前板的 USB 热插拔检测读取外部充电芯片的 DC5V 状态;旧版工作线程因此没有初始化 CDC,热插拔定时器也会按 DC5V=0 断开 USB。

现在 `on` 指令立即初始化 USB 设备,不再等待 DC5V。三种模式通过共同的 USB 占用机制暂停自动探测和定时器断开,关闭后恢复原有检测。DC5V 的实际读数仍用于诊断。另修复 CDC 描述符末尾缺少 SDK 遍历终止字节、模式切换时字符串残留,以及高速连接复位后未恢复全速描述符的问题。

烧录 `ats3089p_dev_watch_261010_debug.fw` 后,先用物理串口执行:

```text

app usbserial on

app usbserial status

```

第一条应输出 `usbserial-v2 CDC init=0`,表示驱动已经实际启动。电脑完成枚举时会看到 `USB reset`、`USB configured`;`status` 同时输出驱动启动结果、PMU_DC5V、复位次数、配置次数和控制请求次数。此时即使 PMU_DC5V=0,也应允许正常枚举。

261010 串口助手收发修复(v3)

上一版运行线程将 DTR 作为 USB 收发的必需条件。有些串口助手打开 COM 后仍保持 DTR=0,设备虽然已枚举,却不读取 OUT 数据,也不发送日志和查询回复。

现在以 USB 已配置且未挂起作为收发条件,DTR 仅用于诊断。打开友善串口调试助手的 COM14 后即可收到日志,发送以 CR/LF 结束的 `AT+FTEST=MAC` 即可查询地址。开启时应看到 `usbserial-v3 CDC console ready, DTR=0 (optional)` 或 DTR=1。

`app usbserial status` 新增 `rx_bytes`(驱动读到的 USB 字节数)和 `tx_queued_bytes`(交给 USB IN 端点的字节数),每次重新开启串口功能时清零。若发送后 rx_bytes 增长但未执行命令,应检查发送内容末尾是否包含回车/换行;助手的"接收自动换行"设置只影响显示。

实现与验证

入口在 `src/main/usb_serial_runtime.c`。CDC 驱动修正了高速 bulk 最大包长(512 字节)、全速/高速接收包长、复位与挂起状态、接收背压及发送缓冲的使用周期。日志回调仅入队,USB 发送和 shell 输入转交由工作线程处理。

U 盘、声卡、串口共用原子 ownership 标记,旧模式完成 USB 退出后才释放;U 盘还要完成刷盘和重新挂载,声卡还要结束延迟工作。关键改动带 `//zk+` 或 `//zk+-` 标记。

构建后运行:

```text

python application/bt_watch/tests/usb_serial/run_tests.py

python application/bt_watch/tests/usb_serial/run_core_tests.py

python application/bt_watch/tests/usb_serial/run_factory_tests.py

python application/bt_watch/tests/ringtone/run_tests.py

```

USB 测试执行真实 ELF 中的 ARM 代码,模拟 USB 硬件及 RTOS 边界,覆盖描述符、全速/高速收发、控制请求、复位、挂起恢复、队列溢出、模式占用、工作线程、shell 接收和模拟拔插。它不能替代电脑上的真实 USB 枚举测试。

核心枚举测试另外执行 SDK 的真实描述符遍历和字符串注册代码,验证全速→高速→全速复位的端点参数,以及长字符串切换到短字符串时的终止和返回内容。

产测测试执行链接的根命令查找、shell 解析及真实查询处理代码,验证 MAC 的字节顺序、缓存优先、开机读取、无效地址及查询不会改写配置。

上板建议依次验证:打开 COM 收日志并执行 `app usbserial status`;执行原有 `app ringtone play 1` / `app ringtone stop`;拔插 USB 并重开 COM;切换 U 盘、声卡、串口;保存 `boot on` 后断电重启确认自动出现 COM 口。

相关推荐
@松2 小时前
学习stm32cudemx +vs 创建hex文件,刷机
stm32
CC180253944862 小时前
具有强大的图像和语音处理能力的高性能 MCU芯片ESP32-P4NRW32X
单片机·嵌入式硬件
小范的技术工坊3 小时前
Linux应用开发(文件IO)
linux·stm32·单片机
科芯创展4 小时前
XZ1824 宽电压150V 10A开关降压DC-DC控制器技术解析
单片机
恒锐丰科技林技术员4 小时前
EG1416 低侧栅极驱动芯片:小封装下的功率驱动利器
经验分享·嵌入式硬件·硬件工程
Zwawa5 小时前
让电机走到指定位置:编码器位置环 PID
c语言·单片机·嵌入式
桀人5 小时前
I2C概念引入
stm32·单片机·嵌入式硬件
神一样的老师6 小时前
RA4M2 + AHT20 温湿度传感器实战
单片机·嵌入式硬件
我是人✓7 小时前
STM32上跑FreeRTOS:实时任务调度全解析
stm32·单片机·嵌入式硬件