GD32F103: A STM32F103 on steroids!

posted in: STM32 | 6

Edit. June 2018

At the time I wrote this post, cheap GD32 based boards were  being sold on AliExpress and eBay.
However this is no longer the case.

I’m just retaining this post for historical reference


Original post


The world of the STM32 continues to get more interesting, with the recent availability of micro-controller boards based on the GigaDevices GD32F103. These devices have a quoted operating frequency of 108MHz, but as I will demonstrate, these boards also seem to work fine at 120Mhz.

I first became aware of a GD32F103C board being available on, via a posting on by @jackson009 about a month ago.

I did some research and discovered that GigaDevices have licensed the design of the STM32F103 from STM, and produced an enhanced version of the STM32F103.

(Update. Nov 18th 2015. When I published this article in September 2015, it appeared as if GigaDevices were a “strategic partner’ of STM. See , however this has now been clarified by STM in a letter to Olimex, indicating that that STM have not licensed the STM32 core to Gigadevices

So it appears that the GD32 has been designed by Gigadevices to be pin and generally register compatible with the STM32)


The GD32F103 has a maximum quoted clock speed of 108MHz, rather than the 72Mhz on the STM32F103, they also have a number of other changes. However the main improvement seems to be the faster clock speeds.

I managed to get some GD32F103C8 boards from TaoBao, (via about a week ago and set about trying to use them with the existing STM32 core.

Initial results were good. It was possible to flash the board using a USB to Serial adaptor, and the blink sketch worked OK, albeit it blinked faster than on the STM32. However Serial didnt work correctly because the clock rate of 108Mhz is 1.5 times faster than on the STM32, so I duplicated the STM32F1 core to make a GD32F103 core and set about investigating the clock settings in order to get the Serial and other timing related things working.

The first difference I noticed with these GD32F103 boards, is that the crystal is 12Mhz instead of the usual 8Mhz used on STM32 boards. Actually STM32 boards could use 12Mhz crystals but generally 8Mhz ones seem to be used on all STM32 boards I’ve seen on eBay and AliExpress.

The STM32 (and GD32) have a Phase Locked Loop (PLL) that multiplies the crystal oscillator frequency to become the master clock frequency. The crystal circuit is called the High Speed External oscillator or HSE for short. On the STM32 the normal setting for the PLL is to multiply the 8Mhz by 9 times to give 72Mhz, but as the crystal on the GD32 board is 12Mhz, the 9 times multipler gives 108Mhz – which is the maximum quoted operational speed of the GD32.

Looking at the other clock controls, the peripheral clocks APB1 and APB2 are quoted as being able to operate at 54MHz and 108Mhz respectively, so the prescalers (dividers) did not need to be changed for the board to operate at 108Mhz.

However at 108Mhz, the USB would not function. This is because the USB prescaler on the STM32 @ 72Mhz is set to 0x00 which gives a prescale value of 1.5 and hence a USB clock of the required 48MHz, and with the GD32 main clock at 108Mhz, the USB clock would be running at 72Mhz not the required 48Mhz.

On the STM32, there is just 1 binary bit to control the USB prescaler, with value of 1.5 x or 1 x, which means that the only clock frequencies that will allow USB operation (48Mhz clock) are 72Mhz and 48Mhz.

However on the GD32, there is an additional bit (23) so that there are 4 USB prescaler options, 1, 1.5, 2 and 2.5, which allows for higher clock speeds to be used while still allowing USB.

But… And its a bit but… If you do the maths,  to use the 108Mhz clock frequency, you need a USB prescaler value of 108/48 = 2.25,  But there isn’t a matching USB prescaler option 🙁

Which strikes me as being very odd.

The new USB prescaler values of 2.0 and 2.5 allow clock frequencies of 48 x 2 = 96Mhz or 48 x 2.5 = 120MHz.

I suspect that perhaps GigaDevices thought that they would be able to operate these devices at 120MHz and hence included a prescaler value of 2.5 to cater for this, but perhaps their production was yeild was not good for devices that could operate at 120Mhz over the spec’ed operating voltages and temperature range, so they had to fall back to saying the GD32 could operate at 108Mhz (and fail to point out that USB was not available at that frequency !)

But like most techie’s I’m always one to push the boundaries, so I thought I may as well set the main PLL to 10 and run the GD32 at 120Mhz and set the USB prescaler to 2.5 so that USB would have the correct clock.

The GD32’s I have, seem to run fine at 120Mhz, under normal domestic conditions, however initially the USB didn’t work.

On closer inspection, and after finding a circuit schematic on the web, it became obvious why the USB was not working: it was because the USB DP (D+) line was not pulled high via the normal 1.5k resistor, as the board does not have a resistor on either D+ or D-.  Where as most STM32 boards have 1.5k connected to D+.

So I fitted an external resistor, and the USB sprang into life.

I’ve now updated both the stm32duino-bootloader to include a generic-pc13 version which runs at 120Mhz and I’ve also updated the Arduino_STM32 repo to include a generic GD32F103C option. I’ve added a clock speed menu for the GD32, which allows selection of 72,96 or 120MHz, as these are the 3 values that allow USB to work. I could have included 48MHz, but I don’t see a need for this, apart from perhaps in low power applications. I’ve not currently included a 108Mhz option as USB doesnt run at 108Mhz and generally 120Mhz seems to work fine.

One note with the GD32 core. I understand from reading some docs translated from Chinese, that there are other changes e.g. changes to Timer Capture; but I have not made any changes to the core about this, because at the moment I’m not aware that the core uses timer capture. The only changes that probably need to be made to the EEPROM library and the bootloader, as there appear to be some changes to the flags that indicate when Flash has finished being erased, but at the moment the bootloader appears to work fine, so I will add that to my To Do list for future stability of the code.


(Update. Nov 18th 2015.

Since posting, this original article I have done some speed comparisons, and the improved clock frequency is not the only improvement. The Flash memory on the GD32 operates without any “wait states” (its known as “Zero wait state”). From what I recall, the STM32 requires 2 or 3 wait states at 72Mhz (don’t quote me on this, but I kown its not zero wait state).

This change gives an instance performance increase to the GD32 even running running at 72Mhz, which result in a Dhrystone test running with a Vax MIPS speed of 64.41 (@72Mhz) where as the STM32 was showing 48.81 – See this thread


This is not a terribly scientific comparison, but I think gives a reasonably general indication of the performance differences between the G32 and the STM32




In conclusion, the GD32 is an interesting new addition for anyone interested in a cortex M3 device, especially as its very similar to the familiar STM32F103, or anyone interested in more performance than the STM32F103 currently offers.

6 Responses

  1. Angel Genchev

    Nice observations. Beware that STM32 also overclocks *very* well, mine (on a blue pill) worked at max multiplier 16×8 -> 128 Mhz, and frequencies above 200 Mhz have been reported by enthusiasts who soldered 16Mhz crystals.
    The power consumption rises rapidly so it may past the max allowed values by the specs.
    What I miss is comparison of the power consumption at equal frequencies. It depends on the process used. Also It’s interesting what is their flash endurance – how many years / how many cycles it sustains compared to STM32 (we know that finner flash cells sustain less writing cycles).
    The lowest power consumption (in low power modes) is of interest also.

  2. Lefour

    Hello i have a flight control board with a gd32f103rbt6 and i would like read it but i don’t now how do this

  3. Roger Clark

    I have found that the GD32 is not as compatible with the STM32 as GD would like you to believe. So only some of the Arduino functions work e.g. SPI seems to have differences which mean it doesn’t always work on the GD32

    You could try selecting the GD32F103C board in my repo, as this may work for your board, but it may not, as your board may not use a 12Mhz main crystal and may have other differences

  4. Roger Clark


    I’ve not tried overclocking the STM32, apart from we normally run the SPI @ 36Mhz which is well above its 20Mhz spec speed and still seems to work fine.

    I know some members of the forum have overclocked to beyond 120Mhz but not anywhere near 200Mhz, because they are just using the normal 8Mhz crystal.

    The advantage of the GD32 is that it has 2 more USB PLL settings which means that it will run at 120Mhz and still have USB, but the STM32F103 is limited to 48 or 72Mhz if you still want USB.

    Re: Low power modes.

    If you look on the forum, @ahull has done a “sunrise / sunset timer” which uses the low power mode with wakeup from RTC interrupt.

    I’ve also investigated running the STM32 @ 8Mhz and from memory I think the current drawn was about 10mA instead of 40mA. But generally the best way to operate with minimum power is not to lower the clock rate, but to use the low power / sleep modes and use wake by external interrupt or by internal RTC interrupt.
    However in some instance running at 8Mhz can be handy.

  5. Stimmy

    Out of curiousity, I’ve just tried to overclock two regular STM32F103.
    Both were doing 128 MHz just fine, so I replaced the crystals with higher frequency ones. One board now has a 18 MHz crystal, the other one is 12 MHz.

    Both boards seem to run stable up to 144 MHz (12MHz * 12 or 18 MHz * 8), exactly double the specified clock.
    At 156 MHz, the board usually hangs after a few seconds. At higher frequencies, they crash in the moment the PLL clock is activated.

    Also, I tried running them from RAM, since I suspected the flash would limit the speed. This does not seem to be the case, they reach exactly the same stable multipliers from RAM as from flash.
    Additionally, I tested the influence of the wait states: With 0 wait states, it was stable up to 60 MHz, with 1 wait state up to 108 MHz.

    And another test: Overvolting does not help in getting higher clocks 😉 . I supplied them with 4.0V (the absolute maximum rating), and they were more unstable as with 3.3 volts.

    One useful reason for overclocking may be the higher ADC speed: The ADCs also seem to overclock very well.
    In an earlier project, I had run the ADC with a divider of 2 on 128 MHz MCU clock. Therefore it is clocked at 64 MHz instead of the allowed 14 MHz, outputting no less than 9.14 MS/s in interleaved mode.
    The measurement results still seemed OK, they only were about 1% lower than at regular speeds. Maybe I’ll test the analog bandwidth of the ADCs, with such a sampling rate they would make quite a useful little oscilloscope.

  6. Roger Clark

    Thats for sharing your experimental data.

    The STM32F103 seems to be a very robust device and can handle a lot of overclocking.
    I think you were lucky with the wait state settings working for you. I recall a few other people playing with the wait states even at 72Mhz and having crashes.

    The drawback with overclocking the STM32 is that USB will only work when the clock runs at 72Mhz or 48Mhz, as the F103 only has 2 clock divider settings.

    The GD32 has 4 USB PLL divider settings, one of which allows the device to run at 120Mhz and still have USB functionality.
    Also the GD32 is higher performance per clock cycle, because the program actually runs from shadow RAM and hence there are no “wait states” in fetching program data.
    This seems to give the GD32 a reasonable performance boost over the STM32 on the same clock speed.

    I’ve not tried overclocking the GD32, so its hard to know whether it would be as robust as the STM32. Potentially not, as its a cheaper device than the STM32 (OEM price)