Moving from STM32 to GD32

The STM32 and GigaDevice GD32 microcontrollers are often compared due to their similar architecture and compatibility. GD32 is a kind of “clone” of STM32, using the same ARM Cortex-M core. The main difference between the two is the price, as the GD32 is usually cheaper, making it attractive for projects on a tight budget. However, despite the similarities, there are differences in features and support levels that may affect the choice between these two families of microcontrollers.

Differences between STM32 and GD32


Although the external similarity and the same name with STMicroelectronics microcontrollers may suggest a complete copy, this is not entirely true. Chips from GigaDevice also have fundamental differences from STM. For example:

  • operating frequency: up to 108 MHz for the GD32F1 family (versus 72 MHz for the STM32F1);
  • Flash memory capacity: up to 3 MB (STM32F2 supports up to 1 MB);
  • RAM capacity: up to 256 KB (STM32 offers up to 128 KB).

Real experience

Several years ago (not at Selectel) we developed an automation controller on the STM32F107RCTx. The project used UART, Ethernet and several GPIOs (the project is under NDA, so we won’t reveal any secrets). The software was written in CubeIDE using FreeRTOS, HAL and lwIP and several third-party libraries. The device was configured via USB and web interface. The project was successfully completed and the customer was satisfied. However, a shortage of microcircuits began (chippageddon), STM32 controllers rose sharply in price and disappeared from warehouses.

We were asked to upgrade to the GD32F107, claiming that it was fully pin-to-pin compatible. You could write software for GD32 in Keil or IAR (you need to install GD32Fx AddOn). For ease of development, the GD32Fx Firmware Library with all drivers and examples is available. We started development at IAR, writing all the software from scratch. The customer is happy again, everything works.

But during operation, new ideas come up or bugs are discovered. As a result, there is a need to improve the software, and the exciting support of two pieces of hardware in two different IDEs begins.

Real experience x2


Are all programmers like this and like to do work twice? I'm starting to look for whether it is possible to make one software that would work on both pieces of hardware at the same time. The hardware of the chips is similar, the registers and legs are the same. After searching a little, I find a document called GD32 and STM32 Compatibility (sumcompatibilityup between GD32 and STM32_V2.0.pdf).

It lists the hardware differences between the GD32 and STM32 chips and practical recommendations for “working around” these differences (a kind of Errata). Having read the document and not seeing much “crime” there, I decide that I can flash the STM binary into GD and see what comes out of it.

Surprisingly, the software starts immediately, numbers are drawn on the display. Ethernet didn't work, but that's a minor issue, we can work with it. Will the debug work? When we try to start debugging we get an error Could not verify ST device! Well, it seems logical, this is not exactly an ST.

The debug doesn’t work, so we’ll try to solve it differently and debug the software in a non-contact way (collect binaries and flash it). Let's go deeper into

sumcompatibilityup

. First, you need to teach the software to determine in which hardware it “woke up”. This can be done using Jtag ID.

uint16_t Get_JTAG_ID()
{
	if(*(uint8_t *)(0xE00FFFE8) & 0x08)
	{
	return ((*(uint8_t *)(0xE00FFFD0)&0x0F)<<8) | ((*(uint8_t *)(0xE00FFFE4)&0xFF)>>3) | ((*(uint8_t *)(0xE00FFFE8)&0x07)<<5)+1;
	}
	return 0;
}
Если функция вернула 0x041 это ST, а если 0x7A3 то перед нами GD.

Since the most serious “difference” between the chips was the operating frequency, I made a separate SystemClock_Config function for GD. In it, using PLL, I overclock the frequency to 108 MHz (versus 72 MHz for STM).

I'm putting together a binary and flashing it (thanks, STM32 Link utility does not divide chips into its own and those of others and works with all), the display and buttons work, Ethernet works every now and then. Through telepathic efforts, I go through the options why Ethernet may not work. And after about 10 attempts, I assemble a new binary with autonegotiation disabled, let the network always operate at a speed of 100 Mbit (as per technical specifications). The guess turns out to be correct and the Ethernet interface starts working, an IP address is obtained via DHCP, data is transferred, and the lights blink.

Then there are a couple more steps: we need to add a sign in the web interface of what kind of piece of hardware is in front of us (this is important in case of potential problems and bugs). Fortunately, we already know how to distinguish hardware by Jtag ID.

Now the single project is theoretically ready, the software works identically on both pieces of hardware. But what if problems arise on GD in the future? How can I fix them without debugging?

Finding a way to debug software written in CubeIDE on GD hardware

On

YouTube

I find an exotic option. You need to run several different versions of CubeIDE in it and start debugging by manipulating and switching through the menu. Of course, thanks to the author, but the option clearly does not work.

Then several times on different forums such instructions come across.

  1. Install Debug probe in the project settings – OpenOCD.
  2. Edit config file C:\ST\STM32CubeIDE_1.3.0\STM32CubeIDE\plugins\ com.st.stm32cube.ide.mcu.debug.openocd_1.3.0.202002181050\ resources\openocd\st_scripts\target\stm32f1x.cfgby adding the line there set CPUTAPID 0.

The zero tells OpenOCD to ignore ID numbers, which means that all clones or non-STM microcontrollers will have to work.

I download CubeIDE 1.3, since under Windows you can simultaneously install several different versions of the IDE and they will not interfere with each other. I'm making a new test project. In the Debug probe settings, I select OpenOCD and launch Debug. And – lo and behold – I see that the debug has started (on the GD32F107x), you can go through the steps and look at the variables in memory.

Now the task is to drag and drop a working project made in an older version of the IDE. When opening the workspace, we receive a menacing message that the version is not the same and performance is not guaranteed. We take risks, open the project and see a message about Missing nature (I don’t understand what it is and why). CubeIDE supposedly offers a solution, but it doesn't work.

Since a project made directly in IDE 1.3 works, but not in a newer version, let's try to find the difference in the files. And it shows up in the file

.project

. Here's what we have in the 1.3 project:

com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAProjectNature

And here's what's in the project from 1.15:

com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAev2ProjectNature

We change one line to another in the combat project by hand – and it immediately opens. That's better, we try to assemble it – again the problem. We see that during assembly the project no longer fits into the allocated areas

RAM

. But how can this be? What has changed? Let's look at who is responsible for assembly and compilation.

In IDE 1.15, where the project was originally made, toolchain was used gnu-tools-for-stm32.12.3.rel1and the only one available in version 1.3 is gnu-tools-for-stm32.7-2018-q2.

On the portal community.st.com I’m finding information on how to add an alternative version of the toolchain to CubeIDE. You just need to copy and replace all the files from here:

C:\ST\STM32CubeIDE_1.15.0\STM32CubeIDE\plugins\ com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.12.3.rel1.win32_1.0.100.202403111256

Afterwards the files need to be inserted here:

C:\ST\STM32CubeIDE_1.3.0\STM32CubeIDE\plugins\ com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.0.0.201904181610

Also, in the project settings, you must force the Fixed version of the toolchain to be installed. We put the project together – and success! I start debugging and it’s also a success. We go step by step, the problem is solved.

What about setting CPUTAPID 0?

I will answer: no way. Version CubeIDE 1.3, when debugging via OpenOCD, does not ask unnecessary questions about the origin of the chip (if it is GD32), everything works without this life hack. I tried to do a trick with setting CPUTAPID 0 in the IDE with versions

1.8, 1.7 and 1.5

And

long story short

– it never worked out. But it was no longer necessary.

Conclusion


Now I have a project made in CubeIDE 1.3, which can be equally successfully launched and debugged on hardware on STM32 and GD32. Is it possible to do this in production on real projects? More likely no than yes. In my opinion, the CubeIDE user agreement does not encourage such things. Or am I wrong?

So everything stated above was done exclusively for research purposes and did not go into the field. And we continue to make two versions of the software for this piece of hardware in two different IDEs, making all the changes twice, because all programmers love this. 🙂

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *