You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ee7563c
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,10 @@ Releases up through `v0.4.0` were workspace-wide and tagged `vX.Y.Z`. From `0.4.
4
4
5
5
## [Unreleased]
6
6
7
+
### Fixed
8
+
9
+
-`tinyboot-ch32`: half-duplex is now safe on a shared (multi-drop) wire. `usart::init` sets HDSEL before TE — the reverse order latched the half-duplex TX output LOW until the first own transmission, clamping the bus from init (measured on CH32V006). The single-wire pin now parks AF open-drain (the bus pull-up owns idle) and flips to push-pull only around writes, so an idle node never drives against other talkers.
The MCU muxes RX onto the TX pin — one wire to the host, no external buffer. Useful when both ends speak half duplex directly (some probes, some DXL servo chains where the MCU is the sole driver on its segment).
28
+
The MCU muxes RX onto the TX pin — one wire to the host, no external buffer. Useful when both ends speak half duplex directly: probes, DXL-style servo chains, any shared single-wire bus.
29
29
30
30
```rust
31
31
Usart::new(&UsartConfig {
@@ -35,6 +35,10 @@ Usart::new(&UsartConfig {
35
35
});
36
36
```
37
37
38
+
**Hardware requirement: the wire needs an external pull-up.** In `Duplex::Half` the driver parks the pin **open-drain** while idle or listening and flips it to push-pull only around its own writes, so between frames nothing holds the line at mark except the pull-up. Without one the wire floats and the receiver sees noise and framing errors — garbage bytes the protocol has to sync past. 4.7–10 kΩ to the bus voltage is typical; go stiffer for high baud rates or long, capacitive buses.
39
+
40
+
This discipline is what makes the single wire **shareable**: an idle node never drives the line, so several half-duplex devices (and the host) can sit on one bus without contention. The driver also raises HDSEL before enabling the transmitter — the reverse order latches the TX output low until the first own transmission, which would clamp the whole bus from init to the first reply.
This is the OpenServoCore hardware style: the MCU runs regular full-duplex UART to a hardware transceiver (MAX485, 74LVC2G241, etc.), and `tx_en` drives the transceiver's direction pin so its output stage only drives the bus while the MCU is transmitting.
@@ -67,6 +71,8 @@ Usart::new(&UsartConfig {
67
71
});
68
72
```
69
73
74
+
The open-drain idle park applies in this setup too — it's the `Duplex::Half` discipline, independent of `tx_en` — so the stub between the pin and the buffer input needs a pull-up (or a transceiver with internal biasing) to keep the buffer's input at mark while the MCU listens.
75
+
70
76
## What `tx_en` actually does
71
77
72
78
When configured, the driver toggles the direction pin around every frame:
Copy file name to clipboardExpand all lines: docs/troubleshooting.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,7 @@ Something in the UART chain isn't right. Work through these in order:
28
28
-**`rx_pull`** — floating RX lines need `Pull::Up`; externally pulled-up lines should use `Pull::None`.
29
29
-**RS-485 / DXL TTL** — a DE/RE pin must be configured via `TxEnConfig`, with `tx_level` matching the transceiver's DE polarity.
30
30
-**Half-duplex contention** — on some boards the programmer's TX driver and the MCU's TX driver both reach MCU_RX. Flipping `tx_level` (so the MCU's side is tri-stated while idle) often resolves it. See the [transports guide](transports.md).
31
+
-**Half-duplex missing pull-up** — `Duplex::Half` parks the pin open-drain while idle, so the wire needs an external pull-up to hold mark between frames. A floating wire reads as noise and framing errors. See the [transports guide](transports.md).
0 commit comments