DIY / ROM programming

Programming a 27C512 (and other EPROMs/EEPROMs) with the RURP

An EPROM holds the first instructions a retro computer runs, the program in an arcade board or the code in a game cartridge. This guide shows how to put your own data into one with the Relatively Universal ROM Programmer (RURP), Anders Nielsen's open-source Arduino shield. The worked example is a 27C512-type chip, from an empty socket to a verified copy.

First: what an EPROM is, and why you would program one

ROM means read-only memory: a chip that keeps its contents when the power is off. A computer reads it like any other memory. It puts an address on the address pins (A0-A15 on a 27C512) and gets one byte back on the data pins (D0-D7). The P in EPROM means programmable: you can write it yourself, but only in a programmer and at a higher voltage than the 5 V the chip runs on. In the finished computer the chip is only read.

A 24-pin ST M2732A EPROM with a round quartz window, clamped in a black 32-pin ZIF socket on a RURP board.
An EPROM in the RURP: an ST M2732A, a 24-pin UV EPROM marked 21V, in a 32-pin ZIF socket. The round quartz window is how you recognise a UV EPROM. Photo: iMania product image.

A 6502 computer is the classic reason to program one. At power-on the CPU fetches its start address from the reset vector at $FFFC-$FFFD, at the very top of the address space, so there has to be ROM there with a valid program. Our 6502 guide explains why, and the 6502 SRAM guide shows how RAM and ROM share the 64 KB address map. The same kind of chip holds the firmware of home computers, arcade boards, synthesizers and industrial equipment from the 1980s and 1990s. Typical jobs are burning your own firmware for a kit such as the 65uino, keeping a backup copy of an old ROM, or replacing one that has failed.

A 27C512 holds 512 kbit, which is 64 KB: 65,536 addresses of 8 bits each. That is exactly one 6502 address space, which is why the part number turns up in so many retro projects.

Top view of a bare RURP Rev 2.1 board: a purple Arduino-shield PCB with presoldered SMD parts, the empty 32-pin socket footprint, a row of LEDs and the RST and USR buttons.
The RURP Rev 2.1 as delivered: SMD parts presoldered; the socket and pin headers are yours to solder.
The pin header kit: a breakable 40-pin header strip, a 4-pin female header and two jumpers.
The pin headers and jumpers kit for the programmer.

Erasing: UV light, high voltage or 5 V

Programming can only change bits from 1 to 0. To get the 1s back the chip has to be erased, and how it is erased decides what you need on your bench.

  • UV EPROMs (27C512, 27C256, 2764, 2732, 2716 and most other 27-series parts) have a quartz window over the silicon. Only short-wave ultraviolet light erases them. ST's M27C512 data sheet asks for 253.7 nm UV and a dose of at least 15 W·s/cm²: about 15 to 20 minutes under a 12 mW/cm² lamp, with the chip within 2.5 cm of the tubes. The RURP cannot do this. It reads and programs UV EPROMs, but erasing them takes a separate UV eraser. Afterwards, cover the window with an opaque label: the same data sheet says direct sunlight can erase the chip in about a week. Windowless "OTP" versions cannot be erased at all.
  • Electrically erasable EPROMs such as the Winbond W27C512 and W27C020 have the same pinout and are programmed the same way as a 27C512 or 27C020, with 12 V on the programming pin. They are erased electrically, though: 14 V on OE/VPP and on A9 while CE is pulsed low for 100 ms (W27C512 data sheet). The RURP does that itself, so no UV lamp is needed. Shops, including ours, often call the W27C512 an EEPROM; Winbond calls it an "electrically erasable EPROM". Either way it needs those high voltages, so it cannot be rewritten inside a 5 V computer.
  • 5 V EEPROMs (the 28C family, such as the AT28C64 and AT28C256) and 5 V flash (SST39SF010A, SST39SF020A, SST39SF040) need no high voltage at all. They erase and write at 5 V using command sequences. The SST39SF parts erase in 4 KB sectors or as a whole chip, typically in 18 ms and 70 ms (SST39SF0x0A data sheet). The software used below supports both families.
VPP values from the data sheets listed under Sources; the M2732A value is from the product page and the chip database of the programming software described below.
ChipPinsTypeErased byProgramming voltage
W27C51228Electrically erasable EPROMThe RURP (14 V)12 V on pin 22
M27C512 (ST)28UV EPROMUV eraser12.75 V ±0.25 V on pin 22
27C256 (Microchip)28UV EPROMUV eraser13.0 V ±0.25 V on pin 1
W27C02032Electrically erasable EPROMThe RURP (14 V)12 V
M2732A (ST)24UV EPROMUV eraser21 V
SST39SF010A/020A/040325 V flashThe RURP (5 V commands)None
AT28C64, AT28C256285 V EEPROMThe RURP (5 V commands)None

What the RURP is, and what else you need

The Relatively Universal ROM Programmer is an Arduino shield. Its SMD parts come presoldered: three 74HC573 latches that hold the address, a boost regulator that makes the programming voltage, and transistor switches that put that voltage on the right socket pin under software control. You solder the chip socket and the pin headers yourself. A small trimpot sets the programming voltage; the README gives a range of 12-27 V. Rev 2 and later select 24-, 28- or 32-pin chips with transistors instead of jumpers, and Rev 2.1 added a 200 mA polyfuse in front of the regulator. Rev 2.2 and Rev 2.3, the current version, have a three-position jumper JP4 with an extra position for 2716-type chips.

Firestarter is the open-source software recommended for the RURP. It is written by Henrik Olsson and published under the MIT licence on GitHub. It has two parts: firmware that runs on the Arduino underneath the RURP shield and operates the chip socket, and the firestarter command-line tool on your computer, which sends it commands over the USB cable. You install the tool with pip install firestarter, and the tool then installs the firmware on the Arduino for you (see below).

To use the RURP with Firestarter you also need:

  • An Arduino Uno, an Arduino Leonardo or an Uno-shaped board with an ATmega328PB. (Anders' 65uino can drive the shield too, but with his original 6502 code and the Python scripts in the RURP repository, not with Firestarter.)
  • A 32-pin socket. A 32-pin ZIF socket is the comfortable choice: the chip drops in and a lever clamps it. A plain 32-pin DIP socket is the budget choice. The 32-pin footprint also takes 24- and 28-pin chips.
  • The pin headers and jumpers for the Arduino connection and JP4.
  • A computer with Python 3.11 or later and avrdude, and a USB cable for the Arduino.
Anders' three rules, from the board and its README. Don't attach the shield while the power is on. Don't power the shield until the Arduino has the right firmware, so install the firmware first and then attach the shield. Don't put a ROM in the socket until you are ready to write it, and don't leave it there while the Arduino is reset or its firmware is being installed: some boards put the programming voltage on several pins during a reset.

Install Firestarter

The RURP README recommends Firestarter if you just want to program ROMs. The commands below are from the current stable release, 3.1.0.

  1. Install avrdude: brew install avrdude on macOS or sudo apt install avrdude on Debian and Ubuntu. The Arduino IDE also includes it.
  2. Install the command-line tool and check its version:
    pip install firestarter
    firestarter --version
  3. Connect the bare Arduino by USB and install the firmware. Use -b leonardo or -b uno328pb for those boards. If avrdude stops with a signature error, the board flag is wrong.
    firestarter fw -i -b uno
  4. Unplug the USB cable, push the shield onto the Arduino, and plug the cable back in. Then ask the board for its firmware version and the shield revision. Neither command touches the socket.
    firestarter fw
    firestarter hw

The tool and the firmware must share the first two version numbers (3.1 with 3.1). When you upgrade, upgrade the tool first and the firmware second.

How the chip goes into the socket

Photo of a RURP Rev 2.1 board from the component side with a 28-pin Winbond W27E257 in the 32-pin socket. Numbered markers: 1, the notch on the left end of the chip, pointing toward JP4; 2, chip pin 1 in socket hole 3; 3, the empty socket holes 1 and 2 at the bottom left and 31 and 32 at the top left; 4, the blue JP4 jumper at the left edge of the board.
A real board, annotated: a 28-pin Winbond W27E257 (27C256 pinout, so VPP on pin 1) in the plain 32-pin socket of a Rev 2.1 RURP, seen from the component side with the labels upright. The notch points left, toward JP4 (1); chip pin 1 sits in socket hole 3 (2); holes 1, 2, 31 and 32 stay empty (3); and JP4 is fitted because this chip has VPP on pin 1 (4). Photo: iMania product image, annotated for this guide - JPG.
Top view of the RURP 32-pin socket, drawn to scale with 600-mil DIP packages. The large drawing shows a 28-pin chip with its pin 1 in socket hole 3 and holes 1, 2, 31 and 32 left empty; two small drawings show a 32-pin chip filling every hole and a 24-pin chip with its pin 1 in hole 5 and holes 1 to 4 and 29 to 32 left empty. In every drawing the chip notch points to socket pin 1.
How 32-, 28- and 24-pin chips sit in the RURP's 32-pin socket, from the Firestarter pin-map table. Drawn to scale for this guide (600-mil DIPs: 2.54 mm pitch, 15.24 mm between the rows) - SVG.
  1. Find pin 1 of the chip. A notch or a dot marks the pin-1 end. With the notch pointing left, pin 1 is the bottom-left pin.
  2. Find pin 1 of the socket. It sits on the square solder pad, and the back of the board has "Pin1->" arrows for 24-, 28- and 32-pin chips. On the Rev 2.1 and Rev 2.3 boards, with the components facing you and the RST, USR and OLED labels upright, socket pin 1 is the lower-left hole, at the end next to jumper JP4.
  3. Point the notch at the socket's pin-1 end and push the chip to the far end. A 32-pin chip fills the socket. A 28-pin chip puts its pin 1 in socket hole 3, so holes 1, 2, 31 and 32 stay empty. A 24-pin chip puts its pin 1 in hole 5, so holes 1-4 and 29-32 stay empty.
  4. On a ZIF socket, lift the lever to open the contacts, drop the chip in without pressing, and push the lever down to clamp it. Lift the lever again before you take the chip out.

Check the orientation twice. Anders notes that the Rev 2.1 fuse is no guarantee: a ROM put in the wrong way round can still be damaged.

Programming voltage and jumpers

firestarter info <chip> prints everything about one chip: size, type, whether it can be erased electrically, its VPP, the pinout, and the jumper setting for each shield revision. It does not use the programmer. Run it for every new chip type.

Setting the voltage. The shield has one adjustable regulator. Its full output is called VPE. For 28- and 32-pin EPROMs the firmware feeds VPP from it through a drop resistor. You set both with the same trimpot, but measure the rail the chip will get:

ChipMeasure with
28- and 32-pin EPROMs, including the W27C512 and W27C020firestarter vpp
24-pin EPROMs (2716, 2732) and Intel 28F flashfirestarter vpe
5 V EEPROMs and 5 V flashNothing to set

Run the command with the socket empty; it shows the voltage again and again but does not connect it to the socket. Turn the trimpot slowly with a small screwdriver until the reading matches the VPP line from info, then press Ctrl+C. Before every write the firmware measures again. More than 0.5 V too high stops the write; below 95 % of the target gives a warning.

For a W27C512 the target is 12 V. Don't overshoot: the data sheet's absolute maximum on OE/VPP and on A9 is 14.5 V. You don't set the 14 V erase voltage separately; for the erase the firmware puts the undropped VPE rail on A9 and OE/VPP for 100 ms.

Side-by-side top-view pinouts of a 27C512 and a 27C256. They are identical except pin 1, which is A15 on the 27C512 and VPP on the 27C256, and pin 22, which is /OE and VPP on the 27C512 but only /OE on the 27C256. Pin 24, A9, is marked on both because it receives high voltage for the chip ID and for the W27C512 erase.
27C512 and 27C256 pinouts from the Winbond W27C512, ST M27C512 and Microchip 27C256 data sheets. Drawn for this guide - SVG.

JP4 routes the programming voltage to pin 1 for chips that need it there. The 27C512 has A15 on pin 1 and shares VPP with /OE on pin 22, so it needs no jumper. The 27C256 and the 2764 have VPP on pin 1, so on Rev 2.2 and 2.3 the jumper goes on the 28-pin pole (toward the socket), and on Rev 2.0 and 2.1 JP4 is closed. The 24-pin pole (toward the board edge) is only for 2716-type chips with VPP on pin 21. It connects socket pin 1 to socket pin 25, so remove it for every 28- and 32-pin chip. Never leave JP4 fitted for a 32-pin chip: the README warns that this will most likely damage the ROM, the programmer or both.

JP5 is a solder jumper on the back, bridged when the board is new. Cut it only for chips with address line A19 on pin 1, such as the 27C080 and M27C801. Firestarter asks you to confirm that JP5 is cut before it writes or erases one of those. Rev 0 and Rev 1 boards use jumpers JP1-JP3 instead; info shows their settings too.

Worked example: a ROM image into a W27C512, then verify

  1. Get the image. A 27C512 holds 65,536 bytes. A smaller file is fine: the write starts at address 0 (or the address you give with -a) and stops at the end of the file. For a 65uino the image is build/abn6507rom.bin, made by the assemble.sh script in the 65uino repository. That script's own last step is firestarter write w27c512 build/abn6507rom.bin. You can try the image in the 65uino emulator first; it opens a raw ROM file locally in your browser (see our guide to the 6502 browser emulators).
  2. Find the exact chip name and read its data:
    firestarter search 27C512
    firestarter info W27C512
    The search lists every 27C512 variant with its maker and VPP. Use the name of the chip in your hand; for the Winbond it is W27C512. info shows VPP: 12.0v, Can be erased: yes (electrically erasable) and "No jumper" for JP4.
  3. Remove the JP4 jumper and set the voltage with the socket empty. Turn the trimpot until the reading says 12.0 V, then press Ctrl+C:
    firestarter vpp
  4. Insert the chip: notch toward the pin-1 end, chip pin 1 in socket hole 3, lever down.
  5. Optional checks. id reads the chip's electronic signature; the data sheet gives DA (Winbond) and 08 (W27C512), so it should match 0xDA08. It puts high voltage on A9, which is why the voltage is set first. If the chip holds something you want to keep, read it to a file before you overwrite it:
    firestarter id W27C512
    firestarter read W27C512 backup.bin
  6. Write and verify in one step:
    firestarter write W27C512 build/abn6507rom.bin --verify
    For an electrically erasable chip, Firestarter erases it first, then programs it byte by byte with 12 V pulses, checking each byte, and finally reads the whole region back and compares it with the file. Success ends with Write to W27C512: verified -- the read-back matches. and exit code 0.
  7. Check again whenever you like. verify compares the chip with the file (exit code 0 means identical), and blank tells you whether a chip is empty:
    firestarter verify W27C512 build/abn6507rom.bin
    firestarter blank W27C512
  8. Lift the lever and take the chip out before you unplug or reset the Arduino. The chip is ready for its socket in the computer.

The same job with a UV 27C512, such as the M27C512: run firestarter blank M27C512 first. A UV chip is never erased by the programmer, so write refuses a chip that is not blank, with a line such as Refusing write to M27C512: not blank at 0x000123, v: 0x4F. Erase it under UV light and try again. info M27C512 shows VPP: 13.0v and Can be erased: no (UV erase only), so set the voltage to 13.0 V before firestarter write M27C512 rom.bin --verify.

Firestarter keeps a list of chips validated on real hardware. In the 27C512 family it includes the W27C512, which passed on two setups (a Leonardo with a Rev 2.0 shield and an Uno with a Rev 2.2 shield), the TMS27C512 and the SST27SF512. The other 27C512 variants are in the database but not yet validated.

What about the 27C256?

Yes, the RURP programs it. firestarter search 27C256 lists 26 database entries from makers such as AMD, Atmel, Intel, Microchip, ST and TI, all on the same 28-pin EPROM protocol as the 27C512. Three things are different:

  • VPP is on pin 1, not pin 22 (see the figure above). Fit JP4 on the 28-pin pole on Rev 2.2/2.3, or close it on Rev 2.0/2.1; firestarter info AM27C256 says the same. Remove the jumper again before you program a 27C512 or a 32-pin chip.
  • VPP depends on the maker. The database has 12.0 V for Intel's and Atmel's 27C256 and 13.0 V for AMD's, Microchip's and ST's M27C256B. Microchip's data sheet gives 13.0 V ±0.25 V. Use the entry for the maker printed on your chip.
  • It is a UV EPROM with half the capacity: 32,768 bytes. Erasing needs a UV eraser, as above.

Can a 27C512 replace a 27C256? Often, but it depends on the board. The pinouts are identical except pin 1. A 27C256 needs its pin 1 (VPP) at the supply voltage when it is read (Microchip data sheet), so boards usually tie that pin to 5 V, and a 27C512 then sees A15 = 1 and answers from its upper half. A common trick is to write the 32 KB image twice into one 64 KB file, so the chip works whichever level pin 1 has:

# macOS, Linux
cat rom32k.bin rom32k.bin > rom64k.bin
# Windows
copy /b rom32k.bin+rom32k.bin rom64k.bin

Check your board's schematic first. If something else drives pin 1, the trick does not apply.

Common errors and what they mean

You seeLikely causeWhat to do
No programmer found, or the wrong one answersSeveral serial devices, or the board is busyConnect one programmer only, or name the port: firestarter -p /dev/ttyACM0 fw
avrdude signature error during fw -iWrong board flagUse -b uno, -b leonardo or -b uno328pb to match the chip on your board
hw shows rev_unknownRevision not detected; the firmware will not switch on the programming voltageSet it by number: firestarter config --rev 5 for Rev 2.3 (4 = Rev 2.2, 3 = 2.1, 2 = 2.0)
VPP is high: 12.9V > 12.0VTrimpot set too high; the write stopsRun firestarter vpp and turn it down
VPP is low: …Trimpot set too lowTurn it up. If you cannot reach the value (some 24-pin chips want up to 25 V), the shield cannot program that chip
Chip ID … does not match expected ID …Wrong chip name, chip reversed or in the wrong holes, lever open, or a different maker's partCheck the print on the chip and its position. id lists chips with the ID it found. Use -f only when you are sure
Refusing write … not blank at …A UV EPROM that still holds dataErase it with UV light. For a W27C512 run firestarter erase W27C512 -b
Byte at … failed to program within 25 pulsesVPP too low, VPP on the wrong pin (JP4), or a worn chipCheck the voltage and JP4 against info, then try another chip
landed, but the read-back did not verifyBad contact or an address problemRun firestarter verify <chip> <file> --full. blank/contact means almost every byte read as FF: the chip is blank or not touching the contacts. address-line points at a bent pin or the wrong holes. Used chips may need their pins cleaned of oxidation
erase does nothing on a 27C512UV EPROMs have no electrical eraseUse a UV eraser
The search shows one part number from several makers with different VPPinfo and write use the first match. M2732A, for example, finds Intel's 25 V entry before ST's 21 V entryCompare the VPP with your chip's data sheet before you write. Don't program until they agree

Limits

  • It does not erase UV EPROMs.
  • It takes parallel 24-, 28- and 32-pin DIP chips. This guide does not cover adapters for other packages.
  • You set the voltage by hand with the trimpot, and you set JP4 and JP5 by hand. The shield cannot sense its jumpers, so the software cannot check them.
  • The shield's supply to the chip is fixed at 5 V. Some UV EPROM data sheets ask for a raised supply while programming (6.25 V for the M27C512, 6.5 V for Microchip's 27C256 "express" algorithm). Firestarter shows a programming VCC in info for such chips and programs them at 5 V.
  • Commercial programmers such as the TL866II or T48 can be faster for some tasks. The RURP is about price, openness and repairability.

FAQ

Do I need a UV eraser? Only for windowed UV EPROMs such as the M27C512, 27C256, 2764 and 2732. The W27C512 and W27C020, 28C EEPROMs and SST39SF flash are erased in the RURP.

Which Arduino? An Uno, a Leonardo or an Uno-shaped board with an ATmega328PB, for Firestarter. Look at the chip marking to pick the right -b flag.

Does my image have to be exactly the size of the chip? No. write writes the file from address 0 (or from -a), and verify compares as many bytes as the file holds.

Can I back up an old ROM? Yes: firestarter read <chip> backup.bin, then firestarter verify <chip> backup.bin. Set the jumpers and voltage for that chip first, as for a write.

Does it program 28C64 and 28C256 EEPROMs? Yes, at 5 V with no programming voltage. Firestarter unlocks their software data protection before each write. No 28C part was on the validated list for release 3.1.0, so treat your first one as a test.

What does RURP stand for? Relatively Universal ROM Programmer.

Where can I see it in action? In Anders' video Open $9 ROM Burner just got even better and easier to use!, which installs Firestarter and burns a chip, and in Open Source ROM Burner Just Keeps Getting Better! about Rev 2.1.

Parts used in this guide

The programmer and what you solder onto it:

For the computer the ROM goes into:

Chips from this guide that iMania lists. They are used parts, so check each page for stock:

Next, see how a ROM gets its place in the address map in the address-decoding guide.

Sources. RURP repository and README (jumpers, voltage, safety rules) · Hackaday project log (74HC573 latches, Rev 2.1 fuse) · Firestarter wiki: Install, Shield Revisions, Reading Chips, Writing and Verifying, Pin Maps, and the Firestarter 3.1.0 tool and chip database (search and info output) · Data sheets: Winbond W27C512 (erase and programming voltages, pinout, signature), ST M27C512 (VPP, UV erasure), Microchip 27C256 (pinout, VPP), Winbond W27C020, SST39SF010A/020A/040. Both diagrams were drawn for this guide.