A recent discussion on the WCH community forums raised an important question about Flash clock frequency configuration on the CH32V317 MCU. This is a critical configuration that affects both performance and reliability.
A developer noticed uncertainty about the correct Flash clock frequency setting for the CH32V317. Setting the Flash wait state incorrectly can lead to:
#### 1. Check Your System Clock
First, verify your system clock frequency:uint32_t sysclk = SystemCoreClock;
#### 2. Set Flash Wait States Based on FrequencyFor CH32V317 (and similar V4F core MCUs):
| System Clock | Flash Wait States | LATENCY |
|---|---|---|
| <= 48MHz | 0 | 0 |
| 48-96MHz | 1 | 1 |
| 96-144MHz | 2 | 2 |
Configure in code:
FLASH->ACTLR = FLASH_ACTLR_LATENCY_2;#### 3. Enable Flash Prefetch Buffer
For optimal performance, enable the prefetch buffer:FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
CH32V003 是南京沁恒的 RV32EC 入门级 MCU,主频 48MHz,片上 2KB SRAM + 16KB Flash(部分型号),价格约 $0.1,非常适合 RISC-V 入门和成本敏感场景。
#include "ch32v00x.h"
int main(void) { GPIO_InitTypeDef gpio = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); gpio.GPIO_Pin = GPIO_Pin_0; gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &gpio); while (1) { GPIO_WriteBit(GPIOC, GPIO_Pin_0, Bit_SET); for (volatile int i = 0; i < 80000; i++); GPIO_WriteBit(GPIOC, GPIO_Pin_0, Bit_RESET); for (volatile int i = 0; i < 80000; i++); } }GPIO、USART、I2C、SPI、TIM(PWM)、ADC(10-bit)、看门狗,基本覆盖教学 / 简单控制需求。
如果要做 BLE,请升级到 CH32V208;如果需要以太网,请考虑 CH32V307。 如有更多问题,欢迎在论坛继续讨论或联系 contact@open-riscv.comBuilding on the existing CH32V317 Flash / clock thread. There is a very practical follow-up question on the WCH BBS right now about how to actually get the CH32V317's built-in 100M Ethernet + PHY to deliver useful throughput. The WCH field engineer response (and a community follow-up) gives a clean answer that I want to surface here since this is the most common WCH-networking question in the last month:
Q (WCH BBS thread 159876): "How much real-world TCP throughput can the CH32V317's 100M Ethernet deliver? It feels similar to the CH32V307's 10M performance." A (WCH field engineering): Throughput is software-stack-bound, not MAC-bound. With a tuned WCHNET configuration the CH32V317 can sustain ~60 Mbps TCP TX (TCP client, 1460-byte packets, single direction) and 15 Mbps TCP RX with back-pressure enabled. Pure MAC loopback / UDP without stack overhead will line-rate the 100M PHY. Practical config changes (innet_config.h) to get the higher numbers:
#define TCP_SEND_BUFSIZE_COUNT 16 // up from default 4
#define TCP_RECV_BUFSIZE_COUNT 16 // up from default 4
#define WCHNET_NUM_TCP_SOCKETS 8 // up from default 4
#define WCHNET_NUM_UDP_SOCKETS 4
#define WCHNET_TCP_MSS 1460
#define WCHNET_NUM_RX_BUF 32 // descriptor ring
#define WCHNET_NUM_TX_BUF 16
#define WCHNET_TIMER_TICK_MS 5
#define WCHNET_RX_QUEUE_SIZE 32
These consume more RAM but are required to keep the pipeline full at 60+ Mbps. RAM cost on a CH32V317 (with 64 KB zero-wait flash + 160 KB non-zero-wait flash and 20 KB SRAM) is about 8-12 KB extra.
Note on TCP RX: the WCH engineer noted that the RX path is the slow side; on the first configuration pass TCP RX stays around 5-7 Mbps unless you explicitly enable back-pressure (setWCHNET_RX_FLOW_CTRL 1). With flow control on, TCP RX climbs to 15+ Mbps on the same hardware.
Tying back to the original thread topic (clock config): the MAC needs HCLK at 96 MHz or 144 MHz to actually feed the descriptor ring at line rate. Running the system clock at 72 MHz (the default after reset) will cap the MAC throughput regardless of buffer tuning. Use the MRS clock-config wizard to lock HCLK = 96 MHz minimum for any real network use case.
Caveats:
- WCHNET is the in-house protocol stack; LwIP porting to the CH32V317 is also viable and typically gets 5-15% better RX throughput with the same buffers, at the cost of more code work.
- CH32V317 vs CH32V307 ethernet: V317 has the same MAC + 100M PHY as V307 but runs at a higher HCLK ceiling and has a wider bus, which is why V317 is the right part for USB-to-Ethernet dongles.
- If you are using CH32V317 in USB-to-Ethernet mode (USB HS 480 Mbps + 100M Ethernet), the USB CDC-ECM driver overhead will cap you at ~80-90 Mbps before you even hit the MAC ceiling.
Source: WCH BBS thread 159876 (CH32V317 100M Ethernet throughput Q&A + community follow-up), https://www.wch.cn/bbs/thread-159876-1.htmlBased on the WCH community discussion, there has been some ambiguity between the datasheet and application notes. Here is a summary of the key points:
Current Understanding: The CH32V317 and CH32V307 share the same PHY IP (10M/100M Ethernet). The original documentation and community references indicate this is a current-drive type PHY, meaning the transformer PHY side center tap must connect to 3.3V. However, newer official documentation appears to label it as voltage-drive type, which has caused confusion. This discrepancy may stem from:For Ethernet-capable RISC-V MCU projects, the CH32V307 ($3, gigabit MAC + 100M PHY) and CH32V317 ($4, 100M PHY + 480Mbps USB) remain strong choices for connected embedded systems.
We also stock K1-based gateway solutions that can pair with these MCUs for edge computing + networking applications. Source: WCH Forum - CH32V317 Internal PHY Driver TypeReported symptoms
The user observed two issues while using the WCHNET stack on CH32V317:Official response
WCH support confirmed that multiple UDP sockets work in their own tests and suggested the user send the project code for review if the issue persists.For the TCP state display, the support team clarified that the value in SocketInf is the socket state, not the full TCP state machine. Their test showed a printed value of 0x05, which represents the socket state in the WCHNET abstraction layer. Developers should not map that value directly to TCP_FIN_WAIT_1 semantics.
Practical takeawayWhen porting existing TCP/UDP code to CH32V317, treat SocketInf state values as WCHNET-specific socket-layer states rather than literal TCP states. If you need fine-grained TCP state tracking, add your own state machine on top of the socket API.
Source: 关于CH32V317的网络,可能是BUG,麻烦关注一下 on WCH CommunityPractical takeaway for CH32V307 / CH32V317 users: WCHNET remains the best-supported path with full example parity. If you standardize on lwIP across a multi-family fleet, budget real time for the ethernetif glue and the sys_arch port, and start MAC/PHY init from the EVT example rather than from scratch.
We published a longer write-up on the blog: "CH32H417 Ethernet: lwIP Support Status and a Realistic Porting Path". Source: https://www.wch.cn/bbs/thread-161401-1.html