This question already has an answer here:
Will an SPI flash memory chip have the same issues with non-atomic write operations as a dsPIC's internal EEPROM? 4 answers
A while back I had some intermittent trouble with the internal EEPROM of a dsPIC. Every so often, some value in the EEPROM would be found zeroed out on power-on. I tracked the problem down to when the chip lost power after the erase step of the write cycle, but before the write had completed. It was all about the timing of the power-down relative to the firmware execution, which was (in normal operation) random. I solved this by adding a buffer section to my EEPROM, to ensure that an incomplete write-cycle could be completed on restoration of power. I had to turn EEPROM writes into an atomic operation.
(For further detail, my buffering technique defines an area of persistent memory that consists of three fields: address to write to, data to be written, and a READY flag. A "write" consists of four steps: write to buffer, set READY flag, write from buffer, clear READY flag. On power-up, you check the READY flag. If it's set, execute whatever's in the buffer. This worked well in internal EEPROM.)
Now I'm using a different dsPIC without internal EEPROM, and I'm trying to use an external EEPROM chip to store persistent data. I'm wondering if I should have similar concerns. Should I be worried that my external EEPROM chip will power down mid-write and lose data, and write a fix for this in my firmware like I did for internal EEPROM? Or does the chip itself guarantee atomic write operations?
The chip cannot guarantee atomic writes - if the power goes away while it is writing (or erasing), there's nothing it can do about it.
Of course, the chip designers could implement some kind of holding store (as you have done) - but that adds cost that other users won't want to pay. Also, what happens if the power goes down whilst writing to the buffer instead of the "real" memory?
For reliable recovery of data from EEPROM there are a number of things that can be done. Let's consider for example storing an occasional counter value into the persistant storage of the EEPROM. You have to take into account both the power loss problem we are discussing here and also the write endurance characteristics of the serial EEPROM.
It is OK to use the EEPROM in a read / write mode (given that you have time to do it) as long as you make sure that you can assure that the wear out endurance for the memory cells will not be used up in the length of life of the product. As for example I have done product designs with external EEPROM such as 93C46 connected to microcontroller via 3 port pins. I have used certain locations in the EEPROM to accumulate information such as accumulated count or total time passage. I have done calculations using the endurance numbers for 93C46 and have found that if you want to ensure that a product can last for 10 years then on average you can permit the EEPROM location to be updated once each 10 minutes.
With this in mind I typically design my software so that the microcontroller maintains the current count or time accumulator in local RAM and then a timer function provides for a "once every 10 minutes" update to copy the RAM locations into the EEPROM. For many applications this simple solution is more than adequate since the occasional loss of 10 minutes of accumulation is not particularly critical.
If the count maintenance needs to be more critical however you can then arrange to have the microcontroller manage its own power off and force a final update of the EEPROM locations from RAM locations just before powering itself off.
And if even more critical maintenance is required you can arrange to have an early warning power fail interrupt that will permit the software to force an update to the EEPROM just before the microcontroller looses its blood supply of electrons.
Now there is an even more important subject to consider in using an EEPROM to maintain nonvolatile counters. This relates to how you manage the process of maintaining reliable storage of the accumulators when the power goes off just as you are in the process of writing to the EEPROM. I have addressed this problem over the years, in many projects, as follows:
Lets take the 93C46 chip as an example. It has 16 bit locations in it. I typically use 2 locations and make my accumulator be 24 bits and then compute a simple XOR type of CRC over these three bytes and plug that into the 4th byte of the 32 bits of the pair of EEPROM locations. Then when the EEPROM is written the accumulator+CRC is written to the EEPROM in two different places. (I.E. the accumulator is redundantly stored into the EEPROM). Also make sure to write your software so that write of one copy of the accumularor+CRC is completely written before the other is started. It is also a good idea to interpose a delay of some number of milliseconds between the pair of write operations.
Then at next power up when I initialize the RAM based copy of the accumulators from EEPROM I use the following concept. I read the first copy of the accululator+CRC from the EEPROM and I check the CRC. If it is correct I then use the read value of the other 24 bits as the value to write into the RAM locations. If the check of the first location proves to fail I then go read the second copy and check it. If it is OK then that becomes the value plugged into the RAM locations. If both have failed then I apply a default value to the counter in RAM such as zero or "full" count. ("full" count would apply to cases where the EEPROM location is being used to keep track if how many times are left to allow something to happen....[such as how many more boxes are allowed by before the microcontroller posts a maintenance request...etc etc].