Update 2020-06-13: Added the HK32, updated stlink-gui/st-flash: it works with CKS32 now.

Welcome back to my 32F103 Comparison. Let’s recap. The STM32F103C8T6 is a popular microcontroller by STMicroelectronics. Various Chinese manufacturers are producing parts in the same naming scheme, eg. APM32F103C8T6, BLM32F103C8T6, CS32F103C8T6, GD32F103C8T6 and MM32F103C8T6. What does this mean? There are parts, such as the famous 555 timer, you can get from many manufacturers and you can expect to get a compatible part. The same holds for the 7400 series and components such as opamps. However, there are edge cases where an equivalent part from another manufacturer won’t work. See EEVblog #1057 – µCurrent Murphy for issues related from a same part from a different manufacturer.

When we enter the world of microcontrollers, this does not have to apply. Even though a similar looking naming scheme might suggest compatibility, this is not always the case.

So far, the ordered MCUs are at least pin-compatible. I’ve soldered them to boards, and I’ll attach a debugger and see what we’ve got. What will I be looking at? First of all, these chips speak both SWD and JTAG. I’ll connect to them over JTAG, to see how they identify themselves in their ROMTABLE.
Furthermore, I’ll see if I can attach a debugger, using OpenOCD configured for an STM part, and I’ll see what QStlink2 makes of it.

JTAG Identification

For this test, I’ll hook op a SEGGER J-Link Edu Mini to the board, and run
openocd -f "interface/jlink.cfg" -c "transport select jtag; adapter_khz 4000;"
for each board. This will cause openocd to connect over the JTAG protocol and autoconfigure the chain. This configure will not be any good for actual debugging, but will show what is connected.

STM32F103C8T6

Info : JTAG tap: auto0.tap tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: auto1.tap tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)

When we look at the original STMicroelectronics part, we see OpenOCD has autoconfigured the chain, and sees two taps. We see a tap where the manufacturer is ARM (The Cortex-M3 core) and we see a TAP where the manufacturer is STMicroelectronics. This is what is expected.

GD32F101CBT6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto1.tap tap/device found: 0x790007a3 (mfg: 0x3d1 (GigaDevice Semiconductor (Beijing)), part: 0x9000, ver: 0x7)

When we look at a GigaDevice part (This is actually an F101 rather then an F103). Again we see two taps, one by ARM and one by GigaDevice. This is what it should look like. A part that identifies itself correctly. One thing to notice is the ARM part has another version number. I believe this refers to the revision of the debugger interface, I’ll come back to this later.

APM32F103C8T6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto1.tap tap/device found: 0x16410001 (mfg: 0x000 (<invalid>), part: 0x6410, ver: 0x1)

At the ApexMic part, we get a report of an invalid manufacturer. At least it doesn’t lie.

BLM32F103C8T6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)

BetterLife only shows the ARM TAP. So, it only shows the ARM Debugger interface, giving no clue about the device itself.

CS32F103C8T6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto1.tap tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)

Looking at the CS32, we see something dirty! This microcontroller pretends to be a STMicroelectronics. Nasty!

HK32F103CBT6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)

Hangshun only shows the ARM TAP.

MM32F103C8T6

Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)

MindMotion only shows the ARM TAP.


The version of the part

In the output we see the debugger interface, Manufacturer 0x23b (ARM Ltd.), Part 0xba00, with either version 3 or 4. I’m not entirely sure about this part, when I look through the specifications.

In the CoreSight SoC Technical Reference Manual – CoreSight Design Kits is mentioned as the JTAG-AP part number, however, it mentions the version should be 5. In the CoreSight SoC Technical Reference Manual – CoreSight-Soc400 it mentions again 0xba00 as the part number for JTAG-AP, with version 4. Version 3 is mentioned as the version for the SWD-AP, but that has part number 0xBA02. So I’m not entirely sure what is going on. Also, I guess I don’t have a complete understanding about which Technical Reference Manual is applicable. I mean, I know I’m dealing with a Cortex-M3 microcontroller. I believe CoreSight is the debugger interface, but what is SoC-400 or SoC-600? I believe DAP-Light is used on Cortex M0, but what is used on the orther Cortex-M series? I don’t know at this moment.

However, apart from looking the version number up in the documentation, are there any relevant differences between those versions that could have implications while using or debugging the microcontroller? There are other reasons why this might be relevant. When browsing the internet, there are a number of questions regarding these numbers. When using OpenOCD, this might result in error messages like

Warn : UNEXPECTED idcode: 0x2ba01477
Error: expected 1 of 1: 0x1ba01477

or

Warn : JTAG tap: stm32f1x.cpu       UNEXPECTED: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
Error: JTAG tap: stm32f1x.cpu  expected 1 of 1: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)

The first one appears to only show up when connecting using an ST-Link debugger connecting over SWD, and does not show up on a J-Link debugger connecting over SWD. The second one shows up on a J-Link debugger connecting over JTAG.

This solution will work, but requires changing configuration files while changing chips

#jtag scan chain
if { [info exists CPUTAPID] } {
   set _CPUTAPID $CPUTAPID
} else {
   if { [using_jtag] } {
      # Replace 0x3ba00477 with 0x4ba00477
      #set _CPUTAPID 0x3ba00477
      set _CPUTAPID 0x4ba00477
   } {
      # Replace 0x1ba00477 with 0x2ba00477
      #set _CPUTAPID 0x1ba01477
      set _CPUTAPID 0x2ba01477
   }
}

In theory there should be a way to ignore the version all together, using the -ignore-version option. However, the ST-Link HLA driver ignores this and still gives the error.

# Adding -ignore-version at the end
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -ignore-version

This fixes the problem when connecting over JTAG using an J-Link. For some reason, when connecting over SWD using the J-Link, the version was already being ignored. I guess these are caused by differences between the normal JTAG/SWD implementation and the High Level Architecture used by the ST-Link.


Compatibility with existing tools

I have tested whether these MCUs work with existing tools targetting the STM32. There are many tools out there, I have to make a selection which ones to test. Personaly, I usually use only OpenOCD, for both flashing and debugging. I have tested dedicated flash tools st-flash / stlink-gui and qstlink2. All of these tools use an ST-Link debugger. Furthermore, I have tested OpenOCD as a debugger, which supports the ST-Link and many other debuggers such as the J-Link. I’ve also tested JLinkExe (aka J-Link Commander), a commercial tool by SEGGER, which works with their J-Link debuggers.

APM32F103C8T6

Flashing:

qstlink2 FAIL
Connects fine, hangs on flashing
stlink-gui / st-flash FAIL
Erases fine, writing fails (unknown coreid, not sure what flash loader to use, aborting!)
OpenOCD SUCCESS
Works fine with the adjustments in the condig file described above
JLinkExe TBD
J-Link has no specific support for this part. TODO: Selecting the ST part probably works, verify this

BLM32F103C8T6

qstlink2 FAIL
Error: Did not find chipID!
stlink-gui / st-flash FAIL
Unknown Chip ID
OpenOCD FAIL
Cannot identify target as a STM32 family.
JLinkExe TBD
J-Link has no specific support for this part. TODO: Probably won’t work,

CS32F103C8T6

qstlink2 FAIL
Connects fine, hangs on flashing
stlink-gui / st-flash FAIL SUCCESS
Erases fine, writing fails (unknown coreid, not sure what flash loader to use, aborting!)
Update 2020-06-13: It works noq. Probably fixed in a later version then I used back in the days. I didn’t note the version back then, but today the version is v1.6.0
OpenOCD SUCCESS
Works fine with the adjustments in the condig file described above
JLinkExe TBD
J-Link has no specific support for this part. TODO: Selecting the ST part probably works, verify this

GD32F103C8T6

qstlink2 SUCCESS
Connects fine, flashes fine
stlink-gui / st-flash SUCCESS
Erases fine, flashes fine
OpenOCD SUCCESS
Works with original config. Even though on mass erase it times out.
JLinkExe TBD
J-Link has specific support for this part

HK32F103CBT6

qstlink2 FAIL
Connects fine, hangs on flashing
stlink-gui / st-flash SUCCESS
OpenOCD SUCCESS
Works fine with the adjustments in the condig file described above
JLinkExe TBD

MM32F103C8T6

qstlink2 FAIL
Connects fine, says Unknown Device
stlink-gui / st-flash FAIL
Did not find chipID!
OpenOCD FAIL
Cannot identify target as a STM32 family.
JLinkExe TBD
J-Link has specific support for this part

Conclusions

APM32F103C8T6

This part lacks documentation, (there is only a Chinese datasheet, which only gives a global overview, no register descriptions). The company’s website is having issues, which have been there for the past month, which is gives them poor credibility. The mcu appears to have some level of compatibility. So far, we’re able to program it using OpenOCD. Further testing will have to give some clues about code compatibility.

BLM32F103C8T6

This part is not compatible with the STM counterpart. As it lacks documentation, I’d say, it’s completely useless. I have no clue how to continue testing this part

CS32F103C8T6

This part lacks documentation, (there is only a Chinese datasheet, which only gives a global overview, no register descriptions). It is unclear who manufactures it. It appears to have some level of compatibility. Chinese sellers claim it is a ‘drop-in replacement’. So far, we’re able to program it using OpenOCD. Further testing will have to give some clues about code compatibility.

GD32F103C8T6

The GigaDevice part has been around for years. It works with existing tools. It has been discussed by various people in the past. There is a good level of code compatibility. I’ve had some experience with this part in the past, and so far I’ve not run into code-compatibility issues.

MM32F103C8T6

While this part is only pin compatible, but incompatible firmware and programming wise, it can not rely on existing flashing tools and debugging software. There is support for this part in commercial software (SEGGER J-Link), so it is possible to use this part with off-the-shelf tools. Looking at the documentation provided (I only took a quick glance), I believe it should not be hard to add support to open source tools. Is it worth it? Maybe if you need the speed (168 MHz vs 72 MHz)?