Update 2020-06-14: Added HK32

Hello there. This is a follow up on the comparison for the *32F103 parts. We’ve got the STM32F103C8T6, GD32F103C8T6, HK32F103CBT6, CS32F103C8T6 and APM32F103C8T6. As seen in part 2, there are some differences in how they identify themselves to the debugger. Now I’ll have a look at the ROMTABLE. I can query this information from within my code as well.

Surprisingly, there are some differences in the results I get from the debugger versus from code. As discussed in the ROMTABLE post, the STMicroeceltronics and the GigaDevice part identify themselves as such when looking at the PeripheralID values in the ROMTABLE.

The ApexMic and CKS parts gave different results when scanning the JTAG chain. Now, querying the ROMTABLE PID from code gives different results. BOTH the APM and CS part answer with bank 5 entry 59. Looking that one up gives me “ARM Ltd.”. Well…. it uses an ARM core, that’s right, but are you supposed to identify the core or the part which uses the core? Speaking about the core, the clones are of a newer revision of the Cortex M3 core. We can see that by looking at the CPUID. On an ARM core, we can find the CPUID in the System Control Space (SCS).

For the HK32, The JP106-used bit is not set. This means, the values for the vendor are not JEDEC assigned IDs. According the the ARM Debug Specs, in this case a legacy ID is used. The ID should contain an ASCII character to indicate a manufacturer. We see ID 85, which in the ASCII table is in ‘U’. Furthermore, we see the Continuation filled, but when interpreting the ID as a legacy ID, this field should be 0. Therefore, these values appear not to be according to specification, but these values give enough information to distinguish the part.

BEWARE: The revision is encoded in a rnpn scheme where r stands for revision and p for patch has a naming mismatch where with the CPUID register. CPUID Variant is Revision, CPUID Revision is Patch. This is confusing, and one may easily mix them up as they both use the word revision for a different field.

There is some more information in the Peripheral IDs such as a Part Number and a Revision. As specified in the ARMv7 TRM (ID120114) Appendix D1.

STM32 : Cortex-M3 r1p1  V:1 CONT:  0 ID: 32 PART: 410 REV:  0 
GD32  : Cortex-M3 r2p1  V:1 CONT:  7 ID: 81 PART: 76F REV:  0 
HK32  : Cortex-M3 r2p1  V:0 CONT:  5 ID: 85 PART: 29B REV:  0
CS32  : Cortex-M3 r2p1  V:1 CONT:  4 ID: 59 PART: 4C3 REV:  0 
APM32 : Cortex-M3 r2p1  V:1 CONT:  4 ID: 59 PART: 4C3 REV:  0 

So we see, the original STM32F103 is a Cortex-M3 r1p1, while the others are r2p1. This indicates a later patch level. As those microcontrollers are designed at a later time, this makes perfect sense. When one goes to ARM today to buy a Cortex-M3 license, one obtains the current revision. As the STM32F1 is one of the first Cortex M3 designs, it makes sense they’ve got an earlier revision of the core. The differences between the revisions can be looked up in the Cortex M3 Technical Reference Manual,

When looking at the values for part number, we notice that the STM32 has a part number of 0x410. This is the same value we’d expect when reading the DBGMCU_IDCODE register. But this time we don’t suffer from Errata 2.3: this value can be read from user code without debugger attached. When we look at the GigaDevice, we see a whole different part number. These part numbers are assigned by the manufacturer. Both the ApexMic and CKS part report manufacturer ARM Ltd., part number 4C3, which corresponds with Cortex-M3 ROM.

So far, I’ve been able to tell the STM and GD parts apart from the CS and APM, however, from code I haven’t yet found a way to distinguish the CS and APM, however, from a JTAG debugger. I could tell the difference from the debugger. Let’s have a look over there. The ROMTABLE contains some more information then just the Peripheral ID. It is a table after all, and there is some data in that table. I’ll have OpenOCD read the ROMTABLE for me. To dump all the output here would be way too long. But one thing, it shows all the components to be expected,

  • Cortex-M3 ROM (ROM Table)
  • Cortex-M3 SCS (System Control Space)
  • Cortex-M3 DWT (Data Watchpoint and Trace)
  • Cortex-M3 FPB (Flash Patch and Breakpoint)
  • Cortex-M3 ITM (Instrumentation Trace Module)
  • Cortex-M3 TPIU (Trace Port Interface Unit)

The first entry, “Cortex-M3 ROM (ROM Table)” shows up like this on the CS and APM, On the STM and GD we get “Unrecognized” as they have STM or GD part numbers

Interestingly on the CS32F103C8T6, there is an additional entry present, which is absent on the others: Cortex-M3 ETM (Embedded Trace).
Whether an actual ETM is present, I don’t know, but I know it won’t be usable, as the pins defined for ETM are only available in 100 pin packages, and the component I’m looking at is in an 48 pin package. Nevertheless, this gives a way to tell them apart. Since the ROMTABLE is accessible from code, I can write a detection code that will be able to tell at least the STM32F103C8T6, GD32F103C8T6, CS32F103C8T6 and APM32F103C8T6 apart.

See github for detection code 2020-06-14: Detection works, but on my HK32 board, the USB does not enumerate. I will have to investigate whether this is a incompatibility or an issue with my board.