Until now you typed 1 or 2 in the CLion serial terminal and read the board's reply there.
In this extension a C program running in Linux (WSL) does the same job: it sends 1 or 2
to the board over the UART and prints what the board answers (Hello or Welcome).
WSL (Linux) Windows Board
┌──────────────┐ usbipd-win ┌──────────────┐ USB cable ┌──────────────────────────┐
│ uart_app │◄────────────►│ CH340 USB │◄───────────►│ CH340 ──► PA9/PA10 │
│ /dev/ttyUSB0 │ (USB/IP) │ device │ │ USART1 of the STM32F103 │
└──────────────┘ └──────────────┘ └──────────────────────────┘
The firmware does not change. Keep flashing it from CLion with Panda Run (HEX) as before.
- The Lab 1 firmware flashed and working (it answers
1→Hello,2→Welcomein the CLion terminal). - The baud rate set in
Usart1_Init()in your firmware. This guide assumes 115200. If yours is different, pass it on the command line in Part 5. - The board's Serial UART DIP switch ON (both ways), and the CH340 USB cable plugged in.
- WSL installed (Ubuntu).
WSL2 is a small virtual machine. Windows owns every USB device and does not hand them
to the Linux VM automatically, so inside WSL there is no /dev/ttyUSB0 yet.
The tool usbipd-win fixes this: it takes the CH340 away from Windows and lends it to WSL
over a virtual network link (the USB/IP protocol). While the CH340 is lent to WSL, Windows
(and CLion's serial monitor, PuTTY, etc.) can't use it, and vice versa.
- Open PowerShell as Administrator (Start → type PowerShell → right-click → Run as administrator).
- Run:
Click through the installer, then close and reopen the admin PowerShell.
winget install --interactive --exact dorssel.usbipd-win
- Make sure WSL itself is up to date (newer WSL kernels already include the CH340 driver):
wsl --update
- Close anything on Windows that has the COM port open (CLion Serial Port Monitor, PuTTY).
- Open a WSL terminal and leave it open (usbipd needs WSL to be running).
- In the admin PowerShell, list the USB devices:
Find the line that says USB-SERIAL CH340 and note its BUSID, e.g.
usbipd list
2-3:The ST-Link (BUSID VID:PID DEVICE STATE 2-3 1a86:7523 USB-SERIAL CH340 (COM5) Not shared0483:3748) is a different device: leave it alone so CLion can still flash. - Share the device (only needed the first time for this USB port):
usbipd bind --busid 2-3
- Attach it to WSL:
usbipd attach --wsl --busid 2-3
usbipd listnow shows the state Attached.
Unplugging the cable or restarting the PC detaches it. Repeat step 5 after that (step 4 is remembered).
In the WSL terminal:
- Install the compiler and CMake:
sudo apt update sudo apt install -y build-essential cmake usbutils
- Check that Linux sees the board:
If
lsusb # should list: 1a86:7523 QinHeng Electronics CH340 serial converter ls /dev/ttyUSB* # should print: /dev/ttyUSB0
lsusbshows the CH340 but there is no/dev/ttyUSB0, runwsl --updatein PowerShell, thenwsl --shutdown, and attach again (Part 3, step 5). - Give your user permission to use serial ports. Linux only lets members of the
dialout group open
/dev/ttyUSB0:Then in PowerShell runsudo usermod -aG dialout $USERwsl --shutdown, reopen WSL, and attach the board again. Check withgroups: the list should containdialout.
- Copy the project into your Linux home folder. Windows drives appear in WSL under
/mnt/, soD:\...is/mnt/d/.... For example, if you unzipped it toD:\nouran\linux-uart-app:(Building insidecp -r /mnt/d/nouran/linux-uart-app ~/ cd ~/linux-uart-app
/mnt/dalso works, just more slowly.) - Build with CMake:
This produces the program
cmake -S . -B build cmake --build buildbuild/uart_app. - Run it (device and baud are optional; these are the defaults):
./build/uart_app /dev/ttyUSB0 115200
- Expected session:
Watch the board's RX/TX LEDs blink on every exchange.
Opened /dev/ttyUSB0 at 115200 baud (8N1) Enter 1 or 2 (q to quit): 1 Sent : 1 Received: Hello Enter 1 or 2 (q to quit): 2 Sent : 2 Received: Welcome Enter 1 or 2 (q to quit): q Bye
When you want to use CLion's serial monitor again, in admin PowerShell:
usbipd detach --busid 2-3Flashing with the ST-Link is not affected either way: it is a separate USB device.
| File | What it does |
|---|---|
src/serial_port.c |
Opens /dev/ttyUSB0 and configures it with termios (the Linux serial-port API). Reads one reply line with a timeout. |
src/main.c |
The user loop: read 1/2 from the keyboard, send it, print the reply. |
include/serial_port.h |
Declarations of the two serial functions. |
CMakeLists.txt |
Builds uart_app with the normal Linux gcc (not the ARM compiler). |
Key ideas:
- In Linux a serial port is a file.
open("/dev/ttyUSB0")gives a file descriptor;write()sends bytes to the board,read()receives bytes from it. - termios settings must match the MCU.
serial_open()sets the same frame asUsart1_Init(): baud rate (cfsetispeed/cfsetospeed), 8 data bits (CS8), no parity (~PARENB), 1 stop bit (~CSTOPB), no hardware flow control (~CRTSCTS). A different baud on either side gives garbage or nothing. - Raw mode.
cfmakeraw()turns off the terminal "helpers" (echo, line editing, turning\ninto\r\n), so the program sees exactly the bytes the board sent. - One byte per command. The firmware reacts to a single character, so the app
sends only
'1'or'2', without the Enter key (\n). - Waiting with a timeout.
serial_read_line()usespoll()to wait up to 1 s for each byte and stops at\n(the firmware ends replies with\r\n). If the board is off or the baud is wrong, you get a clear "No reply" message instead of a frozen program.
| Symptom | Cause and fix |
|---|---|
/dev/ttyUSB0: No such file or directory |
Not attached to WSL. Do Part 3 step 5; check ls /dev/ttyUSB*. |
/dev/ttyUSB0: Permission denied |
Not in dialout (Part 4 step 3), or run once with sudo to confirm. |
usbipd: error: ... WSL ... not running |
Open a WSL terminal first, then attach. |
usbipd attach fails, device busy |
Close CLion's serial monitor / PuTTY on Windows first. |
No reply within 1000 ms |
Baud mismatch with Usart1_Init(), Serial UART DIP switch OFF, or firmware not running (press reset). |
| Received text is garbage | Baud mismatch, or the MCU clock is not what the firmware assumes. |
| COM port vanished from Windows | It is attached to WSL. usbipd detach --busid 2-3. |
- Add a command-line mode:
./build/uart_app /dev/ttyUSB0 115200 1sends one command and exits. - Add a third command in the firmware (e.g.
3toggles the LED) and handle it in the app. - Log every exchange with a timestamp to a file.