From 905b7d153b58f2028e1dbd69910474d08d29606c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Sun, 14 Jun 2020 19:19:29 +0200 Subject: [PATCH] application: improve MCU identification --- application.c | 65 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/application.c b/application.c index 355629a..2ddba5f 100644 --- a/application.c +++ b/application.c @@ -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("Cortex‑M0"); + puts("Cortex-M0"); break; case 0xC23: // the ARM spec actually mentions 0xC24 - puts("Cortex‑M3"); + puts("Cortex-M3"); break; case 0xC24: - puts("Cortex‑M4"); + puts("Cortex-M4"); break; case 0xC27: - puts("Cortex‑M7"); + 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 }