I'm toying with the idea to design/implement some kind of EEPROM simulation for the LPC824 and therefore trying to understand the concept of page erases - especially regarding flash wear.
Since the according command only exists in the IAP API and the concept of erasing pages inside a sector seems to contradict the idea of flash, I wonder if the page erase command just performs a sector erase internally but reads/restores all other pages with some embedded 1kB buffer. If this should be the case, consecutive page erasing wouldn't help to reduce the flash wear and I'd go for a 2 sector approach.
So is my assumption true or does the page erase command really only affect the page (and not the whole sector)?
thank you for reply,but where does function Chip_IAP_PreSectorForReadWrite and Chip_IAP_CopyRamToFlash define.
Hi cai bai,
Please download the lpc824 lpcopen code:
LPCOpen Software for LPC8XX|NXP
The Chip_IAP_PreSectorForReadWrite and Chip_IAP_CopyRamToFlash is in the chip lib.
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Volker Oth,
1. We need know the page, sector and write size:
Page size is:64Bytes.
Sector size is : 1KB.
sector size = 16 Page size.
each write is 4Bytes.
each page can have 16 times writes, it is 16*4=64Bytes.
2. Page erase is not sector erase
1 page erase is just 64 Bytes, 1 sector erase is 1K Bytes.
Please note, the User manual for LPC824 have bugs, before you do the page erase, you need to call Prepare sector(s) for write operation command, this command is also used to page erase.
In the same sector, if you just want to erase small part address, you can use the page erase, the other part in the sector won't be erased, I think it will minimize the flash wear.
Wish it helps you!
If you still have question, please let me know!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
hi,i'm stuck in when erase a page by iapCall, code as follow
i just call writePage(0x7C00,buf,4);
and in writePage call prepareSector return success,but call erasePage will be stuck in,
how to fix it,does IRC must enable?
Hi Cai bai,
This is my code for your reference:
void jjtest(void)
{
uint32_t flash_start_sector, flash_end_sector, i;
uint8_t ret;
flash_start_sector = (FLASH_ADDR_TEST - LPC_FLASH_BASE)/FLASH_SECTOR_SIZE;
flash_end_sector = flash_start_sector + 1;
for(i = 0;i < 512; i++)
{
ram_buffer[i] = i;
}
ret = Chip_IAP_PreSectorForReadWrite(flash_start_sector, flash_end_sector);
if(ret == IAP_CMD_SUCCESS)
{
ret = Chip_IAP_EraseSector(flash_start_sector, flash_end_sector);
if (ret == IAP_CMD_SUCCESS)
{
ret = Chip_IAP_PreSectorForReadWrite(flash_start_sector, flash_end_sector);
ret = Chip_IAP_CopyRamToFlash(0x6000, ram_buffer, 512); //write 2 page data
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "write OK\r\n");
Board_UARTPutSTR(debug_output);
}
ret = Chip_IAP_PreSectorForReadWrite(flash_start_sector, flash_end_sector);
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "page1 erase prepare\r\n");
Board_UARTPutSTR(debug_output);
}
// erase page one: 0x6000+0x00 0x180 page
ret= Chip_IAP_ErasePage(0x180, 0x180);//0x181
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "page180 erase OK\r\n");
Board_UARTPutSTR(debug_output);
}
//erase page two : 0x6000+0x40 0x181
ret = Chip_IAP_PreSectorForReadWrite(flash_start_sector, flash_end_sector);
ret= Chip_IAP_ErasePage(0x181, 0x181);
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "page181 erase OK\r\n");
Board_UARTPutSTR(debug_output);
}
//write page one : 0x6000+0x00
ret = Chip_IAP_CopyRamToFlash(0x6000, ram_buffer, 64); //write 2 page data
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "write OK\r\n");
Board_UARTPutSTR(debug_output);
}
//write page two : 0x6000+0x40
ret = Chip_IAP_CopyRamToFlash(0x6040, ram_buffer, 64); //write 2 page data
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "write OK\r\n");
Board_UARTPutSTR(debug_output);
}
// erase page one: 0x6000+0x00
ret= Chip_IAP_ErasePage(0x180, 0x181);
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "page1 erase OK\r\n");
Board_UARTPutSTR(debug_output);
}
}
}
}
You need to use the Chip_IAP_CopyRamToFlash function to write the page data, the following code also for your reference:
for(i=0;i<16;i++)
{
ram_buffer[i]=i;
//write page one : 0x6000+0x00
ret = Chip_IAP_PreSectorForReadWrite(flash_start_sector, flash_end_sector);
ret = Chip_IAP_CopyRamToFlash(0x6000, ram_buffer, 64); //write 2 page data
if(ret == IAP_CMD_SUCCESS)
{
sprintf(debug_output, "write OK\r\n");
Board_UARTPutSTR(debug_output);
}
}
Wish it helps you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
thank you for reply,but where does function Chip_IAP_PreSectorForReadWrite and Chip_IAP_CopyRamToFlash define.
I find you are not this post author, actually, if you have the detail question, you can create your own question post, then we will help you in your own question post directly.
Next time, please create your own question post, thank you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks for the quick reply.
Re #1 I'm not sure what exactly you need/want to know. The page size etc. is stated in the manual and the write size of the "copy ram to flash" command is limited to (power of two) multiples of 64 bytes, so there's not much design choices that could affect my question about page erase.
About the 16 consecutive writes: I intend to write data records of 64 bytes to a page and would only attempt multiple writes in a page used to manage the data pages (i.e. write a marker which is the last valid page).
Still I wonder how consecutive writes or write of only 4 bytes are even possible if the "copy ram to flash" commands only supports sizes of (2^n) multiples of 64 bytes.
I assume the user has to take care that 32bit data other than the current flash content is only written to flash that still has the fill pattern in it (as even writing a single bit from 1 to 0 would most probably create an ECC error).
Or is it also allowed to perform a normal 32bit (aligned) write operation after preparing the sector? If so: how is the flash reprogramming ended in this case (as the manual says the "copy ram ..." command would do this automatically)?
Regarding the page erase: is it really 100% sure that there is no sector erase performed in the background?
There are two things that seem strange:
1) The page erase command only exists for the IAP commands, not for the ISP commands. This made me wonder if some buffer needed for ISP mode is used in IAP to store/restore the unchanged pages.
2) There is a remark in the ISP chapter that says:
To avoid write disturbance (a mechanism intrinsic to flash memories), an erase should
be performed after following 16 consecutive writes inside the same page. Note that
the erase operation then erases the entire sector.
So if there is a physical page erase, why would erasing the whole sector be necessary if the limit of 16 write operation is exceeded within a page? Shouldn't it be sufficient to erase the page?
I'm still pretty far from actually implementing anything, but I would be tempted to measure the time needed for a page erase vs. a sector erase. If the page erase is faster than the sector erase, I guess this would prove that no sector erase is done in the background.
Hi Volker Oth,
I am sorry for my later reply, because I didn't find the updated information.
1) page erase is just exist in the IAP mode, ISP don't have it. If you want to erase the flash in ISP mode, you need to erase the sector.
2) About the remark in the ISP chapter, it is still caused by the ISP mode don't have the page erase function, so it need to erase the entire sector, not the page, ISP don't have the page erase command.
If you want to use the page erase, I suggest you use the IAP function.Please just follow the user manual.
Wish it helps you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
So I tried using the page erase IAP command and it did not seem to work for me. I have two small persistent data sets that must be in their own page in FLASH as one is written when the system is shutting down while latched to a battery (if battery has power), and the other if application configuration info that we do not want to corrupt if the shutdown log is corrupted due to a bad/missing battery.
I use a single function to write the two pages shown below but when I read the data sets back they are all zero. Sorry I modified this function back to what is was when trying to do page erase - the return type was UINT32 to see the status from each IAP operation and I didn't uncomment the first result byte - the result always came back 0.
static void WritePersistPage(UINT08* data, UINT32 page, UINT32 pageAddr)
{
UINT32 result = 0;
iap_entry = (IAP)IAP_LOCATION;
// disable interrupts while we save the Cfg data to FLASH
__disable_irq(); // Disable Interrupts
// 1. Prepare Persist FLASH Sector
iapCmds[0] = 50;
iapCmds[1] = PERSIST_SECTOR; //Start sector 31
iapCmds[2] = PERSIST_SECTOR; //End sector 31
iap_entry(iapCmds, iapResults);
//result = (iapResults[0] & 0xff) << 0;
// 2. Erase Page
iapCmds[0] = 59;
iapCmds[1] = page; //Start page 499
iapCmds[2] = page; //End page 499
iap_entry(iapCmds, iapResults);
result = (iapResults[0] & 0xff) << 8;
// 3. prepare Persist FLASH Sector
iapCmds[0] = 50;
iapCmds[1] = PERSIST_SECTOR; //Start sector 31
iapCmds[2] = PERSIST_SECTOR; //End sector 31
iap_entry(iapCmds, iapResults);
result = (iapResults[0] & 0xff) << 16;
// 4. Copy RAM to Persist FLASH page
iapCmds[0] = 51;
iapCmds[1] = pageAddr; // Destination address
iapCmds[2] = (UINT32)data; // Source data address
iapCmds[3] = PERSIST_WRITE_SIZE; // Size in bytes (64)
iap_entry(iapCmds, iapResults);
result = (iapResults[0] & 0xff) << 24;
// enable the interrupts after saving data to FLASH.
__enable_irq(); // Enable Interrupts
return result;
}
If I give up (as I did) and put each data set in its own 1k sector (what a waste) everything is fine (see below).
static void WritePersistPage(UINT08* data, UINT32 sector, UINT32 dstAddr)
{
//UINT32 result = 0;
iap_entry = (IAP)IAP_LOCATION;
// disable interrupts while we save the Cfg data to FLASH
__disable_irq(); // Disable Interrupts
// 1. Prepare Persist FLASH Sector
iapCmds[0] = 50;
iapCmds[1] = sector; //Start sector
iapCmds[2] = sector; //End sector
iap_entry(iapCmds, iapResults);
//result = (iapResults[0] & 0xff) << 0;
// 2. Erase Sector
iapCmds[0] = 52;
iapCmds[1] = sector; //Start page
iapCmds[2] = sector; //End page
iap_entry(iapCmds, iapResults);
//result = (iapResults[0] & 0xff) << 8;
// 3. prepare Persist FLASH Sector
iapCmds[0] = 50;
iapCmds[1] = sector; //Start sector
iapCmds[2] = sector; //End sector
iap_entry(iapCmds, iapResults);
//result = (iapResults[0] & 0xff) << 16;
// 4. Copy RAM to Persist FLASH page
iapCmds[0] = 51;
iapCmds[1] = dstAddr; // Destination address
iapCmds[2] = (UINT32)data; // Source data address
iapCmds[3] = PERSIST_WRITE_SIZE; // Size in bytes
iap_entry(iapCmds, iapResults);
//result = (iapResults[0] & 0xff) << 24;
// enable the interrupts after saving data to FLASH.
__enable_irq(); // Enable Interrupts
//return result;
}