EPROM Programmer/Debugger for W25Qxx series (Winbond) BIOS chips using ESP8266, with automatic capacity detection and support from 2MB to 32MB.
- π Automatic Chip Detection: Identifies W25Q16/32/64/128/256 via JEDEC ID
- π¦ Multi-Capacity Support: 2MB, 4MB, 8MB, 16MB, 32MB
- π€ Optimized Streaming Upload: 1KB chunks with automatic verify-retry
- π Protection Management: Automatically removes block protections
- β‘ SPI Speed Control: 0.1-20 MHz adjustable at runtime (presets: 1/4/8/20 MHz)
- β Automatic Verification: Byte-by-byte checksum with detailed error report
- π Responsive Web Interface: Embedded HTML/JS with real-time terminal
- π Detailed Logs: Verbosity system (Quiet/Normal/Verbose/Debug)
- π§ Robust Base64 Decoding: Critical transfer bug fixes
- ESP8266 (NodeMCU, Wemos D1 Mini, etc.)
- W25Qxx Series Chip:
- β W25Q16 (2MB) - JEDEC ID: EF4015
- β W25Q32 (4MB) - JEDEC ID: EF4016
- β W25Q64 (8MB) - JEDEC ID: EF4017 β New support!
- β W25Q128 (16MB) - JEDEC ID: EF4018
- β W25Q256 (32MB) - JEDEC ID: EF4019
- Connection jumpers (recommended: short cables 10-15cm)
- Stable 3.3V power supply (ESP8266 already provides)
| ESP8266 | Pin | W25Qxx | Description |
|---|---|---|---|
| D8 | GPIO15 | CS (Pin 1) | Chip Select |
| D7 | GPIO13 | DI (Pin 5) | Data Input (MOSI) |
| D6 | GPIO12 | DO (Pin 2) | Data Output (MISO) |
| D5 | GPIO14 | CLK (Pin 6) | Serial Clock |
| 3.3V | 3.3V | VCC (Pin 8) | Power Supply |
| 3.3V | 3.3V | WP# (Pin 3) | Write Protect - MUST be connected to VCC! |
| 3.3V | 3.3V | HOLD# (Pin 7) | Hold/Reset - MUST be connected to VCC! |
| GND | GND | GND (Pin 4) | Ground |
IMPORTANT:
- W25Qxx operates ONLY at 3.3V. DO NOT use 5V!
β οΈ CRITICAL: Pins 3 (WP#) and 7 (HOLD#) MUST be connected to 3.3V to allow writing!- If WP# is left at GND, the Status Register is locked and write protection cannot be removed!
- Use short cables (10-15cm) to avoid signal integrity issues
ββββ 1 CS (Chip Select)
β ββ 2 DO (MISO)
β β β 3 WP# (Write Protect) β β οΈ Connect to VCC (3.3V)!
β β ββ 4 GND
ββββΌββΌββΌβΌββ
1ββ€ β ββ8 VCC (3.3V)
2ββ€ ββ7 HOLD# β β οΈ Connect to VCC (3.3V)!
3ββ€ W25Qxxββ6 CLK
4ββ€ Seriesββ5 DI (MOSI)
βββββββββββ
- Pin 3 (WP#): MUST be connected to 3.3V (do not leave floating or at GND!)
- Pin 7 (HOLD#): MUST be connected to 3.3V (do not leave floating or at GND!)
- If WP# is at GND, the Status Register is protected and you WILL NOT BE ABLE to remove block protection!
- If HOLD# is at GND, SPI communication will be permanently paused!
ESP8266 W25Qxx (SOIC-8)
3.3V βββββ¬βββββββββββββββββββΊ Pin 8 (VCC)
β
ββββββββββββββββββββΊ Pin 3 (WP#) β οΈ CRITICAL!
β
ββββββββββββββββββββΊ Pin 7 (HOLD#) β οΈ CRITICAL!
GND ββββββββββββββββββββββββββΊ Pin 4 (GND)
D8 (GPIO15) ββββββββββββββββββΊ Pin 1 (CS)
D7 (GPIO13) ββββββββββββββββββΊ Pin 5 (DI/MOSI)
D6 (GPIO12) ββββββββββββββββββΊ Pin 2 (DO/MISO)
D5 (GPIO14) ββββββββββββββββββΊ Pin 6 (CLK)
Checklist before programming:
- VCC connected to 3.3V (Pin 8)
- GND connected (Pin 4)
- WP# connected to 3.3V (Pin 3)
β οΈ - HOLD# connected to 3.3V (Pin 7)
β οΈ - CS connected to D8 (Pin 1)
- MOSI connected to D7 (Pin 5)
- MISO connected to D6 (Pin 2)
- CLK connected to D5 (Pin 6)
- Short cables (10-15cm maximum) π
- File β Preferences
- In "Additional Board Manager URLs" add:
http://arduino.esp8266.com/stable/package_esp8266com_index.json - Tools β Board β Boards Manager
- Search for "ESP8266" and install
- Board: "NodeMCU 1.0 (ESP-12E Module)" or your specific model
- Upload Speed: 115200
- CPU Frequency: 80 MHz
- Flash Size: 4MB (FS:2MB OTA:~1019KB)
- Port: Select the ESP8266 COM port
Edit the lines in esp8266_w25q32_programmer.ino file:
const char* ssid = "YourWiFi"; // Your network name
const char* password = "YourPassword"; // Your network password- Connect ESP8266 via USB
- Open
esp8266_w25q32_programmer.ino - Click Upload (β)
- Wait for completion
π― Just compile the .ino file - that's it!
- β The web interface (HTML/CSS/JS) is already embedded in the .ino file
- β No need to upload separate HTML files
- β No need to use filesystem (SPIFFS/LittleFS)
- β Everything works out of the box after compilation
- π The
index.htmlfile is just for reference/preview - not required for operation
What happens:
- You compile
esp8266_w25q32_programmer.inoin Arduino IDE - Upload to ESP8266
- The web interface is already there, ready to use
- Just access the IP address in your browser
- Open Serial Monitor (115200 baud)
- Find the IP shown on WiFi connection
- Access
http://YOUR_ESP8266_IPin browser
The interface allows:
- Read JEDEC ID:
- β Automatically detects: W25Q16/32/64/128/256
- β Shows actual chip capacity (2MB-32MB)
- β Validates SPI communication
- Status: Shows if busy or write-protected
- Adjustable Frequency: 0.1 MHz - 20 MHz (slider)
- Quick Presets: 1/4/8/20 MHz buttons for quick testing
- Chunk Size Verify: 4KB, 8KB, 16KB, 32KB, 64KB
- Recommendation:
- Use 1 MHz if you encounter corruption
- Use 4 MHz for stability
- Use 8-20 MHz for speed (short cables)
- Read Data: Reads specific region (address + size)
- Full Dump:
- β Automatically detects chip size
- β Downloads 2MB-32MB according to connected chip
- β
File saved as
bios_<timestamp>.bin
- Accepts Formats:
.bin,.rom,.bssβ New! - Maximum Size: Up to 8MB (adjusts according to detected chip)
- Chunk-by-Chunk System:
- Erases sector (4KB)
- Writes 1KB
- Verifies immediately
- Automatic retry (up to 3x per chunk)
- Automatic Verification:
- Byte-by-byte checksum
- Detailed error report
- Locates first/last error
- Counts affected regions
- Progress Bar: Real-time updates
- Erase Sector: Removes specific 4KB
- Erase Chip:
β οΈ DANGER - Removes everything (makes board unusable) - Automatic Protection: Removes protections before erasing
- Check Protection: Shows Status Register and BP0-BP2 bits
- Remove Protection: Clears all block protection bits
- Auto-Remove: System automatically removes protections before writing
- IMPORTANT: Hardware protection (WP# pin) must be disabled (connected to VCC)
- Verbosity Levels: Quiet / Normal / Verbose / Debug
- Auto-Scroll: Enable/disable automatic scrolling
- Real-Time Logs: Updates every 1 second
- Type Filtering: ERROR (red), WARNING (yellow), INFO (blue), DEBUG (gray)
The W25Q32BV has two levels of protection:
1. WP# Pin (Write Protect - Pin 3):
- GND (LOW): Status Register LOCKED - does not accept modifications β
- VCC (HIGH): Status Register UNLOCKED - accepts modifications β
- For writing: MANDATORY to connect to 3.3V!
2. HOLD# Pin (Pin 7):
- GND (LOW): SPI Communication PAUSED β
- VCC (HIGH): SPI Communication NORMAL β
- For writing: MANDATORY to connect to 3.3V!
BP0, BP1, BP2 bits in Status Register protect memory regions:
| BP2 | BP1 | BP0 | Protected Region | Addresses |
|---|---|---|---|---|
| 0 | 0 | 0 | None (unlocked) β | - |
| 0 | 0 | 1 | Upper 256KB | 0x3F0000-0x3FFFFF |
| 0 | 1 | 0 | Upper 512KB | 0x3E0000-0x3FFFFF |
| 0 | 1 | 1 | Upper 1MB | 0x3C0000-0x3FFFFF |
| 1 | 0 | 0 | Upper 2MB | 0x380000-0x3FFFFF |
| 1 | 0 | 1 | Upper 3MB | 0x300000-0x3FFFFF |
| 1 | 1 | 0 | Upper half | 0x200000-0x3FFFFF |
| 1 | 1 | 1 | Entire chip π | 0x000000-0x3FFFFF |
How to use protection:
- Before writing: Click "π Check Protection"
- If protected: Click "π Remove Protection"
- Make sure WP# is at VCC (3.3V)!
- If WP# is at GND, protection removal WILL NOT WORK!
ALWAYS make a backup of the original BIOS before any modification:
- Click "Full Dump (4MB)"
- Save the
.binfile in a safe location - Keep multiple copies
- Corrupted BIOS = Unusable motherboard
- Only flash compatible BIOS for your H61 board
- Never power off during writing
- Verify file integrity before writing
- Completely power off the motherboard (power cable + battery)
- Make sure there is no residual power
- Use static wrist strap before touching components
- Connect GND first, then other pins
Root cause: Critical bug in Base64 decoding (FIXED in v2.0!)
Solutions:
- Update to latest version (Base64 fix implemented)
- Reduce SPI speed:
- Test 1 MHz first
- If OK, gradually increase to 4 MHz β 8 MHz
- Improve physical connections:
- Use shorter cables (10-15cm)
- Check for loose wires
- Confirm common ground
- Check detailed logs:
- Browser console (F12): size of sent chunks
- Serial Monitor: received/decoded bytes
- Check SPI connections (pin order)
- Confirm stable 3.3V power
- Test jumper continuity
- Check if chip is not soldered inverted
- Use shorter cables (<15cm)
- Chip write-protected:
- Check if WP# (Pin 3) is connected to 3.3V (not GND!)
- Click "π Check Protection" in interface
- If protected, click "π Remove Protection"
- If WP# is at GND, removal WILL NOT work!
- Chip not responding:
- Check if HOLD# (Pin 7) is connected to 3.3V (not GND!)
- If HOLD# at GND, chip stays permanently paused
- Insufficient voltage (use stable 3.3V supply)
- Unstable connection during operation
- Check SSID and password in code
- 2.4GHz network (ESP8266 does not support 5GHz)
- If it fails, ESP creates Access Point:
- Name:
ESP8266-BIOS-Programmer - Password:
12345678 - IP:
192.168.4.1
- Name:
- DO NOT PANIC
- Re-flash original backup
- If backup corrupted, look for official BIOS from manufacturer
- Use board BIOS recovery tool (if available)
| Command | Code | Description |
|---|---|---|
| JEDEC ID | 0x9F | Read ID: EF4016 |
| Read Data | 0x03 | Sequential read |
| Write Enable | 0x06 | Enable writing |
| Page Program | 0x02 | Write page (256B) |
| Read Status | 0x05 | Status register |
| Sector Erase | 0x20 | Erase sector (64KB) |
| Chip Erase | 0xC7 | Erase all |
esp8266_w25q32_programmer.ino
βββ π§ Configuration
β βββ WiFi/AP dual mode
β βββ Configurable SPI (0.1-20 MHz)
β βββ Automatic chip detection
βββ π‘ Low-level SPI functions
β βββ readJedecId() β Read ID + detect capacity
β βββ detectFlashSize() β Adjust FLASH_SIZE dynamically
β βββ readData() β Sequential reading
β βββ programPage() β Write 256 bytes
β βββ sectorErase() β Erase 4KB
β βββ chipErase() β Erase all
βββ π Protection System
β βββ readStatus() / readStatus2()
β βββ writeStatusRegister()
β βββ disableAllProtection() β Remove BP0-BP2
β βββ isWriteProtected() β Check protection
βββ π€ Streaming System (large files)
β βββ 1KB chunks for memory economy
β βββ Write-Verify-Retry per chunk (up to 3x)
β βββ Erase on-demand (erase sector when needed)
β βββ Real-time progress tracking
βββ π HTTP Web Server
β βββ handleInterface() β Embedded HTML/JS/CSS
β βββ handleReadId() β /id (with chip detection)
β βββ handleRead() β /read (dynamic reading)
β βββ handleWriteStream() β /writeStream (init/finish)
β βββ handleWriteChunk() β /writeChunk (ROBUST Base64)
β βββ handleSetSpiFrequency() β /setSpiFrequency
β βββ handleCheckProtection() β /checkProtection
β βββ handleRemoveProtection() β /removeProtection
β βββ handleSystem() β /system (info + detected size)
βββ π Log System
β βββ 4 levels: Quiet/Normal/Verbose/Debug
β βββ Circular buffer (50 messages)
β βββ /logs endpoint for web terminal
βββ π₯οΈ HTML/JS Interface
βββ SPI controls with presets
βββ Streaming upload with progress
βββ Byte-by-byte verification with report
βββ Real-time terminal
βββ Console logs (F12) for debug
Symptom: 4001 corrupted bytes in large uploads
Cause: 3 bugs in manual Base64 decoding:
- β Loop stopped before end (
length() - 3) - β Premature break on padding
- β Incorrect byte extraction logic
Solution: Base64 decoder rewritten from scratch:
- β Processes ALL characters
- β Accumulates bits gradually (not by blocks)
- β Handles padding correctly
- β Validates each byte
- β Debug logs (input/output size)
Result: 0% corruption in tests with 8MB files
- β Automatic detection of W25Q16/32/64/128/256 chips
- β Support for 8MB+ (up to 32MB)
- β .bss file acceptance
- β Critical Base64 decoding fix (eliminates corruption)
- β Base64 debug logs (client + server)
- β Dynamic dump (adjusts to chip size)
- β Interface shows chip name and capacity
- β /system endpoint returns detected size
- W25Q32 support (4MB)
- Streaming upload
- Basic verification
- SPI control
This project is provided "as is" for educational purposes. Use at your own risk. The author is not responsible for damages caused by improper use.