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

View File

@@ -0,0 +1,2 @@
(kicad_symbol_lib
)

View File

@@ -0,0 +1,272 @@
(kicad_pcb
(version 20240108)
(generator "pcbnew")
(generator_version "8.0")
(general
(thickness 1.6)
(legacy_teardrops no)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(stackup
(layer "F.SilkS"
(type "Top Silk Screen")
)
(layer "F.Paste"
(type "Top Solder Paste")
)
(layer "F.Mask"
(type "Top Solder Mask")
(thickness 0.01)
)
(layer "F.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 1"
(type "core")
(thickness 1.51)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "B.Cu"
(type "copper")
(thickness 0.035)
)
(layer "B.Mask"
(type "Bottom Solder Mask")
(thickness 0.01)
)
(layer "B.Paste"
(type "Bottom Solder Paste")
)
(layer "B.SilkS"
(type "Bottom Silk Screen")
)
(copper_finish "None")
(dielectric_constraints no)
)
(pad_to_mask_clearance 0)
(allow_soldermask_bridges_in_footprints no)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(plot_on_all_layers_selection 0x0000000_00000000)
(disableapertmacros no)
(usegerberextensions no)
(usegerberattributes yes)
(usegerberadvancedattributes yes)
(creategerberjobfile yes)
(dashed_line_dash_ratio 12.000000)
(dashed_line_gap_ratio 3.000000)
(svgprecision 4)
(plotframeref no)
(viasonmask no)
(mode 1)
(useauxorigin no)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(pdf_front_fp_property_popups yes)
(pdf_back_fp_property_popups yes)
(dxfpolygonmode yes)
(dxfimperialunits yes)
(dxfusepcbnewfont yes)
(psnegative no)
(psa4output no)
(plotreference yes)
(plotvalue yes)
(plotfptext yes)
(plotinvisibletext no)
(sketchpadsonfab no)
(subtractmaskfromsilk no)
(outputformat 1)
(mirror no)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(net 0 "")
(gr_circle
(center 133.352 82.11)
(end 135.052 82.11)
(stroke
(width 0.1)
(type solid)
)
(fill none)
(layer "Edge.Cuts")
(uuid "019c0a6d-9bb8-42f8-8584-8f200b71a27b")
)
(gr_circle
(center 165.352 114.11)
(end 167.052 114.11)
(stroke
(width 0.1)
(type solid)
)
(fill none)
(layer "Edge.Cuts")
(uuid "097c55d3-ce7a-4886-a7db-9a4e9fcd0127")
)
(gr_circle
(center 165.352 82.11)
(end 167.052 82.11)
(stroke
(width 0.1)
(type solid)
)
(fill none)
(layer "Edge.Cuts")
(uuid "0e8e5788-23b0-4e0e-993f-a94957498ae3")
)
(gr_arc
(start 169.352 114.11)
(mid 168.180427 116.938427)
(end 165.352 118.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "178364bc-250e-4a39-b0ba-4262bbac4b46")
)
(gr_arc
(start 133.352 118.11)
(mid 130.523573 116.938427)
(end 129.352 114.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "3d8baf97-c836-4397-867c-23e52ff05ce1")
)
(gr_line
(start 169.352 114.11)
(end 169.352 82.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "871dfad9-a85d-42ce-9d2d-6520fae7f4c4")
)
(gr_line
(start 129.352 82.11)
(end 129.352 114.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "8baef1cd-8e58-474a-b843-199aa0080763")
)
(gr_arc
(start 165.352 78.11)
(mid 168.180427 79.281573)
(end 169.352 82.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "a7e36be5-cc10-4aad-836f-bde309666136")
)
(gr_line
(start 165.352 78.11)
(end 133.352 78.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "b80e33ff-046b-4986-bc0d-6bc4865afc31")
)
(gr_arc
(start 129.352 82.11)
(mid 130.523573 79.281573)
(end 133.352 78.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "cf226ff4-3173-434d-8c9b-3129470c1ce4")
)
(gr_circle
(center 133.352 114.11)
(end 135.052 114.11)
(stroke
(width 0.1)
(type solid)
)
(fill none)
(layer "Edge.Cuts")
(uuid "d6648504-8f45-4127-8704-34acfec9c9a4")
)
(gr_line
(start 133.352 118.11)
(end 165.352 118.11)
(stroke
(width 0.1)
(type solid)
)
(layer "Edge.Cuts")
(uuid "e1f36007-0f9d-4dc5-ae43-6b056652526f")
)
(gr_text "{{"{{GITHASH}}"}}"
(at 140.240427 116.111573 0)
(layer "F.SilkS")
(uuid "d894e23f-c5ed-4336-947e-ac38e533f04c")
(effects
(font
(size 2 2)
(thickness 0.1)
)
(justify left bottom)
)
)
(group ""
(uuid "deecda4f-8c94-4c72-8782-3da851560eb8")
(members "019c0a6d-9bb8-42f8-8584-8f200b71a27b" "097c55d3-ce7a-4886-a7db-9a4e9fcd0127"
"0e8e5788-23b0-4e0e-993f-a94957498ae3" "178364bc-250e-4a39-b0ba-4262bbac4b46"
"3d8baf97-c836-4397-867c-23e52ff05ce1" "871dfad9-a85d-42ce-9d2d-6520fae7f4c4"
"8baef1cd-8e58-474a-b843-199aa0080763" "a7e36be5-cc10-4aad-836f-bde309666136"
"b80e33ff-046b-4986-bc0d-6bc4865afc31" "cf226ff4-3173-434d-8c9b-3129470c1ce4"
"d6648504-8f45-4127-8704-34acfec9c9a4" "e1f36007-0f9d-4dc5-ae43-6b056652526f"
)
)
)

View File

@@ -0,0 +1,231 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.09999999999999999,
"min_via_diameter": 0.5,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 5,
"td_on_pad_in_zone": false,
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "template123.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "../../../build/default.net",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"legacy_lib_dir": "",
"legacy_lib_list": []
},
"sheets": [],
"text_variables": {}
}

View File

@@ -0,0 +1,5 @@
(kicad_sch (version 20230121) (generator eeschema)
(paper "A4")
(lib_symbols)
(symbol_instances)
)

View File

@@ -0,0 +1,4 @@
(fp_lib_table
(version 7)
(lib (name "lib")(type "KiCad")(uri "${KIPRJMOD}/../../../build/footprints/footprints.pretty")(options "")(descr ""))
)

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