Program once field

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Program once field

Jump to solution
708 Views
pascalschröer
Contributor V

Hi at all,

I have got a question to the program once field at the MK10DX128VLH7 cpu.

First of all I have to say, that I'm using the normal flash and eeprom functions without any problems.

Now I would like to use the program once option to store a serial number in my device.

Here are my questions:

1.      Which addresses do I have to choose for the program once field? These ones?

pastedImage_0.png

2.     Will the program once field be erased when I repartition the device? (I know that you should

partition your device only once)

Well, if the addresses above are right I have programmed the right sector. If I write to this sector with the

WRITE_ONCE_COMMAND I can store data and read out the data. But if I restart the device in debug mode,

the cpu gets a reset when reading the sector and I haven't got any chance to ckeck the error registers.

Thanks a lot!

Pascal

0 Kudos
1 Solution
475 Views
mjbcswitzerland
Specialist V

Pascal

The addresses in the address range may be confusing and are probably best ignored. If you want to read/write from the first OTP location (the one that is said to be at 0xc0 (4 bytes long in your device) you need to use the WRITE_ONCE/READ_ONCE commands with an index of 0 (up to an index of 16).

The OPT values can NEVER be deleted (EEPROM partition has nothing to do with this area).

Below is the OTP code from the uTasker project (using the interface code running in RAM as you already have).

To write 8 bytes (eg a serial number) to the start of the OTP area it can be called with:

unsigned long ulTestBuffer[2]; <- put two long word values into this array

fnProgramOnce(PROGRAM_ONCE_WRITE, ulTestBuffer, 0, 2);   // save to the first 2 long words in the program once area

To read the values back it can be called with:

fnProgramOnce(PROGRAM_ONCE_READ, ulTestBuffer, 0, 2);       

// read 2 long words from the start of the program-once area

Regards

Mark

// Read and write data from the program once area (64 bytes available which can only be programmed once in 4/8 byte blocks)

// The length is the number of long words to be copied to/from the buffer - FPU devices write 8 bytes at a time other 4 bytes at a time

//

extern int fnProgramOnce(int iCommand, unsigned long *ptrBuffer, unsigned char ucBlockNumber, unsigned char ucLength)

{

    #if defined KINETIS_K_FPU

    unsigned long ulBuffer[2];                                           // the devices with FPU read/write always 8 bytes at a time

    unsigned char ucIndex8;

    #endif

    unsigned char ucMax = (ucLength + ucBlockNumber);                    // finishing block

    unsigned char ucIndex = ucBlockNumber;                               // starting block

    unsigned char ucCommandType;

    if (iCommand == PROGRAM_ONCE_READ) {                                 // read data from the program once area

        ucCommandType = FCMD_READ_ONCE;

    }

    else {                                                               // program (one time programmable)

        ucCommandType = FCMD_PROGRAM_ONCE;

    }

    for (; ucIndex < ucMax; ) {

    #if defined KINETIS_K_FPU

        ucIndex8 = (ucIndex/2);

        if (ucCommandType == FCMD_PROGRAM_ONCE) {                        // writing

            if (ucIndex & 1) {                                           // uneven

                ulBuffer[0] = 0xffffffff;

                ulBuffer[1] = *ptrBuffer++;

                ucIndex++;

            }

            else {

                ulBuffer[0] = *ptrBuffer++;

                if (++ucIndex >= ucMax) {

                    ulBuffer[1] = 0xffffffff;

                }

                else {

                    ulBuffer[1] = *ptrBuffer++;

                }

                ucIndex++;

            }

        }

        if (fnFlashNow(ucCommandType, (unsigned long *)&ucIndex8, ulBuffer) != 0) { // read/write 2 long words at a time

            return -1;                                                   // error

        }

        if (ucCommandType == FCMD_READ_ONCE) {                           // reading

            if (ucIndex & 1) {                                           // uneven

                *ptrBuffer++ = ulBuffer[1];

            }

            else {

                *ptrBuffer++ = ulBuffer[0];

                ucIndex++;

                if (ucIndex >= ucMax) {

                    break;

                }

                *ptrBuffer++ = ulBuffer[1];

            }

            ucIndex++;

        }

    #else

        if (fnFlashNow(ucCommandType, (unsigned long *)&ucIndex, ptrBuffer) != 0) { // read/write 1 long word at a time

            return -1;                                                   // error

        }

        ucIndex++;

        ptrBuffer++;

    #endif

    }

    return 0;                                                            // success

}

P.S: The devices with phrase programming work with 8 bytes items and the code is then a little more complicated - you don't need the part with "#if defined KINETIS_K_FPU" which otherwise keeps the routine's interface compatible as long as each write is a multiple of 2 long words in size.

This means that if software designs may move to phrase programming devices it is recommended to design with this in mind already when working with a device such as the smaller and slower K10. (simply use an 8 byte serial number rather than a 4 byte one will allow compatible operation).

View solution in original post

0 Kudos
2 Replies
476 Views
mjbcswitzerland
Specialist V

Pascal

The addresses in the address range may be confusing and are probably best ignored. If you want to read/write from the first OTP location (the one that is said to be at 0xc0 (4 bytes long in your device) you need to use the WRITE_ONCE/READ_ONCE commands with an index of 0 (up to an index of 16).

The OPT values can NEVER be deleted (EEPROM partition has nothing to do with this area).

Below is the OTP code from the uTasker project (using the interface code running in RAM as you already have).

To write 8 bytes (eg a serial number) to the start of the OTP area it can be called with:

unsigned long ulTestBuffer[2]; <- put two long word values into this array

fnProgramOnce(PROGRAM_ONCE_WRITE, ulTestBuffer, 0, 2);   // save to the first 2 long words in the program once area

To read the values back it can be called with:

fnProgramOnce(PROGRAM_ONCE_READ, ulTestBuffer, 0, 2);       

// read 2 long words from the start of the program-once area

Regards

Mark

// Read and write data from the program once area (64 bytes available which can only be programmed once in 4/8 byte blocks)

// The length is the number of long words to be copied to/from the buffer - FPU devices write 8 bytes at a time other 4 bytes at a time

//

extern int fnProgramOnce(int iCommand, unsigned long *ptrBuffer, unsigned char ucBlockNumber, unsigned char ucLength)

{

    #if defined KINETIS_K_FPU

    unsigned long ulBuffer[2];                                           // the devices with FPU read/write always 8 bytes at a time

    unsigned char ucIndex8;

    #endif

    unsigned char ucMax = (ucLength + ucBlockNumber);                    // finishing block

    unsigned char ucIndex = ucBlockNumber;                               // starting block

    unsigned char ucCommandType;

    if (iCommand == PROGRAM_ONCE_READ) {                                 // read data from the program once area

        ucCommandType = FCMD_READ_ONCE;

    }

    else {                                                               // program (one time programmable)

        ucCommandType = FCMD_PROGRAM_ONCE;

    }

    for (; ucIndex < ucMax; ) {

    #if defined KINETIS_K_FPU

        ucIndex8 = (ucIndex/2);

        if (ucCommandType == FCMD_PROGRAM_ONCE) {                        // writing

            if (ucIndex & 1) {                                           // uneven

                ulBuffer[0] = 0xffffffff;

                ulBuffer[1] = *ptrBuffer++;

                ucIndex++;

            }

            else {

                ulBuffer[0] = *ptrBuffer++;

                if (++ucIndex >= ucMax) {

                    ulBuffer[1] = 0xffffffff;

                }

                else {

                    ulBuffer[1] = *ptrBuffer++;

                }

                ucIndex++;

            }

        }

        if (fnFlashNow(ucCommandType, (unsigned long *)&ucIndex8, ulBuffer) != 0) { // read/write 2 long words at a time

            return -1;                                                   // error

        }

        if (ucCommandType == FCMD_READ_ONCE) {                           // reading

            if (ucIndex & 1) {                                           // uneven

                *ptrBuffer++ = ulBuffer[1];

            }

            else {

                *ptrBuffer++ = ulBuffer[0];

                ucIndex++;

                if (ucIndex >= ucMax) {

                    break;

                }

                *ptrBuffer++ = ulBuffer[1];

            }

            ucIndex++;

        }

    #else

        if (fnFlashNow(ucCommandType, (unsigned long *)&ucIndex, ptrBuffer) != 0) { // read/write 1 long word at a time

            return -1;                                                   // error

        }

        ucIndex++;

        ptrBuffer++;

    #endif

    }

    return 0;                                                            // success

}

P.S: The devices with phrase programming work with 8 bytes items and the code is then a little more complicated - you don't need the part with "#if defined KINETIS_K_FPU" which otherwise keeps the routine's interface compatible as long as each write is a multiple of 2 long words in size.

This means that if software designs may move to phrase programming devices it is recommended to design with this in mind already when working with a device such as the smaller and slower K10. (simply use an 8 byte serial number rather than a 4 byte one will allow compatible operation).

0 Kudos
475 Views
pascalschröer
Contributor V

Hi Mark,

Yes, it's very confusing with these addresses :smileysilly: but now it works! I could take my code and only have to change the addresses from 0x00 to 0x0F.

And I got the access error because I tried to write two times to the same address.

Thanks a lot!

Pascal

0 Kudos