Initial project scaffold for CH9350-STM32 USB HID to UART bridge

This commit is contained in:
Xiaofeng Guo
2026-06-05 15:03:01 -07:00
parent d8d5bc83e5
commit 46879bfd8b
9 changed files with 895 additions and 0 deletions

325
elec/src/ch9350-stm32.ato Normal file
View File

@@ -0,0 +1,325 @@
import Power from "generics/interfaces.ato"
import UART from "generics/interfaces.ato"
import USB2 from "generics/interfaces.ato"
import SWD from "generics/interfaces.ato"
import Pair from "generics/interfaces.ato"
import Capacitor from "generics/capacitors.ato"
import Resistor from "generics/resistors.ato"
import Oscillator from "generics/oscillators.ato"
# ============================================================
# CH9350 - USB HID to UART Bridge
# ============================================================
component CH9350_IC:
mpn = "CH9350L"
footprint = "Package_QFP:LQFP-48_7x7mm_P0.5mm"
package = "LQFP-48"
# Power
signal vcc ~ pin 1
signal gnd ~ pin 2
gnd ~ pin 13
gnd ~ pin 20
signal v33 ~ pin 3
# USB
signal udm ~ pin 9
signal udp ~ pin 10
# Crystal (12MHz)
signal xi ~ pin 11
signal xo ~ pin 12
# UART
signal txd ~ pin 18
signal rxd ~ pin 19
# Control
signal rst_n ~ pin 4
signal act ~ pin 5
# Mode/Config
signal mode0 ~ pin 16
signal mode1 ~ pin 17
signal cfg0 ~ pin 22
signal cfg1 ~ pin 23
signal cfg2 ~ pin 24
module CH9350:
ic = new CH9350_IC
# Power Interface
power = new Power
power.vcc ~ ic.vcc
power.gnd ~ ic.gnd
# USB Interface
usb = new USB2
usb.dp ~ ic.udp
usb.dm ~ ic.udm
usb.gnd ~ power.gnd
# UART Interface
uart = new UART
uart.tx ~ ic.txd
uart.rx ~ ic.rxd
uart.gnd ~ power.gnd
# V33 LDO decoupling
c_v33 = new Capacitor
c_v33.value = 1uF +/- 20%
c_v33.package = "0402"
ic.v33 ~ c_v33.p1; c_v33.p2 ~ power.gnd
# 12 MHz crystal oscillator
osc = new Oscillator
osc.crystal.footprint = "Crystal-SMD_L5.0-W3.2"
osc.crystal.mpn = "12MHz-Crystal-SMD-3225"
osc.load_cap_1.value = 22pF +/- 20%
osc.load_cap_2.value = 22pF +/- 20%
ic.xi ~ osc.xin.io
ic.xo ~ osc.xout.io
osc.gnd ~ power.gnd
# Power decoupling
c_dec_1 = new Capacitor
c_dec_1.value = 100nF +/- 20%
c_dec_1.package = "0402"
ic.vcc ~ c_dec_1.p1; c_dec_1.p2 ~ power.gnd
c_dec_2 = new Capacitor
c_dec_2.value = 10uF +/- 20%
c_dec_2.package = "0603"
ic.vcc ~ c_dec_2.p1; c_dec_2.p2 ~ power.gnd
# RESET pull-up (active low)
r_rst = new Resistor
r_rst.value = 10kohm +/- 20%
r_rst.package = "0402"
ic.rst_n ~ r_rst.p1; r_rst.p2 ~ power.vcc
# ACT LED indicator
r_act = new Resistor
r_act.value = 1kohm +/- 20%
r_act.package = "0402"
signal act_led
# Mode/Config default: UART mode, auto-detect
r_mode0 = new Resistor
r_mode0.value = 10kohm +/- 20%
r_mode0.package = "0402"
ic.mode0 ~ r_mode0.p1; r_mode0.p2 ~ power.gnd
r_mode1 = new Resistor
r_mode1.value = 10kohm +/- 20%
r_mode1.package = "0402"
ic.mode1 ~ r_mode1.p1; r_mode1.p2 ~ power.gnd
r_cfg0 = new Resistor
r_cfg0.value = 10kohm +/- 20%
r_cfg0.package = "0402"
ic.cfg0 ~ r_cfg0.p1; r_cfg0.p2 ~ power.gnd
r_cfg1 = new Resistor
r_cfg1.value = 10kohm +/- 20%
r_cfg1.package = "0402"
ic.cfg1 ~ r_cfg1.p1; r_cfg1.p2 ~ power.gnd
r_cfg2 = new Resistor
r_cfg2.value = 10kohm +/- 20%
r_cfg2.package = "0402"
ic.cfg2 ~ r_cfg2.p1; r_cfg2.p2 ~ power.gnd
# ============================================================
# STM32F103C8T6 - ARM Cortex-M3 Microcontroller
# ============================================================
component STM32F103C8T6:
mpn = "STM32F103C8T6"
footprint = "Package_QFP:LQFP-48_7x7mm_P0.5mm"
package = "LQFP-48"
# Power
signal vbat ~ pin 1
signal vdd_1 ~ pin 9
signal vss_1 ~ pin 8
signal vdd_2 ~ pin 24
signal vss_2 ~ pin 23
signal vdd_3 ~ pin 36
signal vss_3 ~ pin 35
signal vdd_4 ~ pin 48
signal vss_4 ~ pin 47
# HSE Crystal (8 MHz)
signal osc_in ~ pin 5
signal osc_out ~ pin 6
# LSE Crystal (32.768 kHz)
signal osc32_in ~ pin 3
signal osc32_out ~ pin 4
# Reset and Boot
signal nrst ~ pin 7
signal boot0 ~ pin 44
# SWD Debug
signal swdio ~ pin 34
signal swclk ~ pin 37
# USART1 (connected to CH9350)
signal pa9_tx ~ pin 30
signal pa10_rx ~ pin 31
# User LED (PC13)
signal pc13 ~ pin 2
module STM32F103_Minimal:
mcu = new STM32F103C8T6
# Power Interface
power = new Power
power.gnd ~ mcu.vss_1
power.gnd ~ mcu.vss_2
power.gnd ~ mcu.vss_3
power.gnd ~ mcu.vss_4
# VDD Decoupling - one 100nF per VDD pin
c_d1 = new Capacitor
c_d1.value = 100nF +/- 20%
c_d1.package = "0402"
mcu.vdd_1 ~ c_d1.p1; c_d1.p2 ~ power.gnd
c_d2 = new Capacitor
c_d2.value = 100nF +/- 20%
c_d2.package = "0402"
mcu.vdd_2 ~ c_d2.p1; c_d2.p2 ~ power.gnd
c_d3 = new Capacitor
c_d3.value = 100nF +/- 20%
c_d3.package = "0402"
mcu.vdd_3 ~ c_d3.p1; c_d3.p2 ~ power.gnd
c_d4 = new Capacitor
c_d4.value = 100nF +/- 20%
c_d4.package = "0402"
mcu.vdd_4 ~ c_d4.p1; c_d4.p2 ~ power.gnd
# Bulk decoupling
c_bulk = new Capacitor
c_bulk.value = 10uF +/- 20%
c_bulk.package = "0603"
mcu.vdd_1 ~ c_bulk.p1; c_bulk.p2 ~ power.gnd
# VDDA filtering
c_vdda = new Capacitor
c_vdda.value = 100nF +/- 20%
c_vdda.package = "0402"
mcu.vdd_1 ~ c_vdda.p1; c_vdda.p2 ~ power.gnd
# 0R jumper for VDDA
r_vdda = new Resistor
r_vdda.value = 0ohm
r_vdda.package = "0402"
mcu.vdd_1 ~ r_vdda.p1; power.vcc ~ r_vdda.p2
# VBAT
c_vbat = new Capacitor
c_vbat.value = 100nF +/- 20%
c_vbat.package = "0402"
mcu.vbat ~ c_vbat.p1; c_vbat.p2 ~ power.gnd
mcu.vbat ~ power.vcc
# HSE: 8 MHz external oscillator
hse = new Oscillator
hse.crystal.footprint = "Crystal-SMD_L5.0-W3.2"
hse.crystal.mpn = "8MHz-Crystal-SMD-3225"
hse.load_cap_1.value = 22pF +/- 20%
hse.load_cap_2.value = 22pF +/- 20%
mcu.osc_in ~ hse.xin.io
mcu.osc_out ~ hse.xout.io
hse.gnd ~ power.gnd
# LSE: 32.768 kHz oscillator for RTC
lse = new Oscillator
lse.crystal.footprint = "Crystal-SMD_L3.2-W1.5"
lse.crystal.mpn = "32.768kHz-Crystal-SMD-3215"
lse.load_cap_1.value = 12pF +/- 20%
lse.load_cap_2.value = 12pF +/- 20%
mcu.osc32_in ~ lse.xin.io
mcu.osc32_out ~ lse.xout.io
lse.gnd ~ power.gnd
# NRST: pull-up to VCC
r_nrst = new Resistor
r_nrst.value = 10kohm +/- 20%
r_nrst.package = "0402"
mcu.nrst ~ r_nrst.p1; r_nrst.p2 ~ power.vcc
# NRST decoupling
c_nrst = new Capacitor
c_nrst.value = 100nF +/- 20%
c_nrst.package = "0402"
mcu.nrst ~ c_nrst.p1; c_nrst.p2 ~ power.gnd
# BOOT0: pull-down to GND (boot from flash)
r_boot0 = new Resistor
r_boot0.value = 10kohm +/- 20%
r_boot0.package = "0402"
mcu.boot0 ~ r_boot0.p1; r_boot0.p2 ~ power.gnd
# SWD interface
swd = new SWD
swd.swdio ~ mcu.swdio
swd.swclk ~ mcu.swclk
swd.swo ~ power.gnd
swd.gnd ~ power.gnd
# UART interface to CH9350
uart = new UART
uart.tx ~ mcu.pa9_tx
uart.rx ~ mcu.pa10_rx
uart.gnd ~ power.gnd
# User LED on PC13 (active low, open-drain)
r_led = new Resistor
r_led.value = 510ohm +/- 20%
r_led.package = "0402"
signal user_led_anode
# ============================================================
# Top-level Application
# ============================================================
module App:
ch9350 = new CH9350
stm32 = new STM32F103_Minimal
# Shared power rail
power = new Power
power.vcc ~ ch9350.power.vcc
power.vcc ~ stm32.power.vcc
power.gnd ~ ch9350.power.gnd
power.gnd ~ stm32.power.gnd
# CH9350 UART -> STM32 USART1 (cross-connected)
ch9350.uart.tx ~ stm32.uart.rx
ch9350.uart.rx ~ stm32.uart.tx
ch9350.uart.gnd ~ stm32.uart.gnd
# CH9350 USB goes to PC
usb = new USB2
usb.dp ~ ch9350.usb.dp
usb.dm ~ ch9350.usb.dm
usb.gnd ~ power.gnd
# Top-level SWD interface for programming/debug
swd = new SWD
swd.swdio ~ stm32.swd.swdio
swd.swclk ~ stm32.swd.swclk
swd.gnd ~ power.gnd