SENI
KECANTIKAN & KESEJAHTERAAN
KRAFTANGAN
BUDAYA & SEJARAH
HIBURAN
ALAM SEKITAR
MAKANAN & MINUMAN
KEJURUTERAAN TERBALIK
SAINS
SUKAN
TEKNOLOGI
WEARABLES
Flash Memory
Volt

Dicipta oleh

Volt

28. Ogos 2026SE
15
0
0
0
0

Flash Memory

This is the sibling of `eprom-floating-gate`. Same storage mechanism — electrons trapped on an island inside the gate oxide — and a completely different way of getting them off again, which changes what the device is for. An EPROM is erased by ultraviolet light through a quartz window. That means the part must be physically removed from the board, put under a lamp for twenty to thirty minutes, and returned. The whole chip erases together; there is no such thing as erasing part of it. The quartz window is also expensive, which is why one-time-programmable EPROMs in cheap plastic packages existed in parallel: the identical die, without the window, erasable never. Fujio Masuoka at Toshiba proposed the change in 1980 and presented it in 1984: erase ELECTRICALLY, in place, by tunnelling the electrons back off the floating gate through a thinner oxide under a strong field. No lamp, no window, no removal from the board. But not one bit at a time. The erase field has to be applied to a whole region at once, so flash erases in BLOCKS — tens of kilobytes at a time in early parts, megabytes in modern ones. You can program individual bytes or pages, and you can only erase in large chunks, and you can only program a bit from 1 to 0. To turn a 0 back into a 1 you must erase its entire block. That single asymmetry is where every strange thing about flash comes from. It is why a flash device needs a controller doing wear levelling and garbage collection rather than presenting itself as plain memory. It is why writing 4 kilobytes can cause megabytes of internal activity. And it is why solid-state drives have a firmware layer more complicated than some operating systems. The name, incidentally, came from a colleague of Masuoka's who said the block erase reminded him of a camera flash. You will measure endurance on real parts by wearing one out deliberately, and watch the erase-block behaviour that the whole architecture is built around.
Pertengahan
5 hours

Arahan

1

Prove the asymmetry — program a byte, then try to un-program it

One experiment establishes the entire character of the device, and it takes ten minutes. USE A SERIAL NOR FLASH — a W25Q32 or similar, on a breakout board, driven over SPI from an ESP32 or an Arduino. These cost very little, the command set is simple and documented, and unlike an SD card there is no controller hiding what is happening. STEP ONE. Erase a sector — command 0x20, sector erase, 4 kilobytes. Read it back. Every byte is 0xFF. Erased means all ones. STEP TWO. Program one byte to 0x0F using the page program command. Read it back: 0x0F. Fine. STEP THREE, and this is the one that matters. Program that SAME byte to 0xF0. Read it back. You will not get 0xF0. You will get 0x00. Think about what happened. Programming can only pull bits DOWN, from 1 to 0 — it adds electrons to floating gates, and there is no per-bit way to take them off. The device did a bitwise AND of what was there with what you asked for: 0x0F AND 0xF0 is 0x00. It did not refuse, it did not report an error, it did exactly what the hardware can do and returned success. STEP FOUR. Erase the sector again and program 0xF0. Now it works, because the erase restored every bit to 1 first. That is flash, completely. Programming clears bits; erasing sets them, and only in blocks. Everything else in a solid-state drive is software built to hide this. NOW SEE THE BLOCK GRANULARITY. Write a recognisable pattern across a whole 4 kilobyte sector. Then erase and observe that you cannot erase less: there is no command to erase 100 bytes. Try modifying one byte in the middle of the sector from 0 back to 1, and find that the only route is to read the entire sector into RAM, erase it, modify the copy, and write all 4 kilobytes back. TIME THAT SEQUENCE and compare it with the time to program 4 kilobytes into an already-erased sector. The read-modify-erase-write cycle is far slower, and it wrote 4096 bytes to change one. That ratio is WRITE AMPLIFICATION, it is the central problem of flash storage, and you have just measured it on your own bench.

Bahan untuk langkah ini:

W25Q32 SPI Flash ModuleW25Q32 SPI Flash Module5 keping
ESP32 Development BoardESP32 Development Board1 keping
BreadboardBreadboard1 keping
Jumper Wire SetJumper Wire Set1 set

Alatan diperlukan:

Desktop ComputerDesktop Computer
Digital Multimeter (Lab Grade)Digital Multimeter (Lab Grade)
Oscilloscope (2-Channel, 100MHz)Oscilloscope (2-Channel, 100MHz)
StopwatchStopwatch
2

Wear one out on purpose

Endurance is a specification everyone quotes and almost nobody measures. It is measurable on a bench in a day, and the result is more interesting than the datasheet number. WRITE A CYCLING LOOP. Pick one sector. Repeatedly: erase it, program the whole sector with a known pattern, read it back, and count any bytes that differ. Log the cycle number and the error count. Leave it running. Use a sacrificial part and confine the cycling to ONE sector so the rest of the device stays healthy as a control. WHAT TO EXPECT. A NOR flash rated at 100,000 cycles will typically go tens of thousands of cycles with zero errors, then start producing occasional single-bit failures, then fail more often, and then fail persistently in particular bytes. Plot errors against cycle count. The curve is not a cliff and it is not linear. It is flat, then a knee, then a steep rise — and crucially the failures cluster: the same few cells fail again and again while their neighbours are fine. That clustering is the whole justification for wear levelling. If failure were uniform there would be nothing to level. WATCH THE ERASE TIME AS WELL AS THE ERRORS, because it is the better early warning. Time each erase operation. As the oxide accumulates trapped charge from repeated tunnelling, erasing gets harder and the internal state machine takes longer — and this happens well before any bit actually fails. A rising erase time is a worn block announcing itself, and real controllers watch exactly this. WHY IT WEARS. Every program and erase drives electrons through the tunnel oxide at high field. A fraction do not make it cleanly through and get stuck in the oxide itself. Trapped charge does two things: it screens the field, so subsequent erases need longer, and it eventually forms a conductive path that lets the floating gate leak. The cell stops holding its bit. The honest framing, which the popular version gets backwards: flash does not wear out from being READ. Reads are gentle. It wears from being ERASED, and the erase count is what a controller tracks. IF YOU HAVE THE PATIENCE, run a second part at elevated temperature — 60 or 70 degrees — and compare. Wear is thermally accelerated, and hot flash dies sooner. That is why an SSD in a badly ventilated laptop has a genuinely shorter life than the same drive in a cool desktop.

Bahan untuk langkah ini:

W25Q32 SPI Flash ModuleW25Q32 SPI Flash Module5 keping
ESP32 Development BoardESP32 Development Board1 keping
DS18B20 Temperature Sensor (Waterproof)DS18B20 Temperature Sensor (Waterproof)1 keping
BreadboardBreadboard1 keping

Alatan diperlukan:

Desktop ComputerDesktop Computer
StopwatchStopwatch
Thermometer (Lab)Thermometer (Lab)
Bench Power Supply (30V/5A)Bench Power Supply (30V/5A)
3

Cycle a sector until it dies

Wearing a part out is the only honest way to see the shape of flash failure, and it needs tens of thousands of cycles, which is a loop rather than a person. This sketch cycles ONE sector — erase, program the whole sector, verify — and logs three things per cycle: the erase time in microseconds, the count of bytes that came back wrong, and the address of the first bad byte. The third column is the one people forget to record, and it is where the interesting result is. Failures CLUSTER: the same addresses fail again and again while their neighbours stay perfect. If wear were uniform there would be no such thing as wear levelling, and this column is the evidence that it is not. The erase-time column is the early warning. Trapped charge accumulating in the tunnel oxide screens the erase field, so the internal state machine needs longer — and this rises measurably before any bit actually fails. A real controller retires a block on exactly this signal rather than waiting for data loss. It verifies after the ERASE as well as after the program, because a worn cell often fails to erase to 0xFF before it fails to hold a programmed 0. Checking only the programmed state misses the first half of the failure. This destroys a real device. Use a sacrificial part, confine the cycling to one sector so the rest of the chip remains as a control, and expect it to take hours.
flash_wear.inocpp
// Flash endurance cycler - wears one sector out and logs how it dies.
// Board: ESP32 DevKit v1 + W25Q32 SPI NOR flash on a breakout.
//
// Endurance is quoted on every datasheet and almost never measured. It is measurable
// in a day, and the SHAPE of the failure is more informative than the number:
// failures cluster in the same few cells, and erase time rises before any bit fails.
// Those two facts together are the entire justification for wear levelling.
//
// WEARS OUT A REAL PART. Use a sacrificial device and cycle ONE sector so the rest of
// the chip stays healthy as a control.
//
// WIRING (VSPI): CS=5  SCK=18  MOSI=23  MISO=19   3.3 V ONLY - 5 V will destroy it.

#include <SPI.h>

#define CS_PIN        5
#define TEST_SECTOR   0x001000UL      // 4 kB sector under test
#define SECTOR_SIZE   4096
#define PAGE_SIZE     256
#define PATTERN       0xA5

#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_STATUS  0x05
#define CMD_READ_DATA    0x03
#define CMD_PAGE_PROGRAM 0x02
#define CMD_SECTOR_ERASE 0x20
#define CMD_JEDEC_ID     0x9F

SPISettings spiCfg(8000000, MSBFIRST, SPI_MODE0);

void cmd(uint8_t c) {
  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(c);
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
}

void waitReady() {
  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(CMD_READ_STATUS);
  while (SPI.transfer(0x00) & 0x01) { /* BUSY */ }
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
}

void addr24(uint32_t a) {
  SPI.transfer((a >> 16) & 0xFF); SPI.transfer((a >> 8) & 0xFF); SPI.transfer(a & 0xFF);
}

unsigned long eraseSector(uint32_t a) {
  unsigned long t0 = micros();
  cmd(CMD_WRITE_ENABLE);
  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(CMD_SECTOR_ERASE); addr24(a);
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
  waitReady();
  return micros() - t0;
}

void programPage(uint32_t a, uint8_t value) {
  cmd(CMD_WRITE_ENABLE);
  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(CMD_PAGE_PROGRAM); addr24(a);
  for (int i = 0; i < PAGE_SIZE; i++) SPI.transfer(value);
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
  waitReady();
}

// Returns bytes that differ, and records WHERE - clustering is the point.
int verifySector(uint32_t a, uint8_t expect, uint32_t *firstBad) {
  int bad = 0; *firstBad = 0xFFFFFFFF;
  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(CMD_READ_DATA); addr24(a);
  for (int i = 0; i < SECTOR_SIZE; i++) {
    if (SPI.transfer(0x00) != expect) { bad++; if (*firstBad == 0xFFFFFFFF) *firstBad = a + i; }
  }
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
  return bad;
}

void setup() {
  Serial.begin(115200);
  pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH);
  SPI.begin();

  SPI.beginTransaction(spiCfg); digitalWrite(CS_PIN, LOW);
  SPI.transfer(CMD_JEDEC_ID);
  uint8_t m = SPI.transfer(0), t = SPI.transfer(0), c = SPI.transfer(0);
  digitalWrite(CS_PIN, HIGH); SPI.endTransaction();
  Serial.printf("# JEDEC id %02X %02X %02X\n", m, t, c);
  if (m == 0x00 || m == 0xFF) { Serial.println("# no device - check wiring and 3.3 V"); while (1) delay(1000); }

  Serial.println("cycle,erase_us,bad_bytes,first_bad_addr");

  for (unsigned long cycle = 1; ; cycle++) {
    unsigned long eus = eraseSector(TEST_SECTOR);

    uint32_t fb;
    int badErased = verifySector(TEST_SECTOR, 0xFF, &fb);   // erase should give all 0xFF

    for (int p = 0; p < SECTOR_SIZE / PAGE_SIZE; p++)
      programPage(TEST_SECTOR + p * PAGE_SIZE, PATTERN);

    int bad = verifySector(TEST_SECTOR, PATTERN, &fb);

    if (cycle % 100 == 0 || bad || badErased) {
      Serial.printf("%lu,%lu,%d,%08X\n", cycle, eus, bad + badErased,
                    fb == 0xFFFFFFFF ? 0 : fb);
    }
    // WATCH THE ERASE TIME COLUMN. It rises before any bit fails - trapped charge in
    // the tunnel oxide screens the field, so the internal state machine needs longer.
    // A real controller retires a block on exactly this signal.
  }
}

void loop() { }

Alatan diperlukan:

Desktop ComputerDesktop Computer
ESP32 Development BoardESP32 Development Board
Oscilloscope (2-Channel, 100MHz)Oscilloscope (2-Channel, 100MHz)
4

Tunnelling, endurance and write amplification

Loading Jupyter Notebook...

Alatan diperlukan:

Desktop ComputerDesktop Computer
Notebook and PencilNotebook and Pencil

Bahan

5

Alatan Diperlukan

8
Jumlah anggaran
$20.00

Blueprint berkaitan

Blueprint ini berkongsi pengetahuan — teknik, bahan atau prinsip

CC0 Domain Awam

Blueprint ini dikeluarkan di bawah CC0. Anda bebas menyalin, mengubah, mengedar, dan menggunakan karya ini untuk sebarang tujuan, tanpa meminta kebenaran.

Sokong Pembuat dengan membeli produk melalui Blueprint mereka di mana mereka memperoleh Komisen Pembuat ditetapkan oleh Penjual, atau cipta iterasi baru Blueprint ini dan sertakan ia sebagai sambungan dalam Blueprint anda sendiri untuk berkongsi hasil.

Perbincangan

(0)

Log masuk untuk menyertai perbincangan

Memuatkan komen...