Search code examples
arduinoembeddedlow-memory

Is it possible to use a SPI flash chip with a arduino (Atmega328p)


Is it possible to use an SPI flash chip with a minimum sector erase size of 4KB with an Atmega 328p (2KB of internal RAM)?

The problem I'm seeing: in order for data to be written to the flash, a page must be erased. If you want to update data inside a sector you first need to read all the pages inside the sector, save them off the chip, erase the sector and write the pages in order back with your changes.

But a sector of 4KB can't be saved inside a 2KB RAM, so what solutions do other people use for this situation? Because I have seen Arduinos be used in this setup but couldn't determine what their solution was.

(Arduino is just an example of a small microcontroller in this question)


Solution

  • You can simply use a dual-redundant page scheme. Given two 4kb pages organised thus:

     Page A           Page B
    +------------+   +------------+
    | Sequence A |   | Sequence B |
    !~Sequence A |   !~Sequence B |
    +------------+   +------------+
    |            |   |            |
    |            |   |            |
    | Data A     |   |  Data B    |
    |            |   |            |
    |            |   |            |
    |            |   |            |
    |            |   |            |
    |            |   |            |
    |            |   |            |
    |            |   |            |
    +------------+   +------------+
    

    Initially you write Data A and set Sequence A to zero its inverse ~Sequence A. On start-up you inspect each page's sequence number and set the page with the highest valid sequence number (valid when sequence ^ ~sequnece == 0xff) as the current read page, and the other as the current write page.

    When you update the data, you erase the current write page, write the data area, then set the sequence number to the sequence number of the read page plus 1 (modulo 256), and set its inverse. Then swap the current read/write pages. When updating you can copy the data from one page to the other without buffering the entire page, and modify just the part you intend to change.

    If there is a power failure or reset during a write, the page sequence number will not be valid as it is written last and both the sequence and inverse sequence write must complete, so the partially written data will be invalidated and the previous valid page will be selected on start-up.

    When selecting the current active page, you of course have to deal with the wrap-around (i.e. when the sequence numbers are 255 and zero, zero is the newer).

    This scheme is suitable for data that will be read often and written seldom. The nature and frequency of your NV read/write cycles will dictate a suitable mechanism since different solutions would be appropriate for sequential logging or non-volatile event counters.