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).