The Ben Eater EEPROM Programmer, 28C256 and Software Data Protection

Many people are learning, like I did, about computer hardware by following Ben Eater’s 8-bit breadboard computer build. And many of those are either moving on to more advanced projects or using slightly different hardware for the build. And some of those are using larger EEPROM chips such as the 28C256.

But there’s a catch with the 28C256: it has something called software data protection (SDP), which protects data from being accidentally overwritten. With the smaller 28C16 (as used by Ben) you can write data in the same way you would with a RAM chip, just by strobing the write pin. You can do the same with the 28C256 if the SDP is disabled, but if it’s enabled then you need to send a specific ‘command sequence’ to the chip. The SDP can be disabled but this requires a similar command sequence1.

If you have a dedicated EEPROM programmer this is not a problem, the programmer will handle the data protection for you, but many hobbyists prefer to save a few pennies and using Ben’s own breadboard EEPROM programmer.

My original 'BenPrommmer' with 28C16 EEPROM
My original ‘BenPrommmer’ with 28C16 EEPROM

Since I’ve already written code to write to a chip with software data protection via a Z80 I thought it would be helpful to update my own ‘BenPrommer’ to handle the 28C256 and to document both the hardware and software changes needed.

Hardware Changes

I’m assuming here that you already have Ben’s programmer for the 28C16 available to modify

Ben’s design permanently connects /CE to ground and drives /OE via one of the 74HC595 shift registers. To get this to work we need be able to drive all three of the EEPROMs control lines. I’m also going to move /WE away from pin 13 of the Arduino. This is also the pin driving the on board LED and I’d rather use that for status information without risking corrupting the EEPROM. For now, just remove the wire between the ‘595 and /OE (the rightmost white wire in the photo above).

Comparing the pinouts for the 28C16 and 28C256 shows that they both have pretty similar layouts. On the left hand side of the chip everything is the same just with the new pins 1 and 2 added (A14 and A12). On the right hand side we need to move Vcc to the new pin 28 and add A13 and A11 to replace the it and /WE.

28C16 pinout
28C16 pinout
28C256 pinout
28C256 pinout


These four new address pins now need to be connected to the rest of the board. Fortunately the existing 74HC595 shift registers have enough space left to add the extra lines. Just connect A11 to Q3, A12 to Q4, A13 to Q5 and A14 to Q6.

74xx595 pinout
74xx595 pinout

And we can finish off by moving the /WE connection from Arduino pin D13 to pin A2 and adding connections from A1 to /OE and from A0 to /CE.

On the photo below you can see the new address wires in a slightly different shade of blue, and the white wires connecting the control signals.

I found that that this design was /very/ unstable until I added some decoupling capacitors (0.1uF). You can find mine next to the power pin for teh EEPROM, the ground pin for the EEPROM and the power pin from the Arduino. Three capacitors is probably overkill but it took me a lot of debigging before I realised I needed them.

The upgraded BenPrommer with 28C256 EEPROM
The upgraded BenPrommer with 28C256 EEPROM
The upgraded BenPrommer with 28C256 EEPROM
Schematic for the upgraded BenPrommer

Software Changes

We can now turn to the software. I’ve made a fair few changes to the original software, largely to improve performance and remove redundancy.

The key routines for this article are writeEEPROMSDP which writes a byte of data whilst SDP is enabled and disableSDP which disables SDP so you can write to the chip with the normal writeEEPROM function.

disableSDP()

Let’s examine the disableSDP function, with reference to section 20 (page 10) of the datasheet.

It begins by setting the data pins to output and asserting /CE

{
  Serial.println("Disabling SDP");

  setDataPinMode(OUTPUT);

  digitalWrite(CHIP_EN, LOW);

We then sent the command sequence by writing specific bytes to specific addresses

  setAddress(0x5555);
  writeEEPROMCurrent(0xaa);
  setAddress(0x2aaa);
  writeEEPROMCurrent(0x55);
  setAddress(0x5555);
  writeEEPROMCurrent(0x80);
  setAddress(0x5555);
  writeEEPROMCurrent(0xaa);
  setAddress(0x2aaa);
  writeEEPROMCurrent(0x55);
  setAddress(0x5555);
  writeEEPROMCurrent(0x20);

and the clear the /CE line.

  digitalWrite(CHIP_EN, HIGH);

  //(No delay needed)
}

and as per the comment, the chip does not need any kind of delay after this code.

writeEEPROMSDP()

writeEEPROMSDP is very similar, just with it’s own command sequence and finishing up with writing the actual byte to the actual address. And then we finish by waiting for the write operation to complete.

bool writeEEPROMSDP(word address, byte data) 
{
  setDataPinMode(OUTPUT);

  digitalWrite(CHIP_EN, LOW);
  setAddress(0x5555);
  writeEEPROMCurrent(0xaa);
  setAddress(0x2aaa);
  writeEEPROMCurrent(0x55);
  setAddress(0x5555);
  writeEEPROMCurrent(0xa0);

  setAddress(address);
  writeEEPROMCurrent(data);
  
  digitalWrite(CHIP_EN, HIGH);

  return writeWait(data);
}

If you check note 4 on the datasheet under the programming sequence (section 19, page 10) you’ll see that you can actually write up to 64 bytes in one go via this procedure. I’ll leave you to add that functionality if desired but if you do pay attention to the section 4.3 ‘Page Write’ (page 3) which explains that each byte written must be within the same 64 byte page. Also, note that there are strict timing requirements to doing page writes and you’ll probably need to write directly to the Arduino’s ports to be able to hit them.

Wrapping Up

And that’s it. I found I didn’t need any delays within the code and, despite what the datasheet shows, I didn’t need to toggle /CE between every write, but I’ve left them commented out within the code in case you have problems.

I’ve only been able to test this code with a single Atmel branded 28C16 which came from Ebay so it could be another chip with changed markings and slightly different timings.

Code and schematics are available on my Github.

Footnotes

  1. My understanding is that the chips, from new, should have SDP disabled, but people are buying supposedly new chips with the protection enabled and getting stuck.

16 Replies to “The Ben Eater EEPROM Programmer, 28C256 and Software Data Protection”

  1. I am using a 28c64 but have wired it up like Ben ignoring the extra address pins (set to ground). Using Ben´s vanilla EEPROM programmer loads and runs but the printout baffles me as below.
    000: 7f 7b 77 1f 4e 3d 4f 47 7f 7b 77 1f 4e 3d 4f 47
    As you can see it is printing only the contents of the second set of addresses.
    I have looked at the code and cant see what is wrong.
    Regards
    Tony

      1. Hi Mike, Thanks for the quick reply. I am a retired chemical engineer with no formal training in electronics or programming. I am amazed that you can figure out that address line A3 could be the problem. Clearly a genius. Maybe you can explain how you figured this out. If it is (I still have to try and find the fault) is it more likely to be the chip or the wiring?
        Regards
        Tony

        1. When counting in binary A0 flips every address, A1 flips every two addresses, A2 flips every four address, A3 every 8 addresses, A3 every 16 addresses and so on. The pattern is repeating after 8 bytes so it looks as though A3 isn’t counting/changing as it should.

          1. Thanks Mike
            You are a genius. I couldn´t find the error but i rewired all the address lines and now it works.
            regards
            Tony

  2. Mike, your intro nails my situation. I’ve built Ben’s 8-bit computer and am working on an expanded version using AT28C256 chips. I only stumbled onto SDP a couple of days ago by using a TL866ii Plus programmer, experimenting with the EEPROM I so far could not write to, and then later was able to write to the chip using Ben’s programmer (already modified to fit the AT28C256). My brisk research turned up a number of references but yours stood out. However, I’ve now made the HW changes and have tried to get your code to work with it but nothing I’ve tried seems to result in disabling SDP, including adding capacitors to my board. Additionally, when I ran your code as is, I was able to discover that without manipulating /CE, a read after write was actually always returning the value that had last been written, and, in fact, nothing had been written to the EEPROM. This was verified by making sure /CE was low when reading and the actual contents of the EEPROM were returned. Have you been able to verify the contents of your one AT28C256 separately from your sketch code? On the other hand if you DID actually get it to work, I’m curious as to what I am overlooking and would welcome any additional insights you may have. NOTE: Although I do have a separate EEPROM programmer, I really want to get the BenEater version working for this.

    1. Hi Bill, it’s hard to understand what the issue is from your message. You won’t be able to read or write without enabling /CE. The code does this already. If you want to verify that pins are being set correctly you can some LEDs (with current limiting resistors) and put suitable delays into the code – but data probably won’t be read or written correctly as this will be too slow for the chip. Other than that it’s a case of double checking your wiring to make sure everything is there as it should be.

      1. Thanks for answering, Mike. I know this is a year back in your rearview mirror.
        I know my writeup was jumbled. Sorry. I’ll start by saying that I think my wiring is fine. And I have done verification with LEDs. When I use it as a stock BenEater on an unlocked 28C256 it writes successfully. My biggest problem was that it did not know how to disable SDP itself.
        So once I made the wiring changes you specified, I tried using your code, with no changes. I invoked autoTest and printContents. Here’s what the results looked like:

        Disabling SDP
        ++++Test Pattern with SDP
        T
        Expecting a write fail!!!: Test SDP On FAIL (1)
        Disabling SDP
        ++Test Pattern without SDP
        t
        Reading EEPROM
        0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …………….
        0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ……………. etc.

        Problem is, that’s not what’s on the ROM. It never wrote to the ROM and, without changes, isn’t reading either. If I bracket printContents with setting /CE low then high, it displays what’s really on the ROM. But, so far, NO changes I’ve tried to your code succeed in writing anything my ROM.

        So back to my question in my earlier post, were you able to verify that you successfully wrote to your ROM with your code as it currently is in Github? In my case, it acts like it’s working when it really isn’t. I’m not asking you to go dig back into it unless it’s something you want to do. I’m really just asking whether you took it any farther than running the tests I see in the code because I don’t think they’re working for me.

        Thanks for your time, in any event.

        Bill Cooksey

        1. Hi Bill,
          yes, the code is tested and fully functional – at least with my setup.

          A few thoughts:
          * EEPROMs can be a bit temperamental, especially with fake chips around. Different brands can behave slightly differently, so what works for me with my setup may not work for others.
          * The test code, IIRC, only tests whether the SDP is on or off. It reads what’s there already and, after it writes, it will that data back again. So, if you just use the test code the ROM contents will remain unchanged. You’ll need to add/uncomment other code to actually write something meaningful to the chip. (The Test Pattern routines should be writing something though).
          * If you’ve written data to the chip, either with my code or a normal programmer, then my code should be able to read it whether SDP is on or off (ie SDP doesn’t affect reading). &ff is the default data for an erased EEPROM.
          * If you can’t read data then that’s the first thing to get working. If you have access to another programmer I’d recommend using that to program data. (you can also use the other programmer to experiment with enabling and disabling SDP).
          * You also try firing just the disableSDP routine and then testing with your other programmer if SDP has actually been turned off.

  3. Hello I have a problem; I am a bigginer in Arduino . I still cannot get your software to write data although for speed I did connect directly to the ports the 3 control wires to A2, A1,A0 successively to /WE, /OE, and /CE . Plus I double and triple checked the wiring still it won’t write or show any data on the serial monitor and only shows the following:
    “Disabling SDP ++++Test Pattern with SDP T Expecting a write fail!!!: Test SDP On FAIL (1)
    Disabling SDP ++Test Pattern without SDP t Disabling SDP Done “.
    It can write nicely using Ben’s software .
    I would really appreciate any clues.

    1. If TestSDPOn fails then it means that it successfully wrote to the EEPROM (Ie SDP is turned off). And if you can write to the chip using Ben’s software then I’m not sure what the problem is.

  4. Okay Just like Wagner said your a life saver; I connected the 3 control wires directly to the ports for speeding up the enabling/disabling pulses’s sequences; also connected the 3x 0.1uf capacitors across the feed lines. I found a mistake at the end of your code where you wrote pin13 instead of A2 for “WRITE_EN ” . After many uploadings I could not get a write or read on the serial printer. So I reverted back to Ben Eaters software and uploaded his code after re-doing the necessary original wiring.
    And the good news is your magic software, although it did not Write or Read on my EEPROM yet it disabled the write protection on the EEPROM .

  5. I have been tumbling for a month with Ben’s design and code to write my data on a 28C64 and a 28C256 but no luck till I knew about the write protect code on your site and Tom’s site,
    although Ben’s code and design all great working with 28C16 . I will try the disabling code
    on Ben’s hardware of which Ibuilt 2 circuits. Then I will try your new adjustments.
    Wish me luck.

  6. Hi!!!

    You have saved my life!!!
    My hardware is not 100% like yours, so I just used some pieces of your code:

    void writeEEPROMCurrent(byte data);
    void disableSDP();

    I am 100% agree with you about your footnotes!!!
    Thank you!!!

Leave a Reply

Your email address will not be published. Required fields are marked *