Flash operations (Read , write and Erase ) and FEE concept with clear Example :
First of all, we need to know our way around the different entities on a flash chip "package" the?die, the?plane, the?block?and the?page :
The important bit here is that?program operations (i.e. writes) take place to a page, which might typically be 8-16KB in size, while erase operations take place to a block, which might be 4-8MB in size. Since a block needs to be erased before it can be programmed again (*sort of, I’m generalizing to make this easier), all of the pages in a block need to be candidates for erasure before this can happen.
Program / Erase Cycles
When your flash device arrives fresh from the vendor, all of the pages are “empty”. The first thing you will want to do, I’m sure, is write some data to them – which in the world of memory chips we call a program?operation. As discussed, these program operations take place at the page level. You can then read your fresh data back out again with?read?operations, which also take place at the page level.?
Where it gets interesting is if you want to?update the data you just wrote. There is no update operation for flash, no undo or rewind mechanism for changing what is currently in place, just the?erase?operation. in that you can continue to turn?the dials and make white sections of screen go black, but you cannot turn black sections of screen to white again without?erasing the entire screen.?An erase operation on a flash chip clears the data from?all pages in the block, so if some of the other pages contain active data (stuff you want to keep) you either have to copy it elsewhere first or hold off from doing the erase.
In fact, that second option (don’t erase just yet) makes the most sense, because the blocks on a flash chip can only tolerate a limited number of program and erase options (known as the?program erase cycle?or?PE cycle?because for obvious reasons they follow each other in turn). If you were to erase the block every time you wanted to change the contents of a page, your flash would wear out very quickly.
So a far better alternative is to simply mark the old page (containing the unchanged data) as INVALID and then write the new, changed data to an empty page. All that is required now is a mechanism for pointing any subsequent access operations to the new page and a way of tracking invalid pages so that, at some point, they can be recycled.
So a far better alternative is to simply mark the old page (containing the unchanged data) as INVALID and then write the new, changed data to an empty page. All that is required now is a mechanism for pointing any subsequent access operations to the new page and a way of tracking invalid pages so that, at some point, they can be recycled.
Flash EEPROM EMULATOR :
There are probably many different algorithms to accomplish EEPROM emulation without forcing a lot of unnecessary writes. The main concept is like a ledger (except values don't depend on previous values). The data set or a variable has many "records" in the ledger. When a new value is written, the old value must be invalidated.
For example, you can invalidate the old value by writing some magic value which means "that record is invalid". Then, a new record can be created. Looking up a value means reading through the ledger to find the current record. All invalidated records can be ignored. Flash pages can be erased when full (the values must all be invalid or be migrated to a new flash page before erasing).
concrete algorithm example:
Let's say I have a data set of 6 bytes. I will devote 2 flash pages to emulated EEPROM for my 6 byte data set. Make the following assumptions:
Flash page header
I'll start my flash page with some sort of header to indicate that I am actively storing data there (or not). Let me use 4 bytes at the start of the flash page which indicate one of the following conditions:
Record header
For each record, I will start with a header also. Let me use 2 bytes, indicating one of the following:
Flash pages start erased
Flash Page #0
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Flash Page #1
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
领英推荐
System initialization
After detecting that the EEPROM data has not been initialized, I will begin by initializing my data set to all 0s:
Flash Page #0
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55FF0000 // Record slot #0 (current value: 0x55FF header.)
00000000
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Flash Page #1
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Notice that bytes 2-3 were not written and remain 0xFFFF. When this flash page fills up and I start a new flash page, I will write 0x5555 over bytes 2-3.
The record header essentially works the same. Byte 1 of the record #0 header remains 0xFF indicating that it is the current record (because byte 0 is 0x55).
Write the value 0xDEADBEEFCAFE
In this order:
Order is important for recovery from spurious resets (this is similar to a journal in a file system).
Flash Page #0
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55550000 // Record slot #0 (now invalid: 0x5555 header.)
00000000
55FFDEAD // Record slot #1 (current value: 0x55FF header.)
BEEFCAFE
...
Flash Page #1
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Write the value 0x12345678ABCD
Flash Page #0
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55550000 // Record slot #0 (now invalid: 0x5555 header.)
00000000
5555DEAD // Record slot #1 (now invalid: 0x5555 header.)
BEEFCAFE
55FF1234 // Record slot #2 (current value: 0x55FF header.)
5678ABCD
...
Flash Page #1
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
The current page is full
This is what the pages look like when the current page (Page #0) is completely full (the current value is 0xAAAA5555BBBB):
Flash Page #0
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55550000 // Record slot #0 (now invalid: 0x5555 header.)
00000000
5555DEAD // Record slot #1 (now invalid: 0x5555 header.)
BEEFCAFE
55551234 // Record slot #2 (now invalid: 0x5555 header.)
5678ABCD
...
55FFAAAA // Final record slot (current value: 0x55FF header.)
5555BBBB
Flash Page #1
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Notice that flash page #0 is not yet invalidated (the current record is the last record in flash page #0).
Write the value 0x80009000ABCD
The next value must go into flash page #1. After writing the new record in flash page #1 and creating the page header to indicate that flash page #1 now contains the current value, we invalidate flash page #0 (write 0x55 to bytes 2-3) and the last record in flash page #0 (write 0x55 to the last record's header byte 1).
Flash Page #0
55555555 // Page Header (page is all now invalid: 0x55555555 header.)
55550000 // Record slot #0 (now invalid: 0x5555 header.)
00000000
5555DEAD // Record slot #1 (now invalid: 0x5555 header.)
BEEFCAFE
55551234 // Record slot #2 (now invalid: 0x5555 header.)
5678ABCD
...
5555AAAA // Final record slot (now invalid: 0x5555 header.)
5555BBBB
Flash Page #1
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55FF8000 // Record slot #0 (current value: 0x55FF header.)
9000ABCD
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Now, flash page #0 is completely invalid, and the new page is Flash page #1.
Flash page #0 is garbage collected (erased)
Finally, flash page #0 can be erased when the system finds it convenient.
Flash Page #0
FFFFFFFF // Page Header (unused: 0xFFFFFFFF header.)
FFFFFFFF // Record slot #0 (unused: 0xFFFF header.)
FFFFFFFF
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Flash Page #1
5555FFFF // Page Header (current value here: 0x5555FFFF header.)
55FF8000 // Record slot #0 (current value: 0x55FF header.)
9000ABCD
FFFFFFFF // Record slot #1 (unused: 0xFFFF header.)
FFFFFFFF
...
Record lookup, real-world complexities
In the real world, the data set would be larger and more complex than a single 6-byte chunk. There are many complexities I glossed over. This is a really simple example, but it would work. It illustrates how EEPROM can be emulated in flash without excessive erasing by creating a ledger of value records.
To look up the current data set values, find which flash page is current (one and only one flash page should have the header 0x5555FFFF). Then, read through the records in that page sequentially until finding the current record (one and only one record should have record header 0x55FF). Errors could invalidate the header configuration, potentially leading to multiple pages and/or records which appear to be current. A real application would need to handle such errors.
Embedded software engineer @ Cairomotive || Functional safety || ISO 26262 || IEC 61508 || Classic AUTOSAR
1 年It really helped me and many many thanks Happy to see this as a first proposal from google search engine
Software Developer | AI Engineer | Data Scientist
3 年Very informative Thanks
Senior Test Manual and Automation Engineer| ISTQB?
3 年Thanks for your efforts ??