hi,
i would like to know the write and erase times for a sector for a 89V51RD2 microcontroller. if you have this info please share it.
Also i see from the datasheet that the write/erase cycles are 10000. is this for one sector or for the entire block? the origin of this question is can the lifetime of the device be calculated as
lifetime of flash = 10000 * number of sectors ?
i will use one sector at a time and then when this sector is full erase and begin writing again to this sector. when the number of write/erase cycles are over then i move over to the next sector. will this work?
any inputs will be helpful. thanks in advance.
write time is especially important for me as i want to store some data if there is a power failure.
Consider what might happen if you lose power while you are in the process of writing to flash.
Best to use at least two sectors and keep a record of last good data. So if power fails during an update, you can revert back to the previous good copy.
Yes, the rotation between sectors means that there is some trace of sequence numbers
So the sectors may contain (after a power failure in the middle of an update)
SEQ CRC 1017 OK 1018 OK 1019 OK 1020 OK <= so this is the newest surviving flash sector broken <= some failure (power, bug, lockup, broken flash sector) during this write. 1012 OK 1013 OK 1014 OK 1015 OK 1016 OK
And with 10 sectors in circulation, a counter of 1020 would indicate that each sector has seen about 100 rewrite cycles which would be 1% of what the 10k from the specification.
Rotating through the sectors is a winner when it comes to availability of redundant data.
This rotation also means that if the unit actually manages 20k cycles/sector then the unit will stay alive for twice as many total cycles. But running 10k/sector and then start the next sector would mean the code has already come to the roads end when it has done 10k on the last sector - it would take extra code to get it to return to the first sector and try to push from 10k to 11k.
Next thing - the count isn't absolute but the retention gets worse as they get older. Wearing a single sector at a time means that even a new unit will spend time depending on a sector with a very high wear level before it switches to a brand new sector.
But running 10k/sector and then start the next sector would mean the code has already come to the roads end when it has done 10k on the last sector - it would take extra code to get it to return to the first sector and try to push from 10k to 11k. sorry but i didnt get this part. i would not come back to the first sector after it finishes the specified number of writes. there would be no question of pushing it from 10k to 11k?
and i did get the point of rotating through the sectors...it makes my life a little difficult though :)...i have to code all of these things in....although i suppose i might find some ready code for it on the net.
well i will initiate the write after i detect the powerfail so i think there is no question of a powerfail during the writing to flash.
It's trivial to rate code.
How to select which sector to use:
save_nonvolatile() { mon_debug("saving nonvolatile data."); build_sector_data(sector_data); for (;;) { sequence_count++; patch_sector_data_with_sequence(sector_data,++sequence_count); eval_crc_for_sector(sector_data); sector_num_to_use = sequence_count % num_sectors; program_sector(sector_num_to_use,sector_data); if (verify_sector(sector_num_to_use)) break; mon_debug("failed saving to sector %u - stepping to next.",sector_num_to_use); } }
Potentially you could keep a list of known broken sectors to instantly skip, but that optimization might not be needed.
And trivial to find current sector too by reading all sectors, while ignoring all sectors with invalid crc. The highest sequence count found represent the surviving sector with newest data. sequence number+1 modulo sector count represents the next sector to use. Sequence number divided by number of sectors represents the amount of wear - divide by the rated wear count and you get how much of total life expectancy you have consumed.
So your life is less complicated if you rotate through the sectors. If you wear one sector at a time, then you need to add lots of "interesting" backup functionality for trying to recover after a sector failure. And remember that if sector n fails after 9000 writes, then sector n-1 contains 9000 writes old information which might represent days, weeks or months old data. With a continuous rotation around all sectors, then the previous sector is just one write old. So you might just step back in time 10 minutes by having to go back to the previous sector to recover.
Your variant with a sector at a time really is extremely complicated. You would need to add own ECC (error correcting code) in your sector data to give your code a chance to recover data even if there are a number of bit errors in the written sector data. And that ECC would still not help you if you lost the power just after you erased the sector but before you had time to write down the updated data. With a rotation scheme, a power loss at that time doesn't matter much becuase you haven't erased your previous save. So you have a safe restore point.
My solution is KISS - keep it simple stupid. Easy to implement and with excellent recovery options.
Your solution might sound KISS but is hard to implement and even when well-implemented still leaves situations you can't recover from without backing in time with a huge amount.
Remember that flash writes requires a constant voltage - so you need to catch power failures by looking at some voltage on the outside of your regulator. And have large enough capacitors that the regulator can supply a valid voltage until you are done.
Not only that - the capacitors must hold for long enough that they support a write failure in which case you might have to try a second time by maybe failing your current sector and move to the next sector. Or you might step back in time with on average 5k saves but potentially a full 10k saves.
you are overcomplicating it use a struct
x x x cksm used
to write after start/power fail: start from the beginning, the first struct where used is ff is where you write then keep a RAM pointer till next fail
to read after powerfail finf the first where used is ff go one back, if cksm is OK, use it, if not, go one more back
i have done this many times, the abive just works
thanks for your reply...this seems to be a good method. i will use it.
ofcourse i will detect the powerfail as early as possible.
regarding the capacitance values i need to know the write time for calculating the capacitance values. and the current consumed by the microcontroller during the write. this value i can get by monitoring the microcontroller for some time during operation but i am still stuck on the write time.
regarding the write time i thought i could calculate it roughly by flashing a hex file of a know size using the FlashMagic SW. i know that this uses isp routines while my application will use iap routines but the time for writing a byte to the flash would be the same?
thanks for your inputs. your inputs have helped me a lot!
Normally, writes are fast. It's normally the erase to make the flash sector ready to accept data that takes lots of time. Which means that having one sector pre-erased can reduce your power needs - but if that write fails you lost your margin for a second attempt.