Short: WCH CH340/CH341 USB serial for Poseidon Author: Serkan Uploader: Serkan Type: driver/other Version: 1.0 Requires: Poseidon 6.x (AROS backport), 68040 or Emu68 Architecture: m68k-amigaos >= 3.1 Distribution: Aminet serialch340.class ================= A Poseidon USB class for serial adapters built around the WCH CH340 and CH341 chips - the cheap "USB-SERIAL CH340" cables and the USB port of many Arduino, ESP8266 and ESP32 boards. It gives AmigaOS a serial.device compatible device, serialch340.device, so terminal programs and anything else that talks to a serial.device can use these adapters. Requirements ------------ - Poseidon 6.x, the AROS-lineage backport of Poseidon for AmigaOS 3.x (https://github.com/rondoval/poseidon-backport). The class uses the Poseidon 6.x class interface; it does not work with the classic Poseidon 4.x/5.x releases. - AmigaOS 3.1 or later. - The binary is built for the 68040 (as are the backport's own 68040 builds). It was developed and tested on an A1200 with PiStorm/Emu68, AmigaOS 3.2.3, xhci.device and poseidon.library 6.1/6.2. To build for another CPU, see "Building" below. Supported adapters ------------------ 1A86:7523 WCH CH340 (the common "USB-SERIAL CH340") 1A86:7522 WCH CH340K 1A86:5523 WCH CH341 in serial mode 4348:5523 WCH CH341 (old vendor ID) 2184:0057 GW Instek GDM-834x multimeter 9986:7523 CH340 clone Other CH34x adapters can be bound by hand in Trident (Devices, select the adapter, force binding to serialch340.class). Installation ------------ Double-click the Install icon in the Poseidon_ch340 drawer (it runs the Install script through IconX), or from a Shell: CD Poseidon_ch340 Execute Install The script - copies the class to SYS:Classes/USB/ (an existing one is kept as serialch340.class.old), - asks whether to copy the tools chtest, chxfer and psdlog to C:, - if the class is not yet known to Poseidon: asks you to unplug all CH340/CH341 adapters, then registers the class (C/chclass ADD) and saves the Poseidon prefs (C/chclass SAVE; the old prefs are kept as ENVARC:Sys/poseidon.prefs.bak), - if the class is already registered: tells you to reboot to load the new version. Unplug the adapters before registering: Poseidon suspends USB devices that stay without a driver, and the class cannot take over an adapter that is already suspended (see "Known problems"). By hand: with the adapters unplugged, copy Classes/USB/serialch340.class to SYS:Classes/USB/, add it in Trident (Classes, Add) and press Save. Then plug in the adapter. Trident's message log shows serialch340.class Another serial killer 'USB2.0-Serial' at serialch340.device unit 0! serialch340.class CH34x chip version 31. The first adapter is unit 0, the second unit 1, and so on - also when two adapters have the same USB IDs. In a terminal program select the device "serialch340.device" and the unit number. Install the class in SYS:Classes/USB, so that it is there when an adapter is plugged in. See "Known problems" for what happens when it is loaded later by hand. Features -------- - Baud rates from 50 to 2,000,000; any rate in between, computed with the same divisor algorithm as the Linux ch341 driver. - 5, 6, 7 or 8 data bits; parity none, odd, even, mark or space; 1 or 2 stop bits. - DTR and RTS are switched on while the unit is open and off when the adapter is set up. - SDCMD_QUERY reports CTS, DSR, DCD and RI (read from the chip) and RTS, DTR, and the number of bytes waiting in the read buffer. - SDCMD_BREAK sends a break of io_BrkTime microseconds. - CMD_READ, CMD_WRITE (io_Length -1 = NUL terminated), CMD_CLEAR, CMD_RESET, CMD_FLUSH, CMD_START, CMD_STOP, SDCMD_SETPARAMS, NSCMD_DEVICEQUERY; SERF_EOFMODE with the termination array (taken over from the cp210x class, not tested with the CH340). - Read-ahead buffering: data arriving while no read is pending is kept. - Several adapters at the same time, one unit each. - Unplugging the adapter while a unit is open does not crash anything: pending reads end with error -2 (IOERR_ABORTED). When the adapter is plugged in again, the same open unit continues to work. Tested ------ All tests on an A1200 with PiStorm/Emu68 (68040), AmigaOS 3.2.3, Poseidon 6.2 backport, with CH340 adapters (chip version 0x31). Binding at boot and hot plug ............................ OK Open/close, many times .................................. OK SETPARAMS 9600, 115200, 921600, 2000000 baud ............ OK Line status (QUERY), DTR/RTS on, BREAK .................. OK Loopback (TX wired to RX) at 9600/115200/921600 ......... OK, byte exact Reading an ESP32 that prints text at 9600 ............... OK Two adapters at once (units 0 and 1) .................... OK Unplug and replug while the unit is open and reading .... OK (see below) Framing, with two adapters wired crosswise (TX to RX, both ways, GND): Same settings on both ends, text arrives intact: 8N1, 7E1, 7O1, 8E1, 8O2, 8M1, 8S1, 7N2 ............... all OK Proof that the settings reach the chip: unit 0 sends "ABC" with 7 data bits, unit 1 receives as 8N1, so the parity bit appears as bit 7: sender expected received 7M1 C1 C2 C3 C1 C2 C3 7S1 41 42 43 41 42 43 7E1 41 42 C3 41 42 C3 7O1 C1 C2 43 C1 C2 43 Throughput: 1 MB of a pattern from one adapter to the other, every byte checked, 8N1, measured with chxfer: baud result bytes/s line limit 115200 no loss 11533 11520 460800 no loss 45988 46080 921600 no loss (both directions) 83500 92160 1000000 no loss 90068 100000 1500000 no loss 122112 150000 2000000 ~180 bytes lost per MB 151000 200000 Up to 1.5 Mbaud nothing was lost. At 2 Mbaud the receive side tops out at about 150 KB/s and, as the CH340 has no flow control, the chip drops what it cannot deliver. Use 1.5 Mbaud or less for bulk transfers. Known problems and limits ------------------------- - Loading the class later onto a suspended adapter hangs. Poseidon 6.2 suspends USB devices that stay without a driver for a while. If serialch340.class is added by hand (e.g. from RAM:) after an adapter has been plugged in long enough to be suspended, the class binds, but its task hangs while the adapter is resumed, and only a reboot clears it. Both the implicit resume (by the first transfer) and an explicit psdResumeDevice() were tried; the cause lies on the resume path and was not found. With the class in SYS:Classes/USB this does not happen: the class binds when the adapter is enumerated, before Poseidon would suspend it. - No flush of old data on open. The read-ahead keeps receiving while the unit is closed, and after a baud rate change the buffer still holds data received with the old settings. A program gets that data first. Read and discard what SDCMD_QUERY reports as waiting right after opening or after SETPARAMS if you do not want it. (Flushing in the driver was tried twice and stopped reception or hung on xhci.device, so it was left out.) - Settings after replugging. When the adapter is unplugged and plugged in again while a unit is open, the unit continues, but the chip starts again at 9600 8N1 with DTR and RTS off. A program that notices a read error -2 should send SDCMD_SETPARAMS again. - No hardware flow control. The CH340 has none; with SERF_7WIRE the driver only keeps DTR and RTS on. XON/XOFF is not handled by the driver either. - DTR/RTS and development boards. Opening the unit switches DTR and RTS on. Boards with an auto-reset circuit (ESP32, ESP8266, many Arduinos) may reset when a unit is opened. - A unit can be opened by one program at a time (SERF_SHARED is not supported). - Removing the class at run time (e.g. with a tool that calls psdRemClass) and adding it again in the same session once led to a reboot when the adapter was replugged afterwards. Use the normal install and reboot to change versions. Tools ----- C/chtest - test a unit: chtest [UNIT n] [BAUD n] [TEXT "..."] [SECS n] [BREAK] [LOOP] [DATABITS 5-8] [PARITY N|E|O|M|S] [STOP 1|2] [HEX] [NOWRITE] [DEVICE name] Opens the unit, prints the line status, writes TEXT and prints what arrives for SECS seconds. With TX wired to RX this is a loopback test. LOOP keeps reading after errors (for unplug tests), HEX prints the received bytes in hex, NOWRITE only listens. chtest UNIT 0 BAUD 9600 SECS 5 NOWRITE C/chxfer - bulk transfer test between two units wired TX to RX: chxfer [FROM n] [TO n] [BAUD n] [SIZE n] [CHUNK n] [DEVICE name] Sends SIZE bytes of a known pattern, checks every byte and prints the throughput and PASS or FAIL. After a lost byte all following bytes count as wrong; compare "sent" and "received" for the real loss. chxfer FROM 0 TO 1 BAUD 921600 SIZE 1048576 C/chclass - used by the Install script: chclass ADD add a class to the running Poseidon chclass LIST list the loaded classes chclass SAVE save the Poseidon prefs (ENVARC: and ENV:) There is no REMove on purpose; see "Known problems". C/psdlog - Poseidon's message log without opening Trident: psdlog [n] the last n messages (default 20) psdlog DEV the USB devices, with their suspend state Source/tests/ has the AmigaDOS scripts used for the framing tests (match, mismatch). Building -------- The source is in Source/. The class is built inside the Poseidon backport tree, which provides the class skeleton, the headers and the toolchain container (ghcr.io/rondoval/amiga-build-container). build.sh clones the backport (revision 0dc2b73), adds the class and builds it with docker: ./build.sh class and tools ./build.sh class class only The class is built for 68040 with -DM68K_CPU=68040; change M68K_CPU in build.sh for 68020 or 68060. History ------- 1.0 (19.10.2026) First release. Credits and license ------------------- serialch340.class is derived from serialcp210x.class by Chris Hodges, part of Poseidon, as found in the AROS backport by rondoval. The CH340 protocol follows the Linux ch341 USB serial driver. Changes for the CH340, the resume fix, the OpenDevice and stale unit fixes, the tools and the tests: Serkan, 2026. Distributed under the AROS Public License 1.1, see LICENSE. The source code is included.