Electronic – arduino – Datalogging on serial flash memory

arduinoflash

I am working on a datalogger that writes positions from GPS to serial flash W25Q64FV. I plan to write GPS data every second. I have couple of questions:

  1. With this flash memory it is possible to write to any position from 1 to 256 bytes at once (page). Specification says the memory has 100,000 write/erase cycles. Is it counted per page or per byte? So if I write one byte at address X and then later another one at address X + 1 (but the same page) does it mean that I have only 99.998 writes left to that page? I would say no, but for sure I am asking. What if writing one byte internally rewrites complete page?
  2. How to persistently keep address of last written byte? I could write it to Arduino's EEPROM on every update, but it also has "only" 100,000 write cycles so this would be reached much sooner. Other possibility could be to scan all written memory and look for empty byte(s) but this can probably take a while. Or maybe just to have some bitmap in the flash header marking full pages and I would only scan the last one. Any other suggestion?
  3. Is there any special purpose of erasing blocks or complete flash memory? Can't I just write to memory in round-robin way? If I delete file on my HDD it won't write zeroes to all its bytes so couldn't it be same with flash?

Best Answer

First of all, the way flash works, in general, is that a write command can only change bits from one to zero. To return bits to one, you must erase an entire erase block. Therefore, you cannot just "write to it like a hard drive". On most flash devices, multiple writes can be made to the same block or even the same byte, again as long as you are only changing ones to zeros. (There are some flash devices where the manufacturer recommends against multiple writes to the same block, but this is rare.)

To answer your specific questions:

1) In general, the endurance is based on erase cycles on each block. You can write individual bits (to zero) as much as you want, but doing an erase to return bits to one will wear down those bits of flash.

2) One way is to use the first byte of each record as a status indicator. It starts, after erasure, as 0xFF. When you start writing the record, you write 0x7F to that byte (zero the high bit). Once you complete writing the record, you write 0x3F to that byte (zero the next highest bit). To mark a record as deleted, you write 0x00 to that byte. All of this takes advantage of the fact that you can always turn a bit from one to zero.

Later, when you're reading records, you only look at records with 0x3F in that byte. 0x7F means that the record writing was interrupted (power fail/reboot) and is invalid. Once an entire erase block has only 0x00, 0x7F and 0xFF blocks, it can be erased.

By the way, you can keep a map of used/free blocks in RAM so that you only have to scan when booting up.

3) See the top of this posting.