element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi Projects
  • Products
  • Raspberry Pi
  • Raspberry Pi Projects
  • More
  • Cancel
Raspberry Pi Projects
Blog Adding Low-Cost Flash Memory Storage to Microcontrollers
  • Blog
  • Documents
  • Events
  • Polls
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi Projects to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: shabaz
  • Date Created: 11 Feb 2023 8:00 PM Date Created
  • Views 23573 views
  • Likes 19 likes
  • Comments 10 comments
  • rpiintermediate
  • SPI Flash
  • pico
  • spi
  • memory
  • pico_eurocard
  • flash
  • pico-eurocard
  • pi pico
Related
Recommended

Adding Low-Cost Flash Memory Storage to Microcontrollers

shabaz
shabaz
11 Feb 2023

Table of Contents

  • Introduction
  • Connecting Flash Memory to Microcontrollers
  • Reading/Writing to Flash Memory
  • Using a File System
  • Trying out the Code
  • Summary


Introduction

There is often a need to store data in some form of non-volatile memory. It may be just a few bytes or much more!

I came across a situation with the Pi Pico a while back, where I was using the Pico’s Flash memory chip (which contains the application firmware for whatever you’re using the Pico for, but it also often has some spare space) to store my own data. Occasionally, there was corruption, which presumably occurred if the device was being power-cycled at the same time as the memory was being written. I didn’t explore that further at the time but have been meaning to consider alternative solutions, that might work with the Pico and other microcontrollers too. At that time, I swapped to using a micro SD card, which is fine but can be overkill if the card doesn’t ever need to be removed.

Recently another requirement came up, which was to be able to read memory chips desoldered off the boards from other products.

This project was the result, of a mash-up of several separate requirements!

image

This blog post discusses three main points:

  1. How to connect cheap Flash memory to a microcontroller (I’ll be using the Pi Pico)
  2. How to read/write Flash memory contents
  3. How to use a file system to read/write files to the Flash memory


I also recommend checking out work by Jan Cumps and by Michael Kellett, who have been investigating high-quality C++ software techniques for working with SPI Flash, and working with PSRAM, respectively.

My needs were a little different as mentioned, so I won’t cover other memory types, and my code is pretty basic, it blocks during SPI communication, only allows one instance, and is not thread-safe, so it’s not all that fantastic (unless these limitations do not matter for your app!). There may also be bugs since my testing of it is minimal. Please fix it if you spot a bug!

Connecting Flash Memory to Microcontrollers

Flash memory is available in various packages, often surface-mount, but also through-hole. This blog post will only consider typical 8-pin SPI NOR Flash memory.

Only six wires need to be connected to the microcontroller. The datasheet for the Flash memory should be checked, to confirm that it is of the same pinout and that it supports the logic voltages involved (3.3V in the case of the Pi Pico).

image

As can be seen, the circuit is trivially simple.

(Note: you could optionally wire the WP# and HOLD# pins (pins 3 and 7 respectively) to GPIO and then set them high, and on some memory ICs it is OK to leave pin 7 disconnected, but it is not recommended to wire just the WP# pin to GPIO and leave pin 7 disconnected, because that might not be supported on all ICs.

The simplest most compatible way is to either (a) wire up the chip as shown in the diagram above, or (b) wire both WP# and HOLD# to GPIO and set them both high, or (c) wire up the chip as shown in the diagram above and wire WP# to GPIO and set it high. Check the datasheet for the specific memory IC if you're unsure, but I believe the diagram shown above will be compatible with all memory ICs with this pinout).

Due to the component shortage, one might be forced to use surface-mount memory parts, but fortunately, the 8 pads are very widely spaced usually, and so they are quite easy to hand-solder.

You can also get flip-top sockets for them if you’re planning to program a lot of chips of a specific size. I got such a socket from AliExpress.

image

Photo of a few memory chips for size comparison (they can be a lot smaller! but these sizes are easy to hand-solder):

image

The bottom of the blog post has downloadable files for a test board for 8x6mm WSON-8 chips.

image

They are pretty large for SMD packages, with 1.27 mm spaced pads, so a socket isn’t essential if you’re just experimenting. The particular memory chip I used for testing was MX25L12833FZ2I-10G  

image



The SIL header pins on the right side can directly plug into the Pico Eurocard, or you could just use jumper wires to connect it to any microcontroller board.

Reading/Writing to Flash Memory

I really like Mbed, so I searched around and found some Mbed code developed by ARM, called spif-driver. It neatly contains an entire SPI Flash memory driver in a single file (plus a header file) so I took that, and made a few slight modifications to get it working with the Pi Pico. The modifications remove references to the SPI handling in Mbed, replaced with SPI functions from the Pi Pico C/C++ SDK instead. If you’re using a different microcontroller board, it would be very easy to do a diff and see what changes I made and replace with the SPI functions for your microcontroller.

The main.cpp code can be examined to see how to use spif-driver (just search for the text ‘spif’). The commands are simple, for instance to erase a block of Flash:

spif.erase(addr, len)

where addr is an address (must be a value of 0, 4096, 8192, 12288 etc) and len must be a value of 4096, 8192 and so on.

To write memory, use the following command:

spif.program(buffer, addr, len);

where buffer contains the data to write, and addr is any value from 0 to 16777215 (for a 128 Mbit Flash, which equals 16 Mbytes of memory), and len is any value from 1 upwards.

To read memory, use this command:

spif.read(buffer, addr, len);

where buffer is the destination for the read data, and addr and len are the same as for spif.program().

Using a File System

The spif-driver mentioned above is great for directly reading or writing to specific locations on the Flash chip, however, sometimes a file system will be handy. I searched around and found a nice project called littlefs which implements features such as wear leveling, and some power loss resilience, so that if power is lost during a write operation, hopefully the file system won’t be corrupted (obviously, one should still take precautions, such as limiting the time that data is written, and perhaps consider power failure detection and backup, and write your code to recover from unexpected file content).

The littlefs code requires an interface to the underlying memory, and this is implemented in the lfs_adapter.cpp file. It merely calls the appropriate spif-driver functions.

To see how to use it, search the main code for lfs (short for little file system). You’ll see commands such as lfs_mount(), lfs_format(), lfs_file_open(), lfs_file_write(), lfs_file_read() and so on. The code example creates two files, one which contains the number of reboots of the system, and the other which contains an IP address (it is an example configuration file).

Trying out the Code

To quickly try the code without building it, there is a prebuilt firmware file that can be transferred to the Pico. There are screenshots further below of what to expect to appear over the USB Serial with the prebuilt firmware.

Otherwise, to build the code, assuming you have GitHub capability installed, type the following (I did this in a Windows terminal, but Linux would work fine too; I did this from a C:\development\pico folder:

git clone https://github.com/shabaz123/flashtester.git
cd flashtester
git clone https://github.com/littlefs-project/littlefs.git

Next, I started up CLion (see this web link to see how to configure it:  Using CLion for Easier Coding with Pi Pico and C/C++   or you could use Visual Code if you prefer).

Click on Open, then select the C:\development\pico\flashtester folder and the project will load up and you’ll see an Open Project Wizard. Nothing needs to be done here, except one line needs typing, in the Environment box:

image

Type in the box:

PICO_SDK_PATH=c:\development\pico\pico-sdk

(That’s if your Pico SDK is installed there; otherwise, type the correct location).

Click on OK, and you’ll see the project all loaded into CLion. You can explore the project files just like with any development environment.


image

The code can be built by clicking on the hammer icon.

image

The binary file called flashtester.uf2 will be in the C:\development\pico\flashtester\cmake-build-debug folder, all ready for running on the Pico.

Serial terminal software (such as PuTTY or SecureCRT) can be used to see what the code does. The code will dump a lot of debug so that things like wear leveling can be examined. In a real project, the debug should be disabled.

The debug will show the size of the Flash memory chip:

image

You’ll also see how the file system writes and reads two files and displays the contents:

image


To develop code for the Pico faster, then PicoProbe can be used. The CLion web link mentioned earlier shows how to use PicoProbe. If you’re using Visual Code, then check out this link: Debugging the Raspberry Pi Pico on Windows 10  

Summary

This blog shows how to connect 8-pin SPI Flash memory to a microcontroller, and how to read and write directly to the memory, and how to use a file system intended for providing some resiliency for constrained embedded systems.

Thanks for reading!

wson8_adapter_rev1_gerbers.zip

  • Sign in to reply
  • shabaz
    shabaz over 2 years ago in reply to Jan Cumps

    Jan discovered the issue! There's a function that is supposed to handle SPI MISO/MOSI operations (at the low-level, i.e. in the spif-driver) where during MISO read operations, unallocated memory was being simultaneously sent on the MOSI line. I've coded a fix (it was simple) and uploaded to GitHub, and me and Jan have tested it on the two memory chips we have.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 2 years ago in reply to DAB

    Hi DAB, thanks!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 2 years ago

    Nice build.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • genebren
    genebren over 2 years ago

    Nice write-up!  I will have to bookmark this one and come back to as a reference.  Thanks for sharing!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 2 years ago in reply to shabaz

    Indeed. My Flash IC is from an existing Cisco device, and has protection against overwrite set.
    It's possible to remove that protection, via SPI commands and correct application of the Write pin.

    My device is at the moment fully protected after leaving the Cisco premises:
    image

    This is not an obfuscation measure. It just assures that no parts of the flash are accidently changed. Once you follow the right sequence of actions, you can enable updates again.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube