Skip to content

CH32X035 port#3703

Open
rhgndf wants to merge 4 commits into
hathach:masterfrom
rhgndf:ch32x035
Open

CH32X035 port#3703
rhgndf wants to merge 4 commits into
hathach:masterfrom
rhgndf:ch32x035

Conversation

@rhgndf

@rhgndf rhgndf commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Adds support for both CH32X035 and CH32X033.

I'm also evaluating this MCU due to it being low cost and have USB.

CH32X035 has both TX and RX CTRL bits in the same byte, so there are changes to how these registers are written in the dcd.
If the current approach isn't satisfactory, there are some alternatives:

  • Make EP_TX_CTRL_WRITE a function instead of a #define
  • 'Inline' the #define: EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~MASK) | BITS

EP4 special handling:
This is a bit confusing, and Codex/Claude has been very helpful to get that part working. In short: no DMA and no auto-toggle, so some special handling has to be built in.

EP3 no special large buffer
The code has some existing handling for large EP3 buffer, but as far as I can tell that functionality doesn't exist in ch32x035, should I #if that out for this port?

Related: adafruit/Adafruit_TinyUSB_Arduino#486

@HiFiPhile

Copy link
Copy Markdown
Collaborator

CH32X035 has both TX and RX CTRL bits in the same byte, so there are changes to how these registers are written in the dcd.

Seems like v103, do you have board to test with ?

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

Top 10 targets by memory change (%) (out of 2404 targets) View Project Dashboard →

target .text .rodata .data .bss total % diff
ch32v103c_bluepill/dynamic_configuration 4,104 → 3,976 (-128) 14,392 → 14,264 (-128) -0.9%
ch32v103c_bluepill/dfu_runtime 8,556 → 8,588 (+32) 2,880 → 2,752 (-128) 13,900 → 13,804 (-96) -0.7%
ch32v103c_bluepill/hid_generic_inout 9,528 → 9,560 (+32) 3,084 → 2,956 (-128) 15,080 → 14,984 (-96) -0.6%
ch32v103c_bluepill/hid_boot_interface 10,388 → 10,416 (+28) 2,960 → 2,832 (-128) 15,812 → 15,712 (-100) -0.6%
ch32v103c_bluepill/hid_composite 10,612 → 10,640 (+28) 2,948 → 2,820 (-128) 16,028 → 15,928 (-100) -0.6%
ch32v103c_bluepill/hid_multiple_interface 10,368 → 10,400 (+32) 2,960 → 2,832 (-128) 15,792 → 15,696 (-96) -0.6%
ch32v103c_bluepill/midi_test 10,720 → 10,752 (+32) 3,208 → 3,080 (-128) 16,392 → 16,296 (-96) -0.6%
ch32v103c_bluepill/cdc_dual_ports 11,736 → 11,764 (+28) 3,552 → 3,424 (-128) 17,752 → 17,652 (-100) -0.6%
ch32v103c_bluepill/printer_to_cdc 11,908 → 11,936 (+28) 3,496 → 3,368 (-128) 17,852 → 17,752 (-100) -0.6%
ch32v103c_bluepill/webusb_serial 12,248 → 12,276 (+28) 3,508 → 3,380 (-128) 18,320 → 18,220 (-100) -0.5%

@rhgndf

rhgndf commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

Seems like v103, do you have board to test with ?

I don't have the board unfortunately. I may take a look if I need a 5V capable mcu though (although py32f07x is also 5V capable but has additional DACs unlike v103)

@rhgndf

rhgndf commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

MemBrowse Memory Report

Got claude to analyze the discrepency, here's the output verbatim:

  Why update_in got smaller

  The refactor folded the endpoint-buffer selection. Old code was a three-way branch:

  if (ep == 0)      memcpy(data.buffer[ep][TUSB_DIR_OUT], ...);  // buffer[ep][0]
  else if (ep == 3) memcpy(data.ep3_buffer.in, ...);
  else              memcpy(data.buffer[ep][TUSB_DIR_IN], ...);   // buffer[ep][1]

  New code is two-way, with the ep0 case absorbed into the inlined helper:

  if (ep == 3) memcpy(data.ep3_buffer.in, ...);
  else         memcpy(ep_buffer(ep, TUSB_DIR_IN), ...);   // buffer[ep][ep==0 ? 0 : 1]

  So the dedicated ep == 0 test-and-branch disappears; the address is now computed in a straight line as data.buffer[ep][ep==0 ? 0 : 1]. The disassembly confirms it: master has an extra li a5,3 / bne / beqz a4 cluster plus a second address computation
  that the branch version doesn't, and with RVC 2-byte instructions the savings land on exactly 8 bytes.

hathach added a commit to alt-0191/tinyusb that referenced this pull request Jun 19, 2026
dcd_edpt_xfer() re-enabled the USB interrupt before update_in() / ep_rx_set_response(),
which read-modify-write the (combined) EP control register. On CH58x the ISR RMWs that
same register to flip the manual data toggle, so a transfer interrupt landing mid-RMW
could drop the toggle flip and desync the endpoint. Move dcd_int_enable() to after the
arming so the whole sequence is atomic w.r.t. the ISR (matching the CH32X035 port hathach#3703).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hathach

hathach commented Jun 23, 2026

Copy link
Copy Markdown
Owner

thank you, after #3515, this should be relatively easy. I have the CH32X035 board but run out of wlinke debugger (attached to hil rig). will get this mcu ported when it got on my desk

@rhgndf

rhgndf commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

I also simplified the comments, since I found a hallucination involving X035.
Other changes:

  • refactored the ep buffer code for 58x and x035
  • removed ep3 in the non ep4 shared buffer case, saves 128 bytes of memory

@rhgndf

rhgndf commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

According to the manuals, it says only EP4 needs manual toggling, maybe manual toggle should only be enabled for EP4?

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Hardware-in-the-loop (HIL) Test Report

hfp.json

✅ 52 passed · ❌ 0 failed · ⚪ 0 skipped · blank not run

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp
stm32l412nucleo ✅ CDC 627k/394k MSC 825k/762k
stm32f746disco ✅ CDC 13.6M/9.4M MSC 15.4M/28.5M
stm32f746disco-DMA ✅ CDC 13.2M/9.1M MSC 18M/26.9M
lpcxpresso43s67 ✅ CDC 12.5M/12.3M MSC 32.5M/35M

tinyusb.json

✅ 337 passed · ❌ 2 failed · ⚪ 11 skipped · blank not run

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp host_info_to_device_cdc cdc_msc_hid msc_file_explorer msc_file_explorer_freertos device_info hid_composite_freertos
ek_tm4c123gxl ✅ CDC 653k/980k MSC 694k/932k
espressif_p4_function_ev rd 409KB/s
espressif_p4_function_ev-DMA rd 409KB/s
espressif_s3_devkitm rd 409KB/s
espressif_s3_devkitm-DMA
feather_nrf52840_express ✅ CDC 440k/360k MSC 558k/555k
max32666fthr ✅ CDC 7M/14.3M MSC 16.3M/18.2M
metro_m4_express ✅ CDC 577k/442k MSC 597k/421k
mimxrt1015_evk ✅ CDC 14M/7M MSC 24.8M/19.2M
mimxrt1064_evk ✅ CDC 19.7M/15.1M MSC 28.9M/21.4M rd 1365KB/s rd 1358KB/s
lpcxpresso11u37 ✅ CDC 415k/327k MSC 646k/569k
ra4m1_ek ✅ CDC 596k/453k MSC 598k/416k
raspberry_pi_pico ✅ CDC 552k/498k MSC 799k/981k rd 62KB/s rd 62KB/s
raspberry_pi_pico_w rd 1108KB/s rd 1022KB/s
raspberry_pi_pico2 rd 1110KB/s rd 1022KB/s
adafruit_fruit_jam ✅ CDC 638k/541k MSC 781k/971k rd 62KB/s rd 62KB/s
stm32f072disco ✅ CDC 445k/351k MSC 697k/501k
stm32f407disco ✅ CDC 930k/554k MSC 928k/995k
stm32f723disco ✅ CDC 490k/360k MSC 640k/603k rd 18078KB/s rd 4096KB/s
stm32f723disco-DMA ✅ CDC 508k/512k MSC 514k/511k rd 20164KB/s rd 4096KB/s
stm32h743nucleo ✅ CDC 1M/986k MSC 974k/1.1M
stm32h743nucleo-DMA ✅ CDC 426k/949k MSC 853k/1M
stm32g0b1nucleo ✅ CDC 595k/527k MSC 719k/550k
stm32l476disco ✅ CDC 779k/504k MSC 887k/1M
stm32u083nucleo ✅ CDC 672k/504k MSC 551k/564k
nanoch32v203-fsdev ✅ CDC 689k/803k MSC 957k/949k
nanoch32v203-usbfs ✅ CDC 676k/554k MSC 1.1M/1M
ch32v103r_r1_1v0
ch582m_evt ✅ CDC 231k/218k MSC 491k/507k

@HiFiPhile

Copy link
Copy Markdown
Collaborator

Hi, I see many comment changes, please verify are they intended.

@rhgndf

rhgndf commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Yes they are intended, since there was a hallucination about the x035 and I was concerned there are more, so I got my agent to shrink all of them so they can be verified easily

@HiFiPhile

Copy link
Copy Markdown
Collaborator

Many comments are from Ha Thach like

// CH58X EP registers split into a low block (EP0-4) and a high block (EP5-7). Walk from each
// block's first slot by the 4-byte slot stride (pointer arithmetic off slot 0, so the unused

They shoudn't be removed.

@rhgndf rhgndf force-pushed the ch32x035 branch 5 times, most recently from 7f1322b to d2b4873 Compare July 4, 2026 09:22
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

Size Difference Report

Because TinyUSB code size varies by port and configuration, the metrics below represent the averaged totals across all example builds.

Note: If there is no change, only one value is shown.

Changes >1% in size

file .text .bss size % diff
dcd_ch32_usbfs.c 1659 ➙ 1688 (+29) 2444 ➙ 2316 (-128) 4103 ➙ 4004 (-99) -2.4%
TOTAL 1659 ➙ 1688 (+29) 2444 ➙ 2316 (-128) 4103 ➙ 4004 (-99) -2.4%
Changes <1% in size

No entries.

No changes
file .text .rodata .data .bss size % diff
audio_device.c 2890 0 1259 1623 4508 +0.0%
cdc_device.c 1236 16 1092 728 1963 +0.0%
cdc_host.c 6399 487 15 971 7594 +0.0%
dcd_ch32_usbhs.c 1892 0 0 481 2373 +0.0%
dcd_ci_fs.c 1924 0 0 1290 3214 +0.0%
dcd_ci_hs.c 1756 0 0 1344 2534 +0.0%
dcd_da146xx.c 3067 0 0 144 3211 +0.0%
dcd_dwc2.c 4223 19 0 265 4506 +0.0%
dcd_eptri.c 2273 0 0 259 2532 +0.0%
dcd_ft9xx.c 3284 0 0 172 3456 +0.0%
dcd_khci.c 1952 0 0 1290 3242 +0.0%
dcd_lpc17_40.c 1481 0 0 648 1805 +0.0%
dcd_lpc_ip3511.c 1463 0 0 264 1683 +0.0%
dcd_mm32f327x_otg.c 1477 0 0 1290 2767 +0.0%
dcd_msp430x5xx.c 1801 0 0 176 1977 +0.0%
dcd_musb.c 2595 0 0 179 2773 +0.0%
dcd_nrf5x.c 2939 0 0 292 3231 +0.0%
dcd_nuc120.c 1096 0 0 78 1174 +0.0%
dcd_nuc121.c 1170 0 0 101 1270 +0.0%
dcd_nuc505.c 0 0 1533 157 1690 +0.0%
dcd_rp2040.c 840 0 764 653 2257 +0.0%
dcd_rusb2.c 2918 0 0 156 3074 +0.0%
dcd_samd.c 1036 0 0 266 1302 +0.0%
dcd_samg.c 1322 0 0 72 1394 +0.0%
dcd_stm32_fsdev.c 2543 0 0 291 2834 +0.0%
dfu_device.c 776 28 712 136 912 +0.0%
dfu_rt_device.c 157 0 134 0 157 +0.0%
dwc2_common.c 603 22 0 0 615 +0.0%
ecm_rndis_device.c 1059 0 1 2759 3818 +0.0%
ehci.c 2763 0 0 6274 7783 +0.0%
fsdev_common.c 180 0 0 0 180 +0.0%
hcd_ch32_usbfs.c 2491 0 0 502 2993 +0.0%
hcd_ci_hs.c 181 0 0 0 181 +0.0%
hcd_dwc2.c 5071 25 1 545 5642 +0.0%
hcd_khci.c 2443 0 0 454 2897 +0.0%
hcd_musb.c 3071 0 0 157 3228 +0.0%
hcd_pio_usb.c 262 0 240 0 502 +0.0%
hcd_rp2040.c 1996 17 4 321 2338 +0.0%
hcd_rusb2.c 2923 0 0 245 3168 +0.0%
hcd_samd.c 2220 0 0 324 2544 +0.0%
hcd_stm32_fsdev.c 3248 0 1 420 3670 +0.0%
hid_device.c 1124 44 997 119 1242 +0.0%
hid_host.c 1246 0 0 1270 2516 +0.0%
hub.c 1384 8 8 30 1419 +0.0%
midi2_device.c 2628 52 1175 561 3211 +0.0%
midi2_host.c 1802 0 0 5921 7723 +0.0%
midi_device.c 1149 0 1007 619 1765 +0.0%
midi_host.c 1339 7 7 3538 4880 +0.0%
msc_device.c 2527 108 2293 804 3331 +0.0%
msc_host.c 1633 0 0 395 2028 +0.0%
mtp_device.c 1713 22 743 589 2309 +0.0%
ncm_device.c 1761 28 819 4393 6167 +0.0%
ohci.c 1925 0 0 2503 4428 +0.0%
printer_device.c 828 0 706 560 1387 +0.0%
rp2040_usb.c 386 35 619 11 1051 +0.0%
rusb2_common.c 160 0 16 0 176 +0.0%
tusb.c 455 0 387 3 457 +0.0%
tusb_fifo.c 855 0 486 0 850 +0.0%
typec_stm32.c 1230 8 2 19 1255 +0.0%
usbc.c 500 2 20 166 688 +0.0%
usbd.c 3530 57 90 355 3948 +0.0%
usbh.c 4967 57 82 1165 6238 +0.0%
usbtmc_device.c 2194 24 68 313 2539 +0.0%
vendor_device.c 639 0 534 559 1197 +0.0%
video_device.c 4433 5 1235 480 4905 +0.0%
TOTAL 123429 1071 17050 49700 174702 +0.0%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants