IAP write - weird problem?

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

IAP write - weird problem?

1,429 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jb111 on Tue Aug 04 23:29:17 MST 2015
Hi,

I am writing a bootloader for the LPC11A13. Ive followed the example code given in the AN10995 documentation. So far it has been working.
[color=#f00][/color]
However during my testing i came across a weird occurrence....

Once an application has been written to flash I do a CRC over the whole application and write this CRC to the last address in the allocated app area (just like the example code). As stated this has worked fine, until I made my application code take up the entire available space (i.e. My whole allocated app area minus the last address which is saved for the CRC).

When the app takes up its full space the CRC write corrupts another memory cell, and the CRC is written just fine.

The IAP call to copy ram to flash returns successful. The IAP call to compare buffers fails.

Another oddity is that if i only copy the second half of my application (i.e. from the middle to the end, to the correct addresses) this issue doesn't arise.




Here is a copy of the memory at the offending location:
        
Before IAP write:
0x00004FF0    -------------   FFFFFEF4  02DC6C00  FFFFFFFF  FFFFFFFF         
After IAP write:
0x00004FF0    -------------   FF[color=#f00]D[/color]FFEF4  02DC6C00  FFFFFFFF  00008054         
     
As you can see the last location the CRC has been writen (correctly), but the cell at 0x4FF0 has also changed.

Here is the function that writes the CRC. As stated it works exceot in this specific case:


uint32_t BOOT_WriteCRC2(uint16_t u16CRC){

uint32_t i;
uint32_t u32Result = 0;
uint32_t a32DummyData[BOOT_IAP_FLASH_PAGE_SIZE_WORDS];
uint32_t *pu32Mem = (uint32_t *)(BOOT_APP_END_ADDR  -      BOOT_IAP_FLASH_PAGE_SIZE_BYTES);



for (i = 0 ; i < BOOT_IAP_FLASH_PAGE_SIZE_WORDS; i++)
{
a32DummyData = *pu32Mem++;
}

a32DummyData[BOOT_IAP_FLASH_PAGE_SIZE_WORDS - 1] = (uint32_t)u16CRC;

int return_val = 0;
BOOT_iap_PrepareSectors(BOOT_APP_END_SECTOR, BOOT_APP_END_SECTOR);
BOOT_iap_CopyRAMToFlash((BOOT_APP_END_ADDR - BOOT_IAP_FLASH_PAGE_SIZE_BYTES), (uint32_t)a32DummyData, 256);
return_val = BOOT_iap_Compare((BOOT_APP_END_ADDR - BOOT_IAP_FLASH_PAGE_SIZE_BYTES), (uint32_t)a32DummyData, 256, 0);
return (return_val);


}

I hope my issue is clear.
I will continue to investigate.
Thanks in advanced.


Labels (1)
0 Kudos
Reply
11 Replies

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by DF9DQ on Fri Aug 07 23:14:00 MST 2015
Transparent to the application, the flash stores a checksum along with each 16-byte flash line. When you write to a flash line for the first time, the flash controller calculates the checksum, and stores it in some extra parity bits associated with that flash line. These parity bits are flash bits themselves, and can never be changed back from 0 to 1 except when erasing the sector/page.

Now your code adds a CRC word to a flash line that has previously been programmed, and so contains a non-empty check field (one or more parity bits are 0). The flash block calculates the check field for the new content of the flash line, and overwrites the parity bits with it. However, parity bits can only flip from 1 to 0, so in the general case the check field is now corrupted.

The checksum is designed to correct a single bit error in the 16-byte block when reading from flash. A corrupted checksum can mistakenly flip (both 0-> and 1->0) any single bit in the 16-byte data field, which is what you observe.

0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Aug 07 01:58:35 MST 2015
BTW:

Did you try to change your data size from 64 to 128 or 256  :quest:
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Fri Aug 07 00:45:30 MST 2015

Quote:
In the main loop i erase before calling iap_write_data() and write iap_overwrite_test().



You are not listening - you can only write to erased sectors. You cannot OVERWRITE. You need to read/modify/write. i.e. read from the flash into RAM, 'overwrite' the data in RAM and then write it back by prepare/erase/copytoflash.

As I said in my other comment, writing just flips '1' bits to '0' bits. It is impossible to flip '0' bits to '1' bits except by erasing a whole sector.
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jb111 on Thu Aug 06 21:41:57 MST 2015
@R2D2 I will try test early next week. I have a LPC1837.
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jb111 on Thu Aug 06 21:40:40 MST 2015

Quote:
Where is the erase?



In the main loop i erase before calling iap_write_data()  and write iap_overwrite_test().

BOOT_iap_PrepareSectors(2,2);
BOOT_iap_EraseSectors(2,2);

//write data to flash keeping last address clear for overwrite
iap_write_data_write(i); //write data to 0x2000 - 0x2100


//copy data into a buffer and append a value, rewrite back to flash.
if (iap_overwrite_test()==10){//if IAP_compare fails, increment error counter
error++;
}


I will have to look at buffer alignment.
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Thu Aug 06 07:13:56 MST 2015
Having had a quick look at your code, I think I see the problem.

iap_overwrite_test is doing:
BOOT_iap_PrepareSectors(2, 2);
BOOT_iap_CopyRAMToFlash(0x2000, (uint32_t)a32DummyData, 256);
return_val = BOOT_iap_Compare(0x2000, (uint32_t)a32DummyData, 256, 0);

Where is the erase?

With flash, a write just flips a "1" bit to a "0" bit. If you have not erased, then you will keep any bits that are already "0" and additionally, set those that are now "0". You cannot write a "1" to a bit that is already "0". 

[EDIT]: P.S. I can't find it in the docs, but I have a feeling that there is an alignment requirement for the data buffer. You have allocated a buffer on the stack, and this may not be correctly aligned.
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu Aug 06 06:38:02 MST 2015
I can't test your sample here, I've no LPC11Axx  :((  :O  :((

Could you repeat this effect with another chip / board?
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jb111 on Wed Aug 05 23:12:36 MST 2015
Cheers R2D2.

I tried it but alas the problem persists....
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Wed Aug 05 21:55:46 MST 2015

Quote: jb111
How do i allocate ram for the ROM? or where can i find out about it?



User manual ?


Quote:
20.5.2.10 RAM used by IAP command handler
[color=#f00]Flash programming commands use the top 32 bytes of on-chip RAM[/color]. The maximum stack usage in the user allocated stack space is 128 bytes and it grows downwards.



FAQ:

https://www.lpcware.com/content/faq/lpcxpresso/reserving-ram-iap


0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jb111 on Wed Aug 05 20:39:29 MST 2015
Thanks nickich for the reply.

Ive set a breakpoint and it seems that the data (a32DummyData)  isnt corrupt. It has the correct values, before and after the write. Also the IAP compare command returns a failure.

How do i allocate ram for the ROM? or where can i find out about it? I havent run out of ram....




I have managed to recreate the problem, so I have attached the project, if this helps anyone's. There is a description of my findings so far.
0 Kudos
Reply

1,311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by nickich on Wed Aug 05 08:12:39 MST 2015
I guess the data is corrupted in the ram (in a32DummyData), before writing it to flash. Can you put a BP and see if it is OK before and after the CRC write up.
Also if you use the ROM make sure you allocate the ram for it.
0 Kudos
Reply