Colibri IMX6 Serial number unique?


Is there any accessable information on the colibri-imx6 processor, which is uniq to each CPU and not changable?
First thought was to use the CPU’s serial number as stated here .

But as described here and here, you can change the MAC adress via the bootloader or the sysinfo library. This would change the SN, since it is tied directly to the MAC address. ( here ) - or have I misunderstood something?

The reason is, we’d like to prevent copying of our product by connecting the application to a unique information stored on each CPU.

Dear @t_achmann

You understood it correctly. The Toradex Serial Number / MAC address is stored in the flash and hence can be changed.
But there are two devices on the Colibri iMX6DL which contain a unique ID

  • the eMMC flash device
  • the CPU

Reading the CPU ID is simple. It is stored in two 32-bit registers located at

  • 0x021B_C410
  • 0x021B_C420

A more detailed description can be found in the i.MX6 reference manual.

The Toradex CE Libraries contain a MapMemory library, which allows to access physical registers like this directly from your application.

Regards, Andy

Hi Andy, thanks for the quick reply.

I have never done this befor. Here is my sample code. Is this correct?
(ommiting Map_Init / Map-Deinti)

QString ToradexMapMem::readUniqueID() const {
    DWORD base = 0x021BC000;
    DWORD cfg0 = 0x410;
    DWORD cfg1 = 0x420;
    DWORD regSize = 32;

    void* mappedMemory1 = Map_MapMemory(base+cfg0, regSize);

    quint32 val1 = *((quint32 *)mappedMemory1);


    void* mappedMemory2 = Map_MapMemory(base+cfg1, regSize);

    quint32 val2 = *((quint32 *)mappedMemory2);


    return QString::number(val1)+QString::number(val2);

Hi @t_achmann

The code looks correct, however I can’t comment on line 19.

It could be done somewhat more efficiently, as Map_MapMemory() internally always works on junks of 2kB:
So you could use code similar to:

void* ocopt_ctrl = Map_MapMemory(base, 2048);
quint32 val0 = *((quint32 *)(ocopt_ctrl + cfg0 / sizeof(quint32));    
quint32 val1 = *((quint32 *)(ocopt_ctrl + cfg1 / sizeof(quint32));

Regards, Andy

Hi Andy,

thanks, works excellent! Only thing is the VC2015 compiler is a little bit picky on pointer to void arithmetic:

QString ToradexMapMem::readUniqueID() const {
    DWORD base = 0x021BC000;
    DWORD cfg0 = 0x410;
    DWORD cfg1 = 0x420;

    quint32* ocopt_ctrl = static_cast<quint32 *>(Map_MapMemory(base, 2048));
    quint32 val0 = *(static_cast<quint32 *>(ocopt_ctrl + cfg0 / sizeof(quint32)));
    quint32 val1 = *(static_cast<quint32 *>(ocopt_ctrl + cfg1 / sizeof(quint32)));

    return QString::number(val1)+QString::number(val2);