Generally I would expect the F411 parts to be interchangeable, within the limits of the pin usage/escape
The Unique ID is more for tracking, serializing, and encryption type work.
There is a DEVID that identifies the chip die
Many of the other F4 part family members could also be identified, and accommodated with a singular code image, but those you'd need to manage PLL, RAM an FLASH differences.
//****************************************************************************
void CORECheck(void) // sourcer32@gmail.com
{
uint32_t cpuid = SCB->CPUID;
uint32_t var, pat;
printf("CPUID %08X DEVID %03X REVID %04X\n", cpuid, DBGMCU->IDCODE & 0xFFF, (DBGMCU->IDCODE >> 16) & 0xFFFF);
pat = (cpuid & 0x0000000F);
var = (cpuid & 0x00F00000) >> 20;
if ((cpuid & 0xFF000000) == 0x41000000) // ARM
{
switch((cpuid & 0x0000FFF0) >> 4)
{
case 0xC20 : printf("Cortex M0 r%dp%d\n", var, pat); break;
case 0xC60 : printf("Cortex M0+ r%dp%d\n", var, pat); break;
case 0xC21 : printf("Cortex M1 r%dp%d\n", var, pat); break;
case 0xC23 : printf("Cortex M3 r%dp%d\n", var, pat); break;
case 0xC24 : printf("Cortex M4 r%dp%d\n", var, pat); break;
case 0xC27 : printf("Cortex M7 r%dp%d\n", var, pat); break;
default : printf("Unknown CORE\n");
}
}
else
printf("Unknown CORE IMPLEMENTER\n");
}
//****************************************************************************
// FPU Programmer Model
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0489b/Chdhfiah.html
void FPUCheck(void) // sourcer32@gmail.com
{
uint32_t mvfr0;
printf("%08X %08X %08X\n%08X %08X %08X\n",
*(volatile uint32_t *)0xE000EF34, // FPCCR 0xC0000000
*(volatile uint32_t *)0xE000EF38, // FPCAR
*(volatile uint32_t *)0xE000EF3C, // FPDSCR
*(volatile uint32_t *)0xE000EF40, // MVFR0 0x10110021 vs 0x10110221
*(volatile uint32_t *)0xE000EF44, // MVFR1 0x11000011 vs 0x12000011
*(volatile uint32_t *)0xE000EF48); // MVFR2 0x00000040
mvfr0 = *(volatile uint32_t *)0xE000EF40;
switch(mvfr0)
{
case 0x00000000 : puts("No FPU"); break;
case 0x10110021 : puts("FPU-S Single-precision only"); break;
case 0x10110221 : puts("FPU-D Single-precision and Double-precision"); break;
default : puts("Unknown FPU");
}
}
//****************************************************************************
void IDCODECheck(void) // sourcer32@gmail.com
{
uint32_t idcode = DBGMCU->IDCODE & 0xFFF;
switch(idcode)
{
case 0x423 :
case 0x433 : printf("STM32F401\n"); break;
case 0x431 : printf("STM32F411\n"); break;
case 0x411 : printf("STM32F457\n"); break;
case 0x413 : printf("STM32F407\n"); break;
case 0x419 : printf("STM32F429 or F439\n"); break;
case 0x421 : printf("STM32F446\n"); break;
case 0x434 : printf("STM32F469\n"); break;
case 0x441 : printf("STM32F412\n"); break;
case 0x440 : printf("STM32F030x8\n"); break;
case 0x442 : printf("STM32F030xC\n"); break;
case 0x444 : printf("STM32F030x4 or F030x6\n"); break;
case 0x445 : printf("STM32F070x6\n"); break;
case 0x448 : printf("STM32F070x8\n"); break;
case 0x417 : printf("STM32L0 Cat 3\n"); break;
case 0x447 : printf("STM32L0 Cat 5\n"); break;
case 0x435 : printf("STM32L43xxx or L44xxx\n"); break;
case 0x415 : printf("STM32L475xx, L476xx or L486xx\n"); break;
case 0x461 : printf("STM32L496xx or L4A6xx\n"); break;
case 0x462 : printf("STM32L45xxx or L46xxx\n"); break;
case 0x470 : printf("STM32L4Rxxx or L4Sxxx\n"); break;
case 0x449 : printf("STM32F74xxx or F75xxx\n"); break;
case 0x451 : printf("STM32F76xxx or F77xxx\n"); break;
case 0x452 : printf("STM32F72xxx or F73xxx\n"); break;
case 0x450 : printf("STM32H7xx\n"); break;
default : printf("Unknown STM32\n");
}
}
//****************************************************************************