application: improve MCU identification

This commit is contained in:
King Kévin 2020-06-14 19:19:29 +02:00
parent e054774544
commit 905b7d153b
1 changed files with 47 additions and 18 deletions

View File

@ -34,6 +34,7 @@
#include "usb_cdcacm.h" // USB CDC ACM utilities
#include "terminal.h" // handle the terminal interface
#include "menu.h" // menu utilities
#include "flash_internal.h" // flash utilities
/** watchdog period in ms */
#define WATCHDOG_PERIOD 10000
@ -188,25 +189,46 @@ static void command_version(void* argument)
(void)argument; // we won't use the argument
printf("firmware date: %04u-%02u-%02u\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY); // show firmware build date
// show flash size
puts("flash size: ");
puts("MCU advertised flash size: ");
if (0xffff == DESIG_FLASH_SIZE) {
puts("unknown (probably a defective micro-controller\n");
puts("unknown (probably a counterfeit/defective micro-controller\n");
} else {
printf("%u KB\n", DESIG_FLASH_SIZE);
}
if ((uint32_t)&__flash_end >= FLASH_BASE) {
printf("linker advertised flash size: %u KB\n", ((uint32_t)&__flash_end - FLASH_BASE) / 1024);
}
uint32_t flash_size = flash_internal_probe_read_size();
printf("readable flash size: %u bytes (%u KB)\n", flash_size, flash_size / 1024);
flash_size = flash_internal_probe_write_size();
printf("writable flash size: %u bytes (%u KB)\n", flash_size, flash_size / 1024);
const uint16_t dev_id = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK;
const uint16_t rev_id = DBGMCU_IDCODE >> 16;
printf("MCUID: DEV_ID=0x%03x REV_ID=0x%04x\n", dev_id, rev_id);
// display device identity
printf("device id: %08x%08x%04x%04x\n", DESIG_UNIQUE_ID2, DESIG_UNIQUE_ID1, DESIG_UNIQUE_ID0 & 0xffff, DESIG_UNIQUE_ID0 >> 16);
char* unreadable;
if (0 == DBGMCU_IDCODE && 0 == (SCS_DHCSR & SCS_DHCSR_C_DEBUGEN)) {
unreadable = " (not readable, retry with debug attached)";
} else if (0x307 == DBGMCU_IDCODE && (SCS_DHCSR & SCS_DHCSR_C_DEBUGEN)) {
unreadable = " (erroneous reading, read over debug first)";
} else {
unreadable = "";
}
printf("MCU id code: %+08x (DEV_ID=0x%03x REV_ID=0x%04x)%s\n", DBGMCU_IDCODE, dev_id, rev_id, unreadable); // see below for details
printf("device id: %08x%08x%04x%04x\n", DESIG_UNIQUE_ID2, DESIG_UNIQUE_ID1, DESIG_UNIQUE_ID0 & 0xffff, DESIG_UNIQUE_ID0 >> 16); // not that the half-works are reversed in the first word
//printf("SCS_DHCSR: %+08x, DEBUGEN: %u\n", SCS_DHCSR, SCS_DHCSR & SCS_DHCSR_C_DEBUGEN);
// SCS_DHCSR: 0x03010000, DEBUGEN: 0 debug not attached
// SCS_DHCSR: 0x01010001, DEBUGEN: 1 debug attached
#if DEBUG
bool fake = false; // if details indicate it's not an STM32
puts("chip family: ");
switch (dev_id) {
case 0: // DBGMCU_IDCODE is only accessible in debug mode (this is a known issue documented in STM32F10xxC/D/E Errata sheet, without workaround)
case 0: // DBGMCU_IDCODE is only accessible in debug mode (this is a known issue documented in STM32F10xx8/B and STM32F10xxC/D/E Errata sheet, without workaround) (CKS32F103 is not affected by this issue)
puts("not readable, retry with debug attached");
break;
// from RM0008 STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx
case 0x307: // this is completely undocumented (even in the errata), but even with debug attached, DBGMCU_IDCODE = 0x00000307, until the DBGMCU_IDCODE is read over SWJ, only then it's correct. but the JEP106 ID part number is always right (with same meaning). this has been seen on a genuine STM32F103C8T6 (AFAICS)
puts("erroneous reading, read over debug first");
break;
case 0x412:
puts("STM32F10x low-density");
break;
@ -220,7 +242,7 @@ static void command_version(void* argument)
puts("STM32F10x XL-density");
break;
case 0x418:
puts("STM32F10xconnectivity");
puts("STM32F10x connectivity");
break;
// from RM0091 STM32F0x8
case 0x444:
@ -324,7 +346,7 @@ static void command_version(void* argument)
}
putc('\n');
// from RM0091 STM32F0x8 reference manual (not sure if it applies to F1)
puts("manufacturing information:\n");
puts("manufacturing information (STM32F0x8 schema):\n");
printf("- X,Y wafer coordinate: %08x\n", DESIG_UNIQUE_ID0);
printf("- lot number: %c%c%c%c%c%c%c\n", DESIG_UNIQUE_ID2 >> 24, DESIG_UNIQUE_ID2 >> 16, DESIG_UNIQUE_ID2 >> 8, DESIG_UNIQUE_ID2 >> 0, DESIG_UNIQUE_ID1 >> 24, DESIG_UNIQUE_ID1 >> 16, DESIG_UNIQUE_ID1 >> 8);
printf("- wafer number: %u\n", DESIG_UNIQUE_ID1 & 0xff);
@ -354,16 +376,16 @@ static void command_version(void* argument)
puts("Cortex-M0+");
break;
case 0xC20:
puts("CortexM0");
puts("Cortex-M0");
break;
case 0xC23: // the ARM spec actually mentions 0xC24
puts("CortexM3");
puts("Cortex-M3");
break;
case 0xC24:
puts("CortexM4");
puts("Cortex-M4");
break;
case 0xC27:
puts("CortexM7");
puts("Cortex-M7");
break;
default:
fake = true;
@ -390,23 +412,25 @@ static void command_version(void* argument)
}
printf(" (cont.=%u, ID=0x%02x), part=0x%03x\n", jep106_continuation, jep106_identification, pidr_partno);
// guess the micro-controller
char* mcu = "STM32"; // which MCU is identified
puts("MCU: ");
if (1 == cpuid_variant && 1 == cpuid_revision && 0 == jep106_continuation && 0x20 == jep106_identification) { // STM32 uses Cortex-M3 r1p1 and the right JEP106 ID
puts("STM32");
mcu = "STM32";
} else if (2 == cpuid_variant && 1 == cpuid_revision && 7 == jep106_continuation && 0x51 == jep106_identification) { // GD32 uses Cortex-M3 r2p1 and the right JEP106 ID
puts("GD32");
mcu = "GD32";
fake = true;
} else if (2 == cpuid_variant && 1 == cpuid_revision && 4 == jep106_continuation && 0x3b == jep106_identification) { // GD32 uses Cortex-M3 r2p1 and ARM JEP106 ID
puts("CS32");
mcu = "CKS32";
fake = true;
} else {
puts("unknown");
mcu = "unknown";
fake = true;
}
puts(mcu);
putc('\n');
// detect fake STM32
if (0x412 == dev_id || 0x410 == dev_id || 0x414 == dev_id || 0x430 == dev_id || 0x418 == dev_id) { // STM32F10x
// the original STM32F10x uses a Cortex-M3 r1p1
// STM32F10x uses a Cortex-M3 r1p1
if (0xC23 != cpuid_partno) { // Cortex-M3
fake = true;
}
@ -417,7 +441,12 @@ static void command_version(void* argument)
fake = true;
}
}
printf("this %s to be a genuine STM32\n", fake ? "does not seem" : "seems");
if (0 != DBGMCU_IDCODE && 0 == (SCS_DHCSR & SCS_DHCSR_C_DEBUGEN)) { // STM32 can't read the MCU ID without debug attached (see errata). CKS32 is not affected by this issue
fake = true;
}
if (0 == strcmp(mcu, "STM32")) {
printf("this %s to be a genuine STM32\n", fake ? "does not seem" : "seems");
}
#endif
}