This is tiny firmware for stm32f10x MCU that partially mimics behaviour of USB-to-many converter ch341. It supposed to be run on so-called bluepill widely available board that has stm32f10x on it. This project tries to achieve best possible simplicity of configuring, building and flashing firmware, hence it has:
- no external library dependencies, only basic and simpliest are used and included to source tree in somewhat stripped form;
- only most widely available cross-platform tools are needed for building and/or flashing.
There are several ones:
-
To have 3.3V SPI programmer for NOR flash EEPROM chips compatible with flashrom tool via USB interface. Although it can be achieved with original ch341 chip, most popular board has flawed schematics with 5V on MOSI/MISO/SCK lines hence it can damage memory chip and other 3.3V equipment (parts of motherboard, for example).
-
To have 5V-tolerant 3.3V USB-to-UART converter compatible with ch341.ko driver from mainline linux kernel.
-
The core code does almost nothing, simply resending bytes from USB to SPI or UART periphery and vice versa; still, it has some useful generic subsystems such as 32-bit system timer, multilevel logger with simple console and basic USB device routines, and rather flexible generalized structure, so it can be good template project, i.e. used as starting point for bigger one or for education.
Look into config.h file for configurable properties.
Used libraries (all included in source tree in libs/ directory):
- cmsis, including startup and
SystemInit()routines for stm32f10x medium density MCUs; - stdperiph Standard Peripherals Library for stm32f10x family;
- usbfs USB Full Speed Device library for STM MCUs.
Build dependencies:
- arm-none-eabi-gcc (tested with 5.4.1);
- arm-none-eabi-binutils (tested with 2.28);
- make (tested with GNU Make 4.1).
Simply run within the root directory:
$ make
It will create three files:
stm32f10x.elf- ELF-formatted image; suitable for flashing with openocd utility, for example;stm32f10x.bin- raw binary image for loading to device's flash memory, usually starting from0x08000000address; suitable for uploading with openocd or stm32flash utilities;stm32f10x.hex- binary image in intel HEX format for loading to device's flash memory; suitable for uploading with stm32flash utility.
You can use any feasible way for uploading firmware images to MCU.
However there are some helper targets in Makefile. They use simple
bash scripts.
For OpenOCD utility (tested with version 0.9.0):
make program_jlink_swd: program with SEGGER jlink compatible programmer in SWD mode (most suitable for bluepill board);make program_jlink_jtag: program with SEGGER jlink compatible programmer in JTAG mode;make program_stlink: program with stlink v2 programmer;make program: same asmake program_jlink_swd.
For STM32Flash utility (tested with version 0.6):
make upload_stm32flash: program with serial interface; you need to switch BOOT0 to1(the one that is not nearRESETbutton on bluepill board), connect 3.3V or 5V UART to pins A9 (TX) and A10 (RX); by default/dev/ttyUSB0used as UART device, it can be changed e.g.make STM32FLASH_DEV=/dev/ttyS1 upload_stm32flash.
Also there are helper targets for downloading firmware image from MCU
and uploading it back. Again, either openocd and J-Link/ST-Link
programmer or stm32flash and UART is needed:
make download_jlink_swd,make download_jlink_jtag,make download_stlink,make download_stm32flash;make upload_jlink_swd,make upload_jlink_jtag,make upload_stlink,make upload_stm32flash.
Pinout can be changed using hw_config.h file.
By default it is as follows:
| PIN | Subsystem | Function |
|---|---|---|
| C13 | LED | Signals about current mode by blink speed |
| A11 | USB | Data Minus |
| A12 | USB | Data Plus |
| B12 | CH341.SPI | Chip Select (NSS) |
| B13 | CH341.SPI | Clock (SCK) |
| B14 | CH341.SPI | Master Input Slave Output (MISO) |
| B15 | CH341.SPI | Master Output Slave Input (MOSI) |
| A9 | CH341.UART | Transmitter (TX, this is output of MCU) |
| A10 | CH341.UART | Receiver (RX, this is input of MCU) |
| B10 | CONSOLE(*) | Transmitter of misc messages (TX, this is output of MCU) |
| B11 | CONSOLE(*) | Receiver of commads (RX, this is input of MCU) |
(*) You can connect any UART (3.3V or 5V TTL) to CONSOLE interface and
see what is going on and even execute some simple commands. Default
console baudrate is 460800, it can be changed in config.h file.
Example of usage:
$ picocom /dev/ttyUSB0 -b 460800
Then type help to see list of available commands.
You can even connect one bluepill board flashed with this firmware
to another one (A10:A9:GND -> B10:B11:GND) to access console of
the latter, or use latter to program former (with A10:A9 pins
and BOOT0 switched to 1) with stm32flash utility.
SPI mode tested with flashrom version 1.2, by successfully
reading and writing contents of Windbond w25x64 and Macronix
mx25l3205 (replacing BIOS with libreboot on
Thinkpad X200). This was done with the following steps:
-
Connect J-Link OB ARM Emulator jlink_swd USB programmer to PC and to bluepill (
DIO,DCLK,3.3,GND). -
Run
make programwithin the root of the project. -
Connect bluepill to pomona clip following SOIC-8 or SOIC-16 pinout (described e.g. here libreboot-flash,
CS->B12,SCK->B13,MOSI->B15,MISO->B14,3.3,GND). -
Connect bluepill to PC with microUSB cable.
-
Run
flashrom -p ch341a_spi -r bios_backup.bin. -
With
spispeed:turbomode, 8mb flash read/written in 38 seconds.
UART mode tested with ch341.ko driver from linux kernel 5.10, by
connecting UART lines (RX and TX) of programmed bluepill to
ft232rl or pl2303 USB-to-UART converter, then
starting two [picocom] sessions on baudrates up to 460800
and checking connectivity.
-
I2C and Parallel interfaces are not implemented.
-
Neither setting nor getting of modem lines status (CTS, RTS, DTR, DSR, RI, DCD) is implemented.
-
UART baudrates above 460800 could experience problems with prescaler/divisor setup leading to wrong real baudrates.
-
Modem lines CTS, RTS, DTR, DSR, RI, DCD:
- allocate GPIO pins;
- change status by request (
modem_ctrl()); - poll and report state changes.
-
Use DMA instead of interrupts for logging/console subsystem.
-
Test building and using with MS Windows.
-
Implement I2C interface.
-
Implement Parallel interface.