Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ports/wch: Add support for WCH CH32V307. #8637

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions ports/wch/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Include the core environment definitions; this will set $(TOP).
include ../../py/mkenv.mk

# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h

# MicroPython feature configurations
MICROPY_ROM_TEXT_COMPRESSION ?= 1

# Include py core make definitions.
include $(TOP)/py/py.mk

# Path you your toolchain and openocd installation, leave empty if already in system PATH
TOOLCHAIN_ROOT = /opt/wch/mounriver-studio-toolchain-riscv/bin/
OPENOCD_ROOT = /opt/wch/mounriver-studio-toolchain-openocd/bin/

CROSS_COMPILE ?= $(TOOLCHAIN_ROOT)riscv-none-embed-

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider an early startup test that looks if ${TOOLCHAIN_ROOT} is a directory and ${CROSS_COMPILE}gcc is a file. Issue a helpful error message so the developer knows where to look in the doc and/or configuration files.

Sometimes hardcoded paths just can't be avoided, but it's worth calling out expectations so another user can meet them.


###############################################################################

# Project specific
BOARD ?= CH32V307EVT
TARGET = $(BOARD).elf

SRC_DIR = bsp/src/
INC_DIR = bsp/inc/

# Toolchain
CC = $(TOOLCHAIN_ROOT)riscv-none-embed-gcc
DB = $(TOOLCHAIN_ROOT)riscv-none-embed-gdb

# Project sources
SRC_C = \
main.c \
mphalport.c \
pin.c \
pin_defs_ch32.c \
pin_named_pins.c \
modmachine.c \
modutime.c \
extmod/utime_mphal.c \
shared/libc/string0.c \
shared/readline/readline.c \
shared/runtime/gchelper_generic.c \
shared/runtime/pyexec.c \
shared/runtime/stdout_helpers.c \

SRC_C += $(wildcard $(SRC_DIR)*.c)

SRC_S += bsp/startup_ch32v30x_D8C.S

SRC_C += $(SRC_MOD)
SRC_CXX += $(SRC_MOD_CXX)
SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX)
SRC_QSTR += pin.c pin_named_pins.c modmachine.c modutime.c

SRC_C += $(BUILD)/pins_$(BOARD).c
SRC_QSTR += $(BUILD)/pins_$(BOARD).c

# Project includes
INCLUDES = -I. -I$(INC_DIR) -I$(BUILD) -I$(TOP)

# Linker Script
LD_SCRIPT = bsp/ch32v30x.ld

# Compiler Flags
CFLAGS = -march=rv32imac -mabi=ilp32 -msmall-data-limit=8 -mno-save-restore -Os
CFLAGS += -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -Wunused -Wuninitialized -g
CFLAGS += -std=gnu99
CFLAGS += $(INCLUDES)

# Linker Flags
LDFLAGS = -T $(LD_SCRIPT) -nostartfiles -Xlinker --gc-sections --specs=nano.specs --specs=nosys.specs

OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.S=.o))

###############################################################################

MAKE_PINS = boards/make-pins.py
BOARD_PINS = boards/ch32v307_evt_pins.csv
AF_FILE = boards/ch32v30x_af.csv
PREFIX_FILE = boards/prefix.c

GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h
GEN_PINS_AF_PY = $(BUILD)/pins_af.py

# Generate Pin details before QSTR processing
$(SRC_QSTR): | $(GEN_PINS_HDR)

$(GEN_PINS_HDR): $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
$(ECHO) "[make-pin] - GEN $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) \
--prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --hdr-obj-decls \
--qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) \
--af-defs $(GEN_PINS_AF_DEFS) --af-defs-cmp-strings \
--af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC)

###############################################################################

all: $(BUILD)/$(TARGET)

$(BUILD)/$(TARGET): $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(CC) $(LDFLAGS) -o $@ $^
$(Q)$(SIZE) $@

prog: $(BUILD)/$(TARGET)
$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c halt -c "flash erase_sector wch_riscv 0 last " -c exit

#$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c halt -c "program $(BUILD)/$(TARGET) 0x08000000" -c exit # OpenOCD-wch 0.10 (MRS Toolchain v1.30)
$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c halt -c "program $(BUILD)/$(TARGET)" -c exit # OpenOCD-wch 0.11 (MRS Toolchain v1.40)

#$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c halt -c "verify_image $(BUILD)/$(TARGET)" -c exit

#$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c "reset" -c exit || exit 0 # OpenOCD-wch 0.10 (MRS Toolchain v1.30)
$(OPENOCD_ROOT)openocd -f $(OPENOCD_ROOT)wch-riscv.cfg -c init -c wlink_reset_resume -c exit || exit 0 # OpenOCD-wch 0.11 (MRS Toolchain v1.40)

#miniterm.py - 115200 --raw

include $(TOP)/py/mkrules.mk
111 changes: 111 additions & 0 deletions ports/wch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
MicroPython port for WCH-CH32V307
================================

This is an experimental port of MicroPython for the [CH32V307EVT](https://eji4evk5kxx.exactdn.com/wp-content/uploads/2022/01/CH32V307V-EVT-R1-720x499.jpg) board, which uses the [WCH CH32V307](https://github.com/openwch/ch32v307) RISC-V microcontroller.

Supported features include:
- [x] REPL (Python prompt) over UART0(WCH-Link/P9).
- [x] Builtin modules: gc, array, collections, io, struct, sys.
- [x] GPIO interface with `machine` `Pin` module
- [x] Sleep functions from `time` module

TODO:
- [ ] GPIO Alternate Functions / Interrupt Services
- [ ] Peripherals - `ADC` / `DAC` / `SPI` / `I2C` / `I2S` / `RTC` support.
- [ ] Stacks - `Ethernet` / `USBFS` / `USBHS`
- [ ] Filesystem - Flash Memory / SDCard.

## Build instructions

Install the toolchain bundle downloaded from the [Mounriver](http://www.mounriver.com/download) website. Edit Makefile to change path variables `TOOLCHAIN_ROOT` and `OPENOCD_ROOT` to the gcc toolchain and openocd bin directory. Rename directories to avoid spaces in path string.

The MicroPython cross-compiler must be built to pre-compile some of the built-in scripts to bytecode. This can be done using:
```bash
$ make -C mpy-cross
```

Then, to build MicroPython for CH32V307, just run:
```bash
$ cd ports/wch
$ make -j`nproc`
```

To flash MicroPython image to your CH32V307, connect USB cable to P9 port and use:
```bash
$ make prog
```

To access the MicroPython REPL running on CH32V307, use and select `WCH-Link`:
```bash
$ miniterm.py - 115200 --raw
```
## Examples

```python
MicroPython v1.18-131-g31ba059e9-dirty on 2022-05-05; ch32v307-evt with wch-ch32v307

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the highlighting of the 5's here somehow meaningful and intentional?

Type "help()" for more information.
>>>
>>> help('modules')
__main__ machine uarray ustruct
builtins micropython ucollections usys
gc time uio
Plus any modules on the filesystem
>>>
>>> import machine
>>> machine.info()
DEVID=0x0518
REVID=0x3070
S=72000000
H=72000000
P1=36000000
P2=72000000
qstr:
n_pool=1
n_qstr=5
n_str_data_bytes=20
n_total_bytes=196
GC:
3968 total
2544 : 1424
1=35 2=18 m=32
```

Connect jumper wires between pads - PA0 <--> LED1 and PE0 <--> KEY.

```python
MicroPython v1.18-131-g31ba059e9-dirty on 2022-05-05; ch32v307-evt with wch-ch32v307

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

Type "help()" for more information.
>>>
>>> from machine import Pin
>>> import time
>>>
>>> pa0=Pin(Pin.board.PA0, Pin.OUT)
>>>
>>> for i in range(5):
... pa0.off()
... time.sleep(1)
... pa0.on()
... time.sleep(1)
... print("Iter: " + str(i))
... # Press Enter and watch LED blink 5 times
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
>>>
>>> pe0=Pin(Pin.board.PE0, Pin.IN)
>>> pe0.value() # USER button not pressed
1
>>> pe0.value() # USER button pressed
0
>>> pe0.value() # USER button not pressed
1
>>> while True: # Pressing USER button lights up LED1
... pa0.value(pe0.value())
... # Press Enter (Infinite Loop)
# Press RESET button to Restart REPL
MicroPython v1.18-131-g31ba059e9-dirty on 2022-05-05; ch32v307-evt with wch-ch32v307
Type "help()" for more information.
>>>
```
92 changes: 92 additions & 0 deletions ports/wch/boards/ch32v307_evt_pins.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
PE2,PE2
PE3,PE3
PE4,PE4
PE5,PE5
PE6,PE6
PC13,PC13
PC14,PC14
PC15,PC15
PD0,PD0
PD1,PD1
PC0,PC0
PC1,PC1
PC2,PC2
PC3,PC3
PA0,PA0
PA1,PA1
PA2,PA2
PA3,PA3
PA4,PA4
PA5,PA5
PA6,PA6
PA7,PA7
PC4,PC4
PC5,PC5
PB0,PB0
PB1,PB1
PB2,PB2
PE7,PE7
PE8,PE8
PE9,PE9
PE10,PE10
PE11,PE11
PE12,PE12
PE13,PE13
PE14,PE14
PE15,PE15
PB10,PB10
PB11,PB11
PB12,PB12
PB13,PB13
PB14,PB14
PB15,PB15
PD8,PD8
PD9,PD9
PD10,PD10
PD11,PD11
PD12,PD12
PD13,PD13
PD14,PD14
PD15,PD15
PC6,PC6
PC7,PC7
PC8,PC8
PC9,PC9
PA8,PA8
PA9,PA9
PA10,PA10
PA11,PA11
PA12,PA12
PA13,PA13
PA14,PA14
PA15,PA15
PC10,PC10
PC11,PC11
PC12,PC12
PD0,PD0
PD1,PD1
PD2,PD2
PD3,PD3
PD4,PD4
PD5,PD5
PD6,PD6
PD7,PD7
PB3,PB3
PB4,PB4
PB5,PB5
PB6,PB6
PB7,PB7
PB8,PB8
PB9,PB9
PE0,PE0
PE1,PE1
USBHS_DP,PB7
USBHS_DM,PB6
USBFS_DP,PA12
USBFS_DM,PA11
ETH_TXP,PC8
ETH_TXN,PC9
ETH_RXP,PC6
ETH_RXN,PC7
SWDIO,PA13
SWCLK,PA14
Loading