Repository navigation
fix(device): 修复 macOS/Linux 下打开串口导致 ESP32 复位、握手失败 - #67
Merged
Merged
Conversation
On macOS (and other non-Windows platforms) the OS raises DTR and RTS when the port is opened. SerialPort then drops them DTR-first, which briefly leaves RTS high with DTR low; through the auto-download circuit on many ESP32 boards this pulls EN low and resets the chip on every connect, so the hello sent right after opening was lost and the handshake always timed out (EasyConNS#56). On non-Windows platforms, open the port with DTR/RTS asserted and then drop RTS before DTR. The final line state is unchanged (both low), but the reset-triggering intermediate state is avoided. Windows behaviour is left untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
变更说明
在 macOS 和 Linux 上,EasyCon 打开串口时会让带自动下载电路的 ESP32 开发板复位,导致握手每次都失败(#56)。
原因
SerialPort默认DtrEnable = false、RtsEnable = false,打开后会先撤销 DTR、再撤销 RTS。中间会短暂出现“RTS 拉高、DTR 未拉高”的状态,通过 ESP32 常见的自动下载电路把 EN 拉低,芯片就复位了。TTLSerialClient打开串口后马上发 hello(A5 A5 81),这一次正好落在芯片重启期间被丢弃,握手超时。改成先撤销 RTS、再撤销 DTR后,中间状态变成“DTR 拉高、RTS 未拉高”,只影响 GPIO0,EN 不受影响,所以不会复位。两种顺序最后都是两根线撤销,状态相同。
修改
只改了
src/EasyCon.Device/Connection/TTLSerialClient.cs,只在非 Windows 平台生效:SerialPort时,设置DtrEnable = true、RtsEnable = true,让打开串口时两根线保持拉高。Open()之后,先设置RtsEnable = false,再设置DtrEnable = false。Windows 走原来的逻辑,没有任何变化。握手流程和成功条件也完全不变,仍然以收到
0x80为准。为什么 Windows 不用这个方案:实测在 Windows 上这样做时,插上后首次打开仍然会复位,而且之后 hello 一直没有回复。我推测芯片在 GPIO0 被拉低时复位,进入了下载模式,但还没有用启动日志确认。
关联 Issue
Fixes #56
变更类型
人工审核声明
自查清单
dotnet build通过dotnet test EasyCon2.slnx -c Release通过dotnet format --verify-no-changes无差异验证方式
测试硬件:ESP32-S3 + CP210x,115200。
EasyCon GUI 实测
cu和tty都测过80,没有启动日志,断开重连也一样 ✅80✅修复前 macOS 和 Linux 上的日志(每次连接都是这样):
修复后:
撤销顺序的对比测试
用 .NET
SerialPort写了一个测试程序,每次打开串口后先监听 2 秒、不发数据,再发一次 hello:default:.NET 默认设置,也就是修复前的做法。ordered:本 PR 的做法。defaultordered80✅80✅测试代码(.NET 10 单文件程序:
dotnet run wintest.cs -- <串口> default|ordered)原始输出
macOS(
/dev/cu.usbserial-2110)Linux(树莓派 5,
/dev/ttyUSB0)Windows(
COM6,每种模式运行前都拔插了 USB)已知问题(不在本 PR 范围内)
Windows 上,插上 USB 后首次连接同样会因为复位而失败,重连后才能成功。这是原来就有的问题,原理相近,但不能用本 PR 的方式解决。