Keil uVision - Atmel SAM3U Read Unique Identifier

0

I've been trying to read the Unique Identifier (UID) from a Atmel SAM3U MCU, but it's proven more difficult than it needs to be to make it happen. Does anyone have any examples or can suggest how to read it properly? Whenever I do, I wait in a do while loop (like the documentation states) for the EEFC (Flash ROM) status register to change states, but it never does so the MCU is then stuck in a loop.

Atmel Read Unique Identifier Document

Here is the code I'm using

// must run this from SRAM
__attribute__((section(".ARM.__at_0x20080000"))) void Get_Unique_ID(unsigned int *pdwUniqueID)
{
    Efc *p_efc;
    unsigned int status;
    
    // clear the array
    pdwUniqueID[0] = 0;
    pdwUniqueID[1] = 0;
    pdwUniqueID[2] = 0;
    pdwUniqueID[3] = 0;
    
    // send the Start Read Unique Identifier command (STUI) by writing the Flash Command Register with the STUI command
    p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
    
    // wait for the Flash Programming Status Register (EEFC_FSR) to fall
    do { status = p_efc->EEFC_FSR; }
    while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
    
    // the Unique Identifier is located in the first 128 bits of the Flash memory mapping
    pdwUniqueID[0] = *(unsigned int *)IFLASH0_ADDR;
    pdwUniqueID[1] = *(unsigned int *)(IFLASH0_ADDR + 4);
    pdwUniqueID[2] = *(unsigned int *)(IFLASH0_ADDR + 8);
    pdwUniqueID[3] = *(unsigned int *)(IFLASH0_ADDR + 12);
    
    // to stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
    // command (SPUI) by writing the Flash Command Register with the SPUI command
    p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI;
    
    // when the Stop Read Unique Unique Identifier command (SPUI) has been performed
    // the FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises
    do { status = p_efc->EEFC_FSR; }
    while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
}

Note that __attribute__((section(".ARM.__at_0x20080000"))) isn't the best method to dynamically assign this function to SRAM via the linker and any suggestions on how to make it more dynamic would be appreciated.

SOLVED The problem was the chips I had were fake so SAM-BA was returning whatever was at the SRAM buffer address it specified. It's a bug in SAM-BA since if it received 0x00000000, it should give an error or warning message and then stop reading. Do not buy fake chips from China!

Thanks.

arm
embedded
microcontroller
keil
atmel
asked on Stack Overflow Jan 27, 2021 by t0rxe • edited Feb 1, 2021 by t0rxe

1 Answer

0

I don't believe p_efc is correctly initialized. You create a pointer to a Efc datastructure which thus points to something.

You then write something to somewhere and are expect it to work.

Efc *p_efc;
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;

My guess would be that you need to intialize it to the correct EEFC base address. The datasheet has the following to say:

The SAM3U4 (256 Kbytes internal Flash version) embeds two EEFC (EEFC0 for Flash0 and EEFC1 for Flash1) whereas the SAM3U2/1 embeds one EEFC.

So depending on your MCU version you need to address EEFC0 or EEFC1. I'm assuming that you use libopencm3 but this will work for any other library. Look for the EEFC location define. Following the defines/files/links we get to this page, it tells us to point our Efc pointer to EEFC0_BASE or EEFC1_BASE. I would advise you to use the EEFC0 and EEFC1 defines though as it makes your code portabler.

So your code should work if your Efc is located in EEFC0 if you do:

Efc *p_efc = EEFC0;
answered on Stack Overflow Jan 28, 2021 by Tarick Welling • edited Jan 28, 2021 by Tarick Welling

User contributions licensed under CC BY-SA 3.0