Embedded HandbookApps
All sections › VI. Practice
STM32F103, STM32F407 · level intermediate · 12 min read
Open in the interactive handbook

41. External memory: SPI Flash, NAND, SD

A microcontroller has little built-in Flash: 64 KB on the BluePill, 1 MB on the F407 — and all of it is taken by the program. As soon as you need to write logs, store images for a display or accumulate measurements, you have to add external memory.

Terms used in the documentation

Term Meaning
page program writing one page
sector / block erase erasing a sector / a block
write enable latch the latch that permits writing
busy flag the flag set while an operation runs
endurance the number of rewrite cycles a cell survives
data retention how long the data is kept
wear levelling spreading wear evenly over the memory
bad block management handling faulty blocks
error correction code (ECC) a code that corrects bit errors
memory-mapped mode the memory appears as a range of addresses

41.1 What there is

Type Capacity Read Write Endurance What it is good for
EEPROM bytes to kilobytes byte by byte byte by byte 1 million settings, counters
FRAM kilobytes byte by byte byte by byte, instantly 10¹² places that are written constantly
NOR Flash 1–32 MB byte by byte in pages 100 thousand logs, images, firmware
NAND Flash 128 MB to GB in pages in pages 1–100 thousand lots of data, cheap
SD / eMMC gigabytes in blocks in blocks depends removable medium, ready-made file system

What people casually call an "SPI flash" — chips like the W25Q or AT45 — is NOR, not NAND. The difference is fundamental.


41.2 NOR versus NAND

NOR NAND
reading any byte directly only whole pages
erase unit 4 KB sector 64–256 KB block
bad blocks none present from the factory, this is normal
error correction not needed mandatory
price per megabyte higher lower
typical capacity up to 32 MB from 128 MB
driver complexity low high

The main practical difference. In NAND some blocks do not work straight from the factory — the manufacturer documents this and marks such blocks with a special byte. The driver must find them, skip them and keep a table of replacements. On top of that, bits in NAND flip spontaneously, so you need an error correction code: usually 1 to 8 bits for every 512 bytes, and on a 2 KB page — up to 32 bits. A NAND with an SPI interface often has the correction and bad block handling built into the chip — that is easier to start with if you do need NAND.

The conclusion: do not start your own project with NAND. If you need megabytes, take a NOR over SPI; its driver can be written in an evening. If you need gigabytes, take an SD card, where all this machinery is already hidden inside the card by its own controller.

NAND is justified when you need a large capacity in a small package specifically and you have a ready-made translation layer — for example, file systems designed specially for it.


41.3 How to connect it

Interface Speed Where it exists Notes
SPI up to 2.25 MB/s on the F103 (18 MHz), up to 5.25 MB/s on the F407 (SPI1, 42 MHz) everywhere four wires, as simple as it gets
Quad SPI up to ~50 MB/s F412, F446, F469 and higher memory mapping: the contents look like an ordinary array
SDIO up to ~24 MB/s high-density F103, F4 a four-bit bus for SD
FSMC / FMC tens of MB/s F103xC/xD/xE in 100- and 144-pin packages, F405/F407 (FSMC), F42x and F446 (FMC); the F401 and F411 do not have it a parallel bus: SRAM, NOR, NAND, SDRAM

⚠️ The BluePill has neither SDIO nor FSMC. The STM32F103C8 is "medium density"; these controllers appear only on the larger chips of the line (xC/xD/xE). So on the BluePill you are left with SPI — and as a rule it is enough.

The memory-mapped mode of Quad SPI is worth knowing about separately: the controller shows the contents of the external flash as an ordinary range of addresses. You can read from there as from an array, and even execute code — a technique used to extend program memory when the built-in memory is not enough.


41.4 How an SPI NOR Flash is organised

Three levels of organisation, and they are easy to mix up:

Unit Size What you can do with it
page 256 bytes write it with one command
sector 4 KB the smallest amount that can be erased
block 32 or 64 KB erase it faster than sector by sector

The key rule of flash memory: a write can only turn ones into zeros. Going back is possible only by erasing, and only a whole sector. So "rewriting one byte" physically means: read the sector into RAM, erase the sector, change the byte, write the sector back.

Rewriting one byte in the W25Q128FV: the 4 KB sector is read with command 0x03 into a RAM buffer — 4 KB of the 20 on the F103C8, the sector is erased with command 0x20 in up to 400 ms, the byte is changed in the buffer, the buffer goes back with sixteen Page Program 0x02 commands of 256 bytes, each preceded by Write Enable 0x06

This also gives the approach to logs: write sequentially, never going back, and erase sectors as needed.

The order of any write operation:

  1. send Write Enable — otherwise the chip silently ignores the command;
  2. send the command itself with the address and data;
  3. wait for the busy flag in the status register to clear.

The write enable is cleared by the hardware automatically after every operation, so it is set before each one, not once at startup.


41.5 🔧 W25Q128FV: a typical chip

16 MB, 256-byte page, 4 KB sector, supply 2.7–3.6 V — it connects to the STM32 directly, without level shifting.

First of all, check the connection. The chip must identify itself:

#define W25_CMD_JEDEC_ID  0x9Fu

uint32_t w25_read_id(void)
{
    uint32_t id;

    CS_LOW();
    spi_xfer(W25_CMD_JEDEC_ID);
    id  = (uint32_t)spi_xfer(0xFF) << 16;   /* производитель: 0xEF — Winbond */
    id |= (uint32_t)spi_xfer(0xFF) << 8;    /* тип памяти */
    id |= (uint32_t)spi_xfer(0xFF);         /* ёмкость: 0x18 = 128 Мбит */
    CS_HIGH();

    return id;
}

For the W25Q128FV the answer is 0xEF4018. If you get zeros or 0xFFFFFF, the problem is in the wiring, not in the code: check the supply, CS, the SPI mode and the pull-ups on WP#/HOLD#.

Reading is the simplest operation; it needs no erase:

void w25_read(uint32_t addr, uint8_t *buf, uint32_t len)
{
    CS_LOW();
    spi_xfer(0x03);                      /* Read Data */
    spi_xfer((uint8_t)(addr >> 16));
    spi_xfer((uint8_t)(addr >> 8));
    spi_xfer((uint8_t)addr);
    for (uint32_t i = 0; i < len; i++) {
        buf[i] = spi_xfer(0xFF);
    }
    CS_HIGH();
}

Writing and erasing rely on two service commands. Write Enable (0x06) permits one following write or erase, and bit 0 BUSY of status register 1 (read with command 0x05) is one while the operation is in progress:

static void w25_write_enable(void)
{
    CS_LOW();
    spi_xfer(0x06);                      /* Write Enable */
    CS_HIGH();
}

static void w25_wait_ready(void)
{
    CS_LOW();
    spi_xfer(0x05);                      /* Read Status Register-1 */
    while (spi_xfer(0xFF) & 0x01u) { }   /* бит 0 — BUSY */
    CS_HIGH();
}

Bit 1 of the same register is WEL: after Write Enable it becomes one, and when the write or erase finishes the chip clears it itself. You check it to confirm that the enable got through. In a product the wait is limited by a timeout.

Programming a page — with the mandatory enable and wait:

void w25_page_program(uint32_t addr, const uint8_t *buf, uint32_t len)
{
    /* Запись, вышедшая за границу страницы, заворачивается на её начало
       и затирает то, что там уже лежало. Обрезаем по границе. */
    uint32_t space = 256u - (addr % 256u);
    if (len > space) {
        len = space;
    }

    w25_write_enable();

    CS_LOW();
    spi_xfer(0x02);                      /* Page Program */
    spi_xfer((uint8_t)(addr >> 16));
    spi_xfer((uint8_t)(addr >> 8));
    spi_xfer((uint8_t)addr);
    for (uint32_t i = 0; i < len; i++) {
        spi_xfer(buf[i]);
    }
    CS_HIGH();

    w25_wait_ready();
}

⚠️ Wrap-around inside a page is a trap that is not noticed right away. If you start writing at address 0x0000 00F0 and pass 32 bytes, the first 16 land at addresses F0…FF, and the next 16 go not to the start of the next page but back to 00…0F of the same page, on top of what was already written. There is no error; the data simply ends up in the wrong place. Hence the trimming at the page boundary in the example above.

And since a write can only turn ones into zeros, the wrapped bytes do not replace the old ones but merge with them by AND — both get corrupted.

Writing 32 bytes from address 0xF0: the first half lands at the end of the page, the second merges with its start

Erasing — only a whole sector at a time:

void w25_sector_erase(uint32_t addr)      /* 4 КБ, адрес любой внутри сектора */
{
    w25_write_enable();

    CS_LOW();
    spi_xfer(0x20);                      /* Sector Erase */
    spi_xfer((uint8_t)(addr >> 16));
    spi_xfer((uint8_t)(addr >> 8));
    spi_xfer((uint8_t)addr);
    CS_HIGH();

    w25_wait_ready();                    /* до 400 мс — это долго */
}

⚠️ An erase takes hundreds of milliseconds, a whole-chip erase takes tens of seconds. A polling loop blocks the program for that whole time. In a real product the busy flag is polled from the main loop or by a timer, not spun on.

Why a three-byte address means exactly 16 MB. Three bytes give 2²⁴ = 16777216 addresses. The W25Q128 uses all of them, and that is the limit: larger chips require switching to four-byte addressing mode, where every command gets an extra byte.

The three-byte W25Q128FV address: 8 bits of the 64 KB block number, 4 bits of the 4 KB sector within the block, 4 bits of the 256-byte page within the sector and 8 bits of the byte within the page — 256 blocks, 4096 sectors, exactly 16 MB; the last address is 0xFFFFFF, beyond it the four-byte mode is needed


41.6 🔧 AT45DB161E: when the chip is non-standard

A useful counterexample. Also an SPI Flash, also 3.3 V, but organised differently.

W25Q128FV AT45DB161E
capacity 16 MB 2 MB
page 256 bytes 528 bytes
on-chip buffers none two SRAM buffers of 528 bytes
smallest erase 4 KB sector 528-byte page
changing a byte in place through RAM: read the sector, erase, write inside the chip: read, modify, erase and write through a buffer

Where 528 comes from. It is 512 bytes of data plus 16 service bytes — historically for checksums and tags. The chip can also work with 512-byte pages. On the E series the switch is reversible: the command 3D 2A 80 A6 sets 512 bytes, 3D 2A 80 A7 sets 528 again, and the size is stored in a non-volatile register rated for about 10000 switches. It was one-time on the old D series — check the revision in the datasheet.

The two buffers are its strong point. You can write data into a buffer and then move it into the main array with one command, with automatic erasing of the page. While the transfer is running, you can already prepare the next portion in the second buffer. For a microcontroller with 20 KB of RAM this is a noticeable saving: you do not need to keep a copy of the sector yourself.

When to take which:


41.7 An SD card over SPI

A way to get gigabytes and a removable medium without dealing with NAND: inside the card is its own controller, which already takes care of wear, bad blocks and error correction.

The initialisation order:

  1. send at least 74 clocks with CS high — the card "wakes up";
  2. CMD0 — put it into the idle state;
  3. CMD8 — find out the version (SDv1 or SDv2);
  4. ACMD41 in a loop — wait until it is ready;
  5. CMD58 — find out whether the card is addressed in bytes or in blocks.

⚠️ Initialisation runs at low speed — no faster than 400 kHz. Only after it finishes is the SPI divider switched to the working frequency. Trying to start straight away at 20 MHz gives a card that "is not detected", and differently on different cards, which makes things completely confusing.

CMD0 arrives while the card is still in its native SD mode, where the checksum is always checked, and the card checks CMD8 against a checksum even in SPI mode, so their frames are taken ready-made: 40 00 00 00 00 95 and 48 00 00 01 AA 87 — the last byte is the CRC7 with the stop one. For the other commands the checksum is not checked in SPI by default, and 0x01 is sent in its place — a single stop one.

Exchanging a block:

After CS goes high one more 0xFF byte is needed: the card releases MISO only on clocks, and without it a neighbouring chip on the same bus (for example, the W25Q128 from 41.5) will read garbage.

The SD block is always 512 bytes — exactly a FAT sector, so the disk layer for the file system is written with almost no adapters.

Power is a separate topic: at peak the card draws up to 100 mA and pulls the voltage down on thin traces. A capacitor next to the holder is mandatory.


41.8 Pitfalls

A forgotten Write Enable. The write command runs "idle", there is no error, the data does not change. Check by reading the WEL bit (bit 1 of status register 1).

Writing without erasing. Flash changes ones to zeros, but not back. If you wrote into a non-empty sector, you get a bitwise AND of the old and new data. The data will look plausible but be corrupted.

Waiting on busy. A sector erase lasts hundreds of milliseconds. The program freezes for that time, and the watchdog may fire.

Wrong SPI mode. Most such chips work in modes 0 and 3. Swapped CPOL/CPHA give garbage on reads, often stable garbage — it looks like "the chip is broken".

Unconnected WP# and HOLD#. Left floating, they pick up noise: a write sometimes goes through, sometimes not. Pull them up to the supply.

Long wires. On a breadboard at 20 MHz SPI works every other time. To check, lower the frequency to a couple of megahertz: if it starts working, the problem is the wiring, not the code.

A DMA buffer in CCM. If the transfer goes through DMA, the buffer must not be in memory connected directly to the core (section 9).

Endurance. 100000 cycles per sector is a lot, but not infinite. A log that writes to the same sector every second wears it out in a day. Write sequentially in a circle.


41.9 Summary

Next: section 41а "SD card over SDIO: four data lines, commands, DMA and FatFS" — the same card, but over its native protocol and four times faster.

Open in the interactive handbook