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?
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
Solved! Go to Solution.
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).
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).
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