cancel
Showing results for 
Search instead for 
Did you mean: 

Portability of the code STM32F411

DRous.1
Associate II

 

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

 

1 ACCEPTED SOLUTION

Accepted Solutions

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");
  }
}

//****************************************************************************
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

3 REPLIES 3

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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)

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");
  }
}

//****************************************************************************
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..