Skip to content

Commit 5849de6

Browse files
committed
prepare to support more targets
1 parent 4a8f540 commit 5849de6

10 files changed

+117
-30
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
PROGRAM = stm32-vserprog
1010
CROSS ?= arm-none-eabi
1111
SERIAL ?= /dev/ttyUSB0
12-
BOARD ?= stm32-vserprog-v2
12+
BOARD ?= stm32-vserprog-v3
1313
OBJS = vserprog.o \
1414
usbcdc.o \
1515
spi.o \

README.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# stm32-vserprog:
2-
## flashrom serprog programmer based on STM32F103 MCU & USB CDC protocol.
2+
## flashrom serprog programmer based on STM32 MCU & USB CDC protocol.
33
**This project deprecates previous [serprog-stm32vcp](https://github.com/dword1511/serprog-stm32vcp) project, which uses STMicro's proprietary firmware library. Most functions are the same.**
44

55
* * *
@@ -9,11 +9,11 @@
99
* A STM32F103C8T6 MCU, a 8MHz crystal, a 3.3V 1117 LDO, some 0805 capacitors, resistors and LEDs along with dedicated [PCB available on OSH Park](https://oshpark.com/shared_projects/08Rj6sSm)
1010
* Or some general-purpose STM32F103 development boards, just with minor modifications in the source code to assign correct GPIO for USB D+ pullup and LEDs.
1111
* Hardware USB2.0 FullSpeed and efficient virtual COM port with USB CDC protocol eliminates the need of USB-to-UART bridges and the headache that comes with them, operates at any baud rates.
12-
* *Ironically, you will still have to buy or borrow a USB-to-UART bridge (not RS-232 but TTL level) to program the programmer itself.*
13-
* Hardware full-duplex SPI with DMA, multiple clock speeds available:
14-
* 36MHz *(Default)*
12+
* *Ironically, you will still have to buy or borrow a USB-to-UART bridge (not RS-232 but TTL level) to program the programmer itself,* unless you are using a STM32F042 device (support is in progress).
13+
* Hardware full-duplex SPI with DMA, multiple clock speeds available (default at the one closest to but under 10MHz), e.g. on STM32F103 targets:
14+
* 36MHz
1515
* 18MHz
16-
* 9MHz
16+
* 9MHz *(Default)*
1717
* 4.5MHz
1818
* 2.25MHz
1919
* 1.125MHz
@@ -45,11 +45,11 @@
4545

4646
1. Clone and compile.
4747

48-
Simply type:
48+
Simply type (change the board name accordingly, for details see the header of the Makefile):
4949

5050
```bash
5151
git clone https://github.com/dword1511/stm32-vserprog.git
52-
make
52+
make BOARD=stm32-vserprog-v2
5353
```
5454
1. Program.
5555

@@ -58,7 +58,7 @@
5858
Then type:
5959

6060
```bash
61-
make flash
61+
make BOARD=stm32-vserprog-v2 flash
6262
```
6363
1. Done!
6464

boards/stm32-tiny042-v1.h

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef __BOARD_H__
2+
#define __BOARD_H__
3+
4+
#include <stdbool.h>
5+
#include <libopencm3/stm32/rcc.h>
6+
#include <libopencm3/stm32/gpio.h>
7+
8+
#define BOARD_USE_DEBUG_PINS_AS_GPIO false
9+
10+
#define BOARD_RCC_LED RCC_GPIOA
11+
#define BOARD_PORT_LED GPIOA
12+
#define BOARD_PIN_LED GPIO14
13+
#define BOARD_LED_HIGH_IS_BUSY false /* Only LED, high active, use as idle. */
14+
15+
/* STM32F0x2 has internal USB pullup. */
16+
17+
/* Currently you can only use SPI1, since it has highest clock. */
18+
19+
#endif /* __BOARD_H__ */

boards/stm32-tiny042-v1.mk

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
stm32f042.mk

boards/stm32f042.mk

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ARCH_FLAGS = -DSTM32F0 -mthumb -mcpu=cortex-m0 -msoft-float
2+
LDSCRIPT = libopencm3/lib/stm32/f0/stm32f04xz6.ld
3+
LIBOPENCM3 = libopencm3/lib/libopencm3_stm32f0.a
4+
OPENCM3_MK = lib/stm32/f0

flashrom

spi.c

+16-16
Original file line numberDiff line numberDiff line change
@@ -21,44 +21,44 @@ uint32_t spi_setup(uint32_t speed_hz) {
2121
rcc_periph_clock_enable(RCC_SPI1);
2222
rcc_periph_clock_enable(RCC_DMA1);
2323

24-
/* SPI1 is on APB2 which runs at 72MHz. Assume f = f_PCLK / 2 = 36MHz (whereas datasheet says 16MHz max but reference manual has no such word). */
24+
/* SPI1 is on APB2 which runs at 72MHz. Assume f = f_PCLK / 2 = 36MHz (whereas datasheet says 18MHz max but reference manual has no such word). */
2525
/* Lowest available */
2626
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_256;
27-
relspd = 281250;
27+
relspd = rcc_apb2_frequency / 256;
2828

29-
if(speed_hz >= 562500) {
29+
if(speed_hz >= rcc_apb2_frequency / 128) {
3030
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_128;
31-
relspd = 562500;
31+
relspd = rcc_apb2_frequency / 128;
3232
}
3333

34-
if(speed_hz >= 1125000) {
34+
if(speed_hz >= rcc_apb2_frequency / 64) {
3535
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
36-
relspd = 1125000;
36+
relspd = rcc_apb2_frequency / 64;
3737
}
3838

39-
if(speed_hz >= 2250000) {
39+
if(speed_hz >= rcc_apb2_frequency / 32) {
4040
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_32;
41-
relspd = 2250000;
41+
relspd = rcc_apb2_frequency / 32;
4242
}
4343

44-
if(speed_hz >= 4500000) {
44+
if(speed_hz >= rcc_apb2_frequency / 16) {
4545
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_16;
46-
relspd = 4500000;
46+
relspd = rcc_apb2_frequency / 16;
4747
}
4848

49-
if(speed_hz >= 9000000) {
49+
if(speed_hz >= rcc_apb2_frequency / 8) {
5050
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_8;
51-
relspd = 9000000;
51+
relspd = rcc_apb2_frequency / 8;
5252
}
5353

54-
if(speed_hz >= 18000000) {
54+
if(speed_hz >= rcc_apb2_frequency / 4) {
5555
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_4;
56-
relspd = 18000000;
56+
relspd = rcc_apb2_frequency / 4;
5757
}
5858

59-
if(speed_hz >= 36000000) {
59+
if(speed_hz >= rcc_apb2_frequency / 2) {
6060
clkdiv = SPI_CR1_BAUDRATE_FPCLK_DIV_2;
61-
relspd = 36000000;
61+
relspd = rcc_apb2_frequency / 2;
6262
}
6363

6464
/* Configure GPIOs: SS = PA4, SCK = PA5, MISO = PA6, MOSI = PA7 */

spi.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include <libopencm3/stm32/gpio.h>
88

9-
#define SPI_DEFAULT_CLOCK 36000000
9+
#define SPI_DEFAULT_CLOCK 10000000
1010

1111
#define SPI_SELECT() gpio_clear(GPIOA, GPIO_SPI1_NSS)
1212
#define SPI_UNSELECT() gpio_set(GPIOA, GPIO_SPI1_NSS)

vserprog.c

+65-2
Original file line numberDiff line numberDiff line change
@@ -231,28 +231,91 @@ void handle_command(unsigned char command) {
231231
LED_IDLE();
232232
}
233233

234+
#ifdef GD32F103
235+
void rcc_clock_setup_in_hse_12mhz_out_120mhz(void) {
236+
/* Enable internal high-speed oscillator. */
237+
rcc_osc_on(RCC_HSI);
238+
rcc_wait_for_osc_ready(RCC_HSI);
239+
240+
/* Select HSI as SYSCLK source. */
241+
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
242+
243+
/* Enable external high-speed oscillator 12MHz. */
244+
rcc_osc_on(RCC_HSE);
245+
rcc_wait_for_osc_ready(RCC_HSE);
246+
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
247+
248+
/*
249+
* Set prescalers for AHB, ADC, ABP1, ABP2.
250+
* Do this before touching the PLL (TODO: why?).
251+
*/
252+
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 120MHz Max. 108MHz */
253+
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_ADCPRE) | ((uint32_t)0x10004000); /* ADC Set. 12MHz Max. 14MHz */
254+
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 60MHz Max. 54MHz */
255+
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 120MHz Max. 108MHz */
256+
RCC_CFGR |= ((uint32_t)0x00800000); /* USB Set. 48MHz Max. 48MHz */
257+
258+
/* GD32 has 0-wait-state flash */
259+
flash_set_ws(FLASH_ACR_LATENCY_0WS);
260+
261+
/*
262+
* Set the PLL multiplication factor to 10.
263+
* 12MHz (external) * 10 (multiplier) = 120MHz
264+
*/
265+
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL10);
266+
267+
/* Select HSE as PLL source. */
268+
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
269+
270+
/*
271+
* External frequency undivided before entering PLL
272+
* (only valid/needed for HSE).
273+
*/
274+
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
275+
276+
/* Enable PLL oscillator and wait for it to stabilize. */
277+
rcc_osc_on(RCC_PLL);
278+
rcc_wait_for_osc_ready(RCC_PLL);
279+
280+
/* Select PLL as SYSCLK source. */
281+
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
282+
283+
/* Set the peripheral clock frequencies used */
284+
rcc_ahb_frequency = 120000000;
285+
rcc_apb1_frequency = 60000000;
286+
rcc_apb2_frequency = 120000000;
287+
}
288+
#endif /* GD32F103 */
289+
234290
int main(void) {
235291
uint32_t i;
236292

237293
rcc_periph_clock_enable(BOARD_RCC_LED);
238294
LED_ENABLE();
239295
LED_BUSY();
240296

297+
#ifdef GD32F103
298+
rcc_clock_setup_in_hse_12mhz_out_120mhz();
299+
#else
241300
rcc_clock_setup_in_hse_8mhz_out_72mhz();
301+
#endif /* GD32F103 */
302+
242303
rcc_periph_clock_enable(RCC_GPIOA); /* For USB */
243304
rcc_periph_clock_enable(BOARD_RCC_USB_PULLUP);
244305
rcc_periph_clock_enable(RCC_AFIO); /* For SPI */
245306
#if BOARD_USE_DEBUG_PINS_AS_GPIO
246307
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_TIM2_REMAP_FULL_REMAP);
247308
#endif
248309

249-
/* Setup PB3 to pull up the D+ high. */
310+
#ifndef STM32F0
311+
/* Setup GPIO to pull up the D+ high. */
250312
gpio_set_mode(BOARD_PORT_USB_PULLUP, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, BOARD_PIN_USB_PULLUP);
251313
#if BOARD_USB_HIGH_IS_PULLUP
252314
gpio_set(BOARD_PORT_USB_PULLUP, BOARD_PIN_USB_PULLUP);
253315
#else
254316
gpio_clear(BOARD_PORT_USB_PULLUP, BOARD_PIN_USB_PULLUP);
255-
#endif
317+
#endif /* BOARD_USB_HIGH_IS_PULLUP */
318+
#endif /* STM32F0 */
256319

257320
usbcdc_init();
258321
spi_setup(SPI_DEFAULT_CLOCK);

0 commit comments

Comments
 (0)