cancel
Showing results for 
Search instead for 
Did you mean: 

Confusion with the DBGMCU_IDCODE register.

mreed
Associate III

In our product we will be placing one of 3 different processors. I have developed code to determine this by evaluating the registers for the peripherals, but I'm wondering if there is another way.

I've been looking at the DBGMCU_IDCODE register. And one thing confusing is that the value is different if you use the STLINK. In code, it looks like I can tell the difference between the various processors, but from the STLINK, you can't.

For clarity I'll only report the ID value, not the register contents.

Processor Code read value STLINK read value

STM32F427 120 419

STM32F429 310 419

STM32F437 320 419

1) Why are they different?

2) Can I rely on the code-read values?

I've also evaluated some other processors I'm working with:

Processor Code read value STLINK read value

STM32L051 810 417

STM32L073 820 447

6 REPLIES 6

The die can have multiple steppings (versions) as bugs are fixed, these will be listed in the errata, and ST typically only has a couple

I've used the codes to program PLL's in an assortment of F4-DISCO boards, so I can run each at maximum speeds and bus settings with a single application

The list here isn't comprehensive, at least in entire parts using each die, but is good enough for target practice.

//****************************************************************************
 
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 0x457 : printf("STM32L011xx\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;
    case 0x480 : printf("STM32H7Ax or H7Bx\n"); break;
    default : printf("Unknown STM32\n");
  }
}
 
//****************************************************************************
 
void SystemDiagnostic(void)
{
  printf("\n\nCore=%d, %d MHz\n", SystemCoreClock, SystemCoreClock / 1000000);
  CORECheck();
  IDCODECheck();
  FPUCheck();
  printf("APB1=%d\n", HAL_RCC_GetPCLK1Freq());
  printf("APB2=%d\n", HAL_RCC_GetPCLK2Freq());
}
 
//****************************************************************************

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

I your IDCODECheck() function you left out the F1. Understandable, the F1 idcode scheme is really complicated.

@Tesla DeLorean Thanks for sharing your code, it looks great. But I'm afraid it does not answer my questions.

Why is DBGMCU_IDCODE value different when I read it from executing code than what it is when I read it with STLINK?

The ID numbers in your code reflect the value obtained when read with STLINK. And 0x419 is the code for 427, 429, 437 and 439.

I will look through the errata, maybe that will help. :beaming_face_with_smiling_eyes:

> Why is DBGMCU_IDCODE value different when I read it from executing code

Show that code.

JW

I think the docs say the JTAG is reading a different internal register, not one in the processors addressable memory space.

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

Actually, there is no code. I just run the debugger in Eclipse and view memory location 0xE0042000 (for the st32L073/051 0x40015800).

I recently added the ST32L476RG (from a Nucleo board).

STLINK reports ID 415 Rev4, STLINK memory read returns 1007 6415

Memory in debugger displays: 1564 0710

AUUUG! I AM EMBARRASSED! :squinting_face_with_tongue:

I forgot the byte order. 1564 0710 is 1007 6415.

So Sorry! I really thought I had found a way to determine the part number.