ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

当我把四个串口交给 AI:一次 2.4G 双向透传的完整调试闭环

当我把四个串口交给 AI:一次 2.4G 双向透传的完整调试闭环 从“你把日志贴给我看”到“你直接读串口、发数据、烧固件、统计丢包”嵌入式开发的协作方式发生了什么变化一、需求看起来并不复杂项目使用两块相同的 GD32F303CC Tag 板和 SI24R1 2.4 GHz模块希望实现一条双向透明串口链路发射端串口收到什么接收端串口就输出什么接收端串口收到什么发射端串口也原样输出两端通过 C1按键完成配对芯片是半双工不能让两端同时抢占空口命令行支持编译、CMSIS-DAP和J-Link下载原 Base业务的ADC采样频率为100 Hz链路需要承受双向持续数据。真正困难的地方不在“发一包、收一包”而在于同时处理半双工调度、ACK Payload滞后一轮、应用层确认、串口DMA、掉电恢复、配对事务和持续吞吐。最终架构确定为发射端固定为 PTX是唯一主动发包者接收端固定为 PRX通过 SI24R1 ACK Payload回传数据空中每帧最多32字节其中透明业务数据最多22字节两端USART1是纯字节流内部无线协议不会泄漏到业务串口USART0只负责日志USART1只负责透传。二、先把工程从“能打开”变成“能重复构建”我们没有继续在原 Tag或Base工程上堆条件编译而是建立独立工程CMSIS_RTX5_F303_Transparent构建方式参考另一个VCU项目Python直接调用arm-none-eabi-gcc并行编译不依赖Keil GUI和GNU Make。新的正式命令直接使用业务含义命名python build/build.py transmitter python build/build.py receiver python build/flash.py flash transmitter dap--yes python build/flash.py flash receiver dap--yes固件产物也不再叫含义模糊的A和B而是transparent_transmitter.bin transparent_receiver.bin这是一个很小但重要的工程决策。固件交给测试、生产或其他开发者后不需要额外解释“A到底是哪一端”。三、第一个问题代码里有日志串口却一片安静USART0已经初始化ELF里也能找到日志字符串但PA9没有任何输出。根因不是串口配置而是编译器运行库不同原Keil工程通过fputc()重定向printf()新GNU GCC工程使用newlibprintf()最终调用_write()工程没有实现_write()链接器使用了libnosys的空实现。于是日志被正常格式化然后悄无声息地丢弃。补上_write() - USART0后启动日志终于出现boot transparent roletransmitter/PTX这个问题提醒我们嵌入式移植不能只看外设初始化还要检查C运行库的系统调用边界。四、第二个问题接收端能收到几千包发射端却认为全部失败配对时接收端不断打印pair receiver: beacon received但发射端统计几乎是MAX_RT ≈ TX RX 0这组日志非常关键。它证明发射端到接收端的方向正常但接收端没有形成发射端可接收的硬件自动ACK。问题还没到上层配对协议已经卡在SI24R1硬件应答。对比原Base/Tag后发现新驱动采用了未经这批PA/LNA模块验证的配置。整改包括恢复已验证的CRC配置配对阶段使用4 ms、15次自动重发FEATURE写入后读回必要时执行ACTIVATE 0x73解锁动态载荷和ACK PayloadCE保持到TX_DS或MAX_RT后再拉低。修复后配对顺利进入Beacon、Config、Commit和Sync阶段。五、第三个问题发射端说配对成功接收端却停在SyncACK Payload不是“本次请求立即得到本次响应”。接收端收到请求后才由软件预装响应发射端要到下一次主动发送时才能取回。原同步状态机要求接收端处理两次LINK_SYNC才完成本地配对但发射端取得第一次延迟的SYNC_ACK后就停止发送Sync。结果是发射端显示配对完成接收端停在wait sync两端随后都显示链路断开。修复方法是接收端第一次收到合法Sync后先预装Sync ACK再立即完成本地配对预装的ACK仍留在硬件FIFO中等待发射端下一次重复Sync取走。最终两端同时出现pair complete roletransmitter/PTX link4E6E pair complete rolereceiver/PRX link4E6E link up六、真正的转折把串口权限交给 AI在前面的联调中我需要把日志从串口助手复制出来再发给AI分析。这个过程有三个明显问题两端日志时间不完整很容易只看到结果看不到因果顺序人工复制可能贴错窗口甚至把同一端日志贴两遍“串口助手显示发送成功”并不代表字节真的进入了MCU引脚。后来我明确提供了四个端口并授权AI直接操作端点日志口透明数据口发射端COM3COM6接收端COM26COM27从这一刻开始调试方式变了。AI不再只解释我贴出的日志而是直接完成枚举Windows串口和USB硬件标识同时打开COM3和COM26捕获两端日志向COM6写入11 22 33 44向COM27写入44 33 22 11在对端严格读取并逐字节比较通过OpenOCD复位板卡读取启动测试文本验证PA2物理输出把每次测试固化为可重复执行的Python脚本。第一次自动测试显示Windows确实向COM6和COM27各写出了4字节但两块板的uart1-rx都没有增加。这立刻排除了无线协议。问题发生在USB串口TX到MCU PA3之间。为了进一步分层固件增加了三组统计uart1-rx 本地PA3实际收到的字节 uart1-queued 无线收到后进入USART1 TX队列的字节 uart1-dma DMA完成且USART1 TC置位的字节又增加了一个完全绕过无线和DMA的启动测试USART1_TX_PIN_OKAI打开COM27同时用OpenOCD复位接收板实际捕获到完整18字节文本。这证明接收板PA2、USB串口RX、波特率和Windows端口都正常。最终根因非常朴素USB串口的RX和TX接反了。重新接线后AI再次运行自动测试transmitter - receiver sent11 22 33 44 received11 22 33 44 receiver - transmitter sent44 33 22 11 received44 33 22 11 result forwardPASS reversePASS这件事的价值不只是“AI帮忙看了串口”。更重要的是权限让AI获得了可验证的反馈回路修改代码、构建、烧录、复位、发数据、读数据、比较结果。调试从自然语言问答变成了实验驱动的工程闭环。当然权限应该是明确和最小化的。本次只授权指定COM口、当前工作区和已连接调试器烧录前仍明确区分发射端与接收端整片擦除等破坏性操作没有默认执行。七、短包能通不代表持续流量能通4字节双向测试通过后我们编写了压力脚本tests/uart_stress_test.py每条记录固定20字节包含方向、32位序号、时间戳、图样和CRC16。两端各以100 Hz发送即每方向2000 Byte/s。最初5秒测试是双向0丢包但30秒后出现明显不对称发射端 - 接收端0%丢包 接收端 - 发射端23.2256%丢包固件内部统计显示问题不是COM6也不是PA2输出而是接收端USART1 RX缓冲溢出。反向ACK窗口推进效率不足持续输入最终超过了链路实际排空能力。八、不是盲目增加重发而是重新设计窗口原配置使用4 ms、15次硬件自动重发极端情况下单包可能占用约60 ms。这个策略适合原低频遥控和远距离可靠性目标却不适合持续透明传输。最终整改为普通透传2 ms、3次硬件重发配对阶段仍保留4 ms、15次应用层继续保存未确认数据负责最终可靠交付发送窗口深度从2增加到4ACK使用最后连续接收序号旧序号识别为重复不重复输出超前序号暂不接收等待缺失数据重发ADC业务仍是100 Hz射频调度按需最高200 Hz用额外时隙处理ACK Payload、重发和积压恢复空闲时仍降到10 Hz和1 Hz不持续空发。需要强调200 Hz不是把100 Hz ADC数据重复发送两次。业务数据仍只产生和发送一次多出来的射频时隙用于反向回传、确认和拥塞恢复。九、最终结果双向3001包丢包率均为0%整改后的30秒正式测试方向发送包接收包丢包率CRC错误重复乱序发射端→接收端300130010%000接收端→发射端300130010%000测试条件每方向100 Hz 每包20 Byte 每方向2000 Byte/s 双向并发30秒这不意味着项目已经完成所有长期验证。下一步仍要运行5分钟、30分钟并加入距离、遮挡和2.4 GHz干扰场景。但至少系统已经从“偶尔能通”走到了“可量化、可重复、可回归测试”。十、这次协作最值得保留的五件事1. 日志必须可分层只打印“收到/没收到”远远不够。UART输入、无线入队、DMA完成、硬件重发、应用序号都要有独立统计。2. ACK Payload必须按流水线理解它不是同步RPC。响应滞后一轮配对、同步和运行态都必须幂等并允许重复。3. 短时通过不能代表持续吞吐达标5秒0丢包30秒可能暴露缓冲积压。压力测试必须覆盖稳态而不只是功能演示。4. 重发不是越多越好底层长时间重发会堵住后续业务。硬件负责短时干扰应用层负责最终可靠二者必须分工。5. 给AI权限的核心价值是反馈闭环真正提升效率的不是让AI“猜得更准”而是让它能够执行实验并读取结果。串口权限把以下步骤连成了一条链提出假设 - 修改代码 - 编译 - 烧录 - 发送测试数据 - 读取两端日志和原始字节 - 严格比较 - 更新结论当工具权限有明确边界、测试脚本可复现、结果可以量化时AI就不只是一个代码生成器而可以成为嵌入式联调过程中的工程协作者。结语这次调试从半双工协议、ACK时序一路走到编译器运行库、串口接线和持续吞吐。很多问题单独看都不复杂但它们叠加后很容易让人误判根因。最终让过程显著提速的是把现场信号变成AI可以直接验证的数据四个串口、一个调试器、一组可重复运行的脚本以及每次修改后诚实记录的PASS或FAIL。下一步我们会继续把5分钟和30分钟压力结果加入报告并为未来的1 Mbps 500 HzOTA高速模式保留独立的能力协商和安全回退机制。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进