2024-05-29 04:58 PM
Hi,
I have built a program on my Nucleo F411 development kit, which has an STM32F411RE on it. I want to design a custom PCB for my program and use the same STM32F411, but this time in an STM32F411CE format.
Using STM32CubeIDE, would it be possible to flash the custom PCB with the STM32F411CE with the exact same code as the STM32F411RE since everything looks identical inside the chip? If not, are there setups that can be changed to fit the chip without having to rebuild the program around a new STM32F411CE project?
I'm not using all of the I/Os, so having a smaller format is better for my design.
Nucleo :
https://www.st.com/en/evaluation-tools/nucleo-f411re.html
STM32F411CE :
https://estore.st.com/en/stm32f411cey6tr-cpn.html
Solved! Go to Solution.
2024-05-29 05:22 PM
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");
}
}
//****************************************************************************
2024-05-29 05:05 PM
Many of these part share a common die, this is affixed in the package and bonded out different ways depending on the number of pins/balls a particular form-factor allows for.
There's typically a couple of bits in the Unique ID that identify exactly which, and values in OTP for the amount of FLASH tested on a given part.
2024-05-29 05:07 PM
So from what I understand, since there are unique ID between the device models, it will not be possible to use the same code and flash the new device (STM32F411CE)
2024-05-29 05:22 PM
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");
}
}
//****************************************************************************