IAP ROM Bug!!!

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

IAP ROM Bug!!!

671 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kralux on Fri Oct 26 09:52:41 MST 2012
The In-App Flash Programming on the LPC11xx has bugs in it!
The following piece of code erases the memory and then programs it twice with different values.
Bits that are reset to 0 during the first or second programming should remain to zero and bits programmed to 1 both times should remain to one.
So writing this pattern 0xAAFFFF55 followed by 0xFFAA55FF should lead to a Flash page programmed with 0xAAAA5555 and it does for most of the bytes except every 16 bytes, one bit is flipped down whereas it should not be.
The result in memory is:
0xAAAA5555 0xAAAA5[COLOR=Red]1[/COLOR]55 0xAAAA5555 0xAAAA5555 instead of
0xAAAA5555 0xAAAA5555 0xAAAA5555 0xAAAA5555
Note that the result you get is also pattern depending which also points to a bug (meaning if you write 1000 times 0xFFFFFFFF, no bit flip will occur). For instance if the second pattern is 0xFF55AAFF, then the result in memory will be:
0xAA55AA55 0xAA55A[COLOR=Red]E[/COLOR]55 0xAA55AA55 0xAA55AA55 instead of
0xAA55AA55 0xAA55AA55  0xAA55AA55 0xAA55AA55

Here is the code for you to test and confirm this is a real ROM routine bug:

// IAP Calls
typedef void (*IAP) (uint32_t [],uint32_t []);
#define IAP_LOCATION0x1fff1ff1
// IAP Commands
#define PREPARE_SECTORS50
#define COPY_RAM_TO_FLASH51
#define ERASE_SECTORS52
#define BLANK_CHECK_SECTORS53
#define COMPARE56
#define READ_UID58
#define ERASE_PAGE59


uint32_t retVal0, retVal1, retVal2, retVal3, retVal4, retVal5;
int32_t i;
// TEST
__disable_irq();  // since Flash is unavailable during operations, disable ALL IRQs to avoid crashing
retVal0 = prepareSectors(8, 8); 
retVal1 = erasePages(128, 128); // addr 0x8000
__enable_irq();

for (i = 0; i < 256 / 4; i++) {
buf0.chunk = 0xaaFFFF55;
}
for (i = 256 / 4; i < 512 / 4; i++) {
buf0.chunk = 0xFFaaFFFF;
}

for (i = 0; i < 1; i++) {
__disable_irq();  // since Flash is unavailable during operations, disable ALL IRQs to avoid crashing
retVal2 = prepareSectors(8, 8); 
retVal3 = writePages(0x8000, (uint32_t) &buf0.chunk, 256);
retVal4 = prepareSectors(8, 8); 
retVal5 = writePages(0x8000, (uint32_t) &buf0.chunk[256/4], 256);
__enable_irq();
}


// Prepares sectors for write/erase.
// Will prepare both start and end sectors. They should both be the same to prepare a single sector
uint32_t prepareSectors(int32_t startSector, int32_t endSector) {
command[0] = PREPARE_SECTORS;
command[1] = startSector;
command[2] = endSector;
iapEntry(command, result);
return result[0];
}

// Erases a page or multiple pages in the flash memory.
// Use the same start and end page to erase only one page.
uint32_t erasePages(int32_t startPage, int32_t endPage) {
command[0] = ERASE_PAGE;
command[1] = startPage;
command[2] = endPage;
command[3] = PLL_FREQ * 1000; // clock in kHz
iapEntry(command, result);
return result[0];
}

// Programs the flash memory. Sectors must be prepares first, then erased (set to 0xFF) before being able to be programmed.
// The boot sector can not be written by this command.
// flashDestinationAddr: Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
// ramSourceAddr: Source RAM address from which data bytes are to be read. This address should be a word boundary.
// size: Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
uint32_t writePages(uint32_t flashDestinationAddr, uint32_t ramSourceAddr, uint32_t size) {
command[0] = COPY_RAM_TO_FLASH;
command[1] = flashDestinationAddr;
command[2] = ramSourceAddr;
command[3] = size;
command[4] = PLL_FREQ * 1000; // clock in kHz
iapEntry(command, result);
return result[0];
}


So am I doing something wrong or is it really a bug or limitation that you cannot program more than once after erasing (understood that it will act as an AND between successive programming of course)?

This was tested on an LPC1115 so you may need to change the address of the Flash to which you are writing to if you don't have 64 KB of Flash memory like the LPC1115 (just change the sector, page and address 0x8000 accordingly). You will also need to set PLL_FREQ to whichever value you need to.
0 Kudos
5 Replies

522 Views
harrienoorlande
Contributor I

It seems like I am facing the same issue, with an LPC11C24.

If I understand 'LPC WARE' correctly, an sector erase should always be executed prior to writing to flash.

However in the UM10398 (26.5.7) point 3 states that an erase should be executed after 16 writes.
This is kind of confusing, now it this seems like it is contradicting one-another.

Can someone please explain the correct procedure on how to write to flash?

Kind regards,

Harrie

0 Kudos

522 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kralux on Sat Oct 27 00:05:57 MST 2012
Ok thank you. I understand what you mean now. It really is not very well explained in the user manual of the LPC (UM10398).
0 Kudos

522 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gbm on Sat Oct 27 00:02:15 MST 2012
And how do you want to reprogram the hidden redundancy check data, changing its bits from 0 to 1 while changing the primary data from 1 to 0?

That's exactly what you are trying to do.

LPC flash is not a simple one - it cannot be reprogrammed without prior erase.
0 Kudos

522 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kralux on Fri Oct 26 22:11:52 MST 2012
gbm, where do you get the idea we are programming a single word?
This is a spread of a full page of 256 bytes.
Also, this same issue occurs when we reflash half of the firmware (32KB) with a real binary.
I don't think you understood what I wrote above.
0 Kudos

522 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gbm on Fri Oct 26 13:03:41 MST 2012
Wrong, wrong.

The LPC Flash is not so simple. It has some redundancy check mechanism - this is why you can't program a single word.
0 Kudos