Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Design

EPROM Emulation


SEP94: EPROM Emulation

EPROM Emulation

Your own emulator for microcontroller development

David Mockridge

David develops client/server systems for Southern Life Assurance in South Africa. He also writes for electronics magazines and has a special interest in embedded-systems software. You can contact David at 13 Ayreshire Rd., Rondebosch East, 7700 South Africa.


One of the most tedious parts of embedded-systems development is the "crash-and-burn" EPROM cycle, where object code is burned into an EPROM ("erasable programmable ROM") chip, which in turn is plugged into the target system. If (or more realistically, when) code bugs appear, you have to extract the chip, expose it to an ultraviolet EPROM eraser, and reprogram it with the debugged program.

While you can ease the process by keeping a small pile of chips nearby--erasing several at a time--a better approach is to use an EPROM emulator plugged into the EPROM socket, disguised as the real thing. As far as the embedded system is concerned, it is the real thing. However, there's one difference from your perspective: Once the emulator is plugged into the EPROM's homebase, you can download your programs over and over again. When you're satisfied with your program, you only have to burn it into an EPROM once.

Hardware Design

This article describes the software and hardware that make up an EPROM emulator. The emulator has several design requirements, of which low cost is paramount. The programs it uses are created on a PC, so they have to be transferred out of the PC's memory and into the emulator. To avoid buying an additional interface card or serial port, I used the PC's existing parallel printer port. This also buys some speed when downloading. Of course, if you do a lot of printing on your PC, you may need to buy a second parallel card, anyway. If you do get a new port and dedicate it to the emulator, you'll have to change the base addresses in the download program, which currently uses 3BC hex, the standard printer-port address for LPT1. Although utilities such as Central Point's PCTools will return your printer-port addresses, you can also find them with DEBUG using the dump command in Figure 1. The memory dump shows two ports, LPT1 at 03BC hex and LPT2 at 0278 hex. In any case, if LPT1 on your PC is not at 03BC hex, you'll have to replace the base addresses in the download program.

The download software is a short, DOS command-line utility. Although I used Basic (it makes for fast development and readable code), the download software is straightforward enough to easily port to your favorite language. A Windows version could be knocked out without difficulty, with the standard file-open dialog and a static control for a bar graph showing the file-download progress. If you choose a language with no verb for direct-port output, however, you might need to add a few bytes of assembler. (Incidentally, the prototype used the no-longer-supported Borland Turbo Basic. Some minor syntax changes converted the programs to run under Microsoft's QuickBasic 4.5.)

When you run the program, the name of the file to be downloaded is read from the command line or prompted for, if omitted. A short routine parks the cursor after the command-line filename and gives a running display of the bytes downloaded, so the user can see what is happening. Since the software drives custom hardware, I'll examine the hardware before moving on to exactly how a download works.

Although an IBM-type PC was used for this project, any computer with access to one and a half output ports (one port and four extra lines) could run the same software and drive the emulator just as well.

RAM to the Core

At the core of the emulator is a RAM chip, masquerading as an EPROM. I chose static RAM over dynamic RAM, since SRAM does not require the constant refreshing and complex support circuitry of DRAM. Admittedly, SRAM is more expensive, but this device only needs a single, small-capacity chip.

Figure 2 shows the emulator core, including the central RAM chip. To write a byte, you present your data (together with an address) to the correct pins, and then pulse the read/write line briefly from read to write state and back again. Since the chip is normally left in read mode, if the address data is unchanged, the new data will now appear on the I/O lines.

Memory chips have a fair number of lines for carrying address, data, and control information. The PC printer port only has a few. Therefore, design problem #1 is that there aren't enough lines to do the job.

Squeezing the Printer Port

Since the nature of the data download is to always send a consecutive block of bytes, the addresses these bytes are assigned to must start at 0 and increment by 1 for each byte. Put another way, at download time the address information is implicit in the data file being downloaded, so you can eliminate explicit address data from the download process if you can provide these addresses locally, in the emulator.

A hardware counter (Figure 2) is used to locally address the emulator's memory. The CD4040 chip chosen is 12 bits wide. After a 1 is applied to the reset pin, it outputs address 0. On each 0-to-1 transition at the clock pin, the address increments by one. The clock and reset lines are driven by software described later. If you connect the counter directly to the RAM's address lines (a tiny local bus?), all you have to do is advance the counter once after each byte is loaded into the RAM.

Using a counter to address the memory simplifies expansion, since expanding the RAM by any amount will only require more counters, leaving the two-line PC interface unchanged.

The prototype emulator was built using a Hitachi 6116 RAM chip. Although it only holds 2K of RAM, this was sufficient for the assembly-language controller program being developed. If you're developing more-complex applications using compilers, you can easily expand memory with a larger RAM and by daisy-chaining another address counter. The hardware described here could support either a 4K or a 2K RAM, since the counter is 12 bits wide.

The IBM-PC parallel-printer port actually consists of three physical ports (see Table 1). They are not memory-mapped and are accessed by the 80x86 IN and OUT port I/O instructions. Most high-level languages have an equivalent verb for accessing these functions. Basic has an OUT verb for port output. The three ports are addressed consecutively from the base address upwards, with port 3BC handling printer data, while 3BD and 3BE handle printer-control input and output, respectively.

As with the printer BIOS routines, you send data through the base port. In addition, you'll hijack the traditional printer control functions in the third port to drive the emulator with custom software.

The emulator plugs into the EPROM socket on the host system. The RAM connections are simply brought out to a header plug, since the 6116 is electronically compatible with a 2716 EPROM. In the prototype, the printed-circuit board was laid out for the often-cheaper (although four times the size) 27C64 EPROM. This presented no problem, since the 27[C]xxx family of EPROMs are similar enough that the smaller 2716 can easily pass for a (partially filled) larger family member, with minor header-connection changes.

Once the data is safely in the RAM, you have to cut all connections to the emulator to prevent the interface from conflicting with the host system's. At worst, this could mean clipping two alligator clips onto the chip's power-supply pins, unplugging it from the emulator, and plugging it into the host. A better solution would be some kind of software-invoked disconnection.

A Software Guillotine

Address and data lines are fed through data gateways, comprising 74LS244 octal-buffer chips. Each buffer chip has data-bus inputs that connect straight through to an output bus. A 1 written to the buffer's output-disable pin effectively disconnects the two buses, leaving the outputs free to follow whatever they are connected to. Figure 3 shows how three such buffers form a switchable channel for address, data, and control lines between RAM and emulator.

So the emulator will not interfere with the host. But what about the host clashing with the emulator? A second set of buffers would do the trick, but in practice, the host was removed by powering it down for downloads, which conveniently triggers a hardware reset in the target system when it is powered back up. Since the emulator has its own power supply, its data is saved irrespective of the host.

Software to Drive a Download

Listing One shows the complete listing for EMULOAD.BAS, the download program. (An executable version of the program is available electronically; see "Availability," page 3.) The emulator hardware requires individual bits in the parallel port to be manipulated, while the PC is essentially byte (or word) oriented. Instead of maintaining the current port value and masking bits on or off as needed, whole-byte constants were defined. This faster approach was made possible because the set of all useful bit patterns was small enough.

The PC downloads to the emulator by writing data to the first printer-port address, where it is latched until replaced by another write. In between, it writes control byte constants to the third address, which fires various pieces of emulator hardware.

Before sending any data, the address counter is reset to zero by writing the ResetCounter% constant. (The percentage-sign suffix denotes a Basic integer variable.) After the initial reset, this line is left at 0 for all other operations.

The first byte in the download file is written to the data port. Software generates positive-going pulses by writing 0,1,0 to the required pin. This technique is used in successive writes of the ReadState% and WriteState% constants. They flip the RAM's write line to place your byte inside the chip. ClockRising% then similarly advances the address counter. This process will repeat until end of file is reached. Finally, the DisableCard% constant is written to disable the buffers that carry emulator address and data lines.

Software for Debugging

Construction of the prototype produced a rather dense mass of wiring, with a proportionately high chance of construction errors. An advantage of hybrid software/hardware projects is that software can sniff out hardware problems for you. Hardware buffs may argue otherwise, but for me, it beats holding the device in front of your nose with a magnifying glass or spending hours with a continuity tester and circuit diagram. With this in mind, some short and simple programs (such as TESTEM1.BAS in Listing Two which tests individual lines) are used to pulse individual lines slowly, flip the counter over, and kick the latches in and out of circuit. I discovered several board-wiring errors and one cable error using this program. Fortunately, none of these were fatal for the chips. (An executable version of the testing program is available electronically.)

Output Protection

The buffer chips have output protection; they can field nasty spikes in the power supply and various overload conditions. As I found out, they also go into a dead short if you connect the buffer inputs directly to ground. All unused inputs on any MOS chips should be grounded through a current-limiting resistor (around 10K, for example).

The OE Line

Once the prototype was built, tested and ready, I plugged it into an 8051 embedded system, where...nothing happened. I then plugged it into a breadboard, where it functioned perfectly. Test programs wrote data into every byte of memory, from which they all read back faultlessly using external circuitry. After suspecting and replacing everything but the programmer, a careful review of the 8051 architecture revealed the problem. The OE (output enable) pin on a real EPROM is used to turn the EPROM's data outputs off when the CPU does not want it on the bus. This control line exists on the 6116 RAM, but was not in the correct place on the header plug. Once this was properly placed, the 8051 board could turn the emulator off whenever it wanted the busses for itself. It worked.

After a few hours, however, the emulator stopped working again. After much digging around, it emerged that any programs larger than a quarter of the total memory size did not work correctly. The two most-significant address lines had been swapped around. Downloaded programs were being written to memory quadrants in the order 0213, instead of 0123, so the problem only occurred with programs larger than a quarter of memory.

Have Chip, Will Travel

While the emulator was designed for an 8051-type CPU embedded system, freeing the design from any particular host has clear portability advantages. The final emulator design supports any conceivable EPROM use, across all microprocessors, through to straight hardware applications like a character generator or decoder. This is why the emulator has its own power supply and is not connected to the host system in any way besides plugging into the target EPROM socket.

Although described here as a stand-alone device, I originally designed theemulator for integration into an embedded-system development tool, where it would be compiled as a subroutine, callable from an integrated-development environment menu bar.

Choice of RAM type may be critical for high-speed systems. Careful consideration of system-clock speed versus chip-propagation delay time is advised. The prototype system ticked along comfortably with a 16-MHz system clock and a Hitachi HM6116LP-3 (a 300ns RAM).

Future enhancements for the emulator could include a verification facility and software-switched activation of the host, although the current arrangement of flipping a switch is not an intolerable burden. It would be nice to expand the emulator to the full 64K address space of the 8031 by expanding the address counter. A new counter's clock input would connect to the existing counter's most-significant address bit. If more than one RAM chip is used, an address-decoding block will be required to make sure that only the chip being addressed is enabled. The prototype's chip-select input was tied permanently low, since it was the only chip in the system. In a system with only two RAMs, the counter line one bit above the most-significant address bit could be inverted to provide a chip select for a second chip, with the current chip enable being driven from the same line.

After using an EPROM emulator, you'll never want to return to the "crash-and-burn" method. Does anyone out there want to buy some second-hand EPROMs?

References

8-Bit Microcontrollers. Matra Harris MHS, Nantes, Cedex, France, 1989.

CMOS Data Book. National Semiconductor Corp., Santa Clara, CA.

IC Memory Products 1986. Hitachi Electronic Components Europe GmbH, Munich, Germany, 1986.

MOS Memory Data Book. National Semiconductor Corp., Santa Clara, CA, 1984.

Veary, Trevor. "BITPNET: Build Your Own Inexpensive Parallel Network." BIT Magazine (March 1983).

Figure 1: Use this DEBUG command to find your printer-port addresses.

C:\> DEBUG
-d 40:8 L 8
0040:0008   BC 03 78 02 00 00 00 00
-q

Figure 2 The emulator core.

Table 1: The PC printer port.

    Port   Bits   Printer function   D-connector pins   Emulator function
    0      0..7   Data output        2..9               Data input
    1      0..7   Control inputs     --                 Unused
    2      0      Strobe             1                  Address clock
    --     1      Auto linefeed      14                 Read/write
    --     2      Initialize         16                 Address reset
    --     3      Select             17                 Enable

Figure 3 The complete emulator.

Listing One


' EMULOAD.BAS EPROM emulator downloader by David Mockridge Copyright (C) 
' Downloads a file to dedicated EPROM emulator hardware attached to PC
' parallel printer port. Current file addr displayed during download.

' Subroutine declaration
DECLARE SUB GetCursor (pCursorX%, pCursorY%)

'----- Main ------
GOSUB Initialize
GOSUB Download
END

'----- Initialize -------
' PC standard parallel printer port base addresses for Lpt1:
PrinterData% = &H3BC
PrinterRead% = PrinterData% + 1
PrinterCtrl% = PrinterData% + 2
' Control line constants
ResetCounter% = 13   ' Reset on,  Card enabled,  RAM Read   Clock off
ReadState% = 9       ' Reset off, Card enabled,  RAM Read,  Clock off
WriteState% = 11     ' Reset off, Card enabled,  RAM Write, Clock off
ClockRising% = 8     ' Reset off, Card enabled,  RAM Read,  Clock on
DisableCard% = 1     ' Reset off, Card disabled, RAM Read,  Clock off
' Other constants
AppName$ = "EMULOAD" ' Name of this program as appears on DOS cmd line
ChunkSize% = 64      ' n Bytes after which addr. display is updated
NullString$ = ""
Quote$ = CHR$(34)
GOSUB FindProgNam          ' Find end of program name on screen
LOCATE CursorY%, CursorX%  ' Park cursor there
FileName$ = COMMAND$ ' Read name of file to download, from command line
IF FileName$ = NullString$ THEN
   ' No file specified so prompt for it
   INPUT "Enter filename to download "; FileName$
   LOCATE CursorY%, CursorX%
   PRINT FileName$; " ";
   CursorX% = CursorX% + 1
ELSE
   CursorX% = CursorX% + LEN(FileName$) + 1
   LOCATE CursorY%, CursorX%  ' Park cursor past filename
END IF
RETURN
'---- FindProgNam:  Find column where .exe cmd calling this program ends ----
CALL GetCursor(CursorX%, CursorY%)
IF CursorY% > 1 THEN CursorY% = CursorY% - 1  ' Go up to command line
' Build a string with current prompt and command line
CmdLine$ = NullString$
FOR NextCol% = 1 TO 40
   CmdLine$ = CmdLine$ + CHR$(SCREEN(CursorY%, NextCol%))
NEXT NextCol%
CmdLine$ = UCASE$(CmdLine$)
' Now search this string for download command
NameStarts% = INSTR(CmdLine$, AppName$)
IF NameStarts% > 0 THEN
   CursorX% = NameStarts% + LEN(AppName$) + 1
END IF
RETURN
'----- Download: Open file, download to emulator hardware -----
FileByte$ = " "    ' Set size of file i/o buffer to one byte
OPEN FileName$ FOR BINARY AS #1 LEN = 1
   FileLen% = LOF(1)
   IF FileLen% = 0 THEN
      PRINT "Could not open file "; Quote$; FileName$; Quote$;
      PRINT " - 0 bytes downloaded.";
      PLAY "T255DCBA"  ' Error Fanfare
      END              ' End right here
   ELSE
      PRINT "Downloading "; FileLen%; " bytes. ";
      ' Reset address counter
      OUT PrinterCtrl%, ResetCounter%
      PRINT "Address: 0";
      CALL GetCursor(CursorX%, CursorY%)
      CursorX% = CursorX% - 1 ' Backspace past "0"
      Chunk% = 0
      FOR Addr% = 0 TO FileLen% - 1
         ' Update current address display only every ChunkSize% bytes
         Chunk% = Chunk% + 1
         IF Chunk% > ChunkSize% THEN
            Chunk% = 0
            LOCATE CursorY%, CursorX%
            PRINT Addr%;
         END IF
         GET #1, , FileByte$ ' Read from file buffer
         DataByte% = ASC(FileByte$)
         ' Manipulate emulator hardware using control lines
         OUT PrinterData%, DataByte%    ' Set up data
         OUT PrinterCtrl%, ReadState%   ' Write pulse. (0 = Write)
         OUT PrinterCtrl%, WriteState%
         OUT PrinterCtrl%, ReadState%
         OUT PrinterCtrl%, ClockRising% ' Now advance address counter
         OUT PrinterCtrl%, ReadState%
      NEXT Addr%
      ' Update final addr display if file not a multiple of chunk size
      IF Chunk% <> 0 THEN
         LOCATE CursorY%, CursorX%
         PRINT Addr%;
      END IF
   END IF
CLOSE
' Disable emulator so CPU card can take over the RAM chip
OUT PrinterCtrl%, DisableCard%
PLAY "T255AE"  ' Short bleep to say we're done.
PRINT "-Done.-";
END
SUB GetCursor (pCursorX%, pCursorY%)
   pCursorY% = CSRLIN  ' Save current cursor column
   pCursorX% = POS(0)  ' Save current cursor row
END SUB



Listing Two


' TESTEM1.BAS Program to test emulator hardware on printer port lines
' by David Mockridge Copyright (C). Control line 2 (constant value 4, the reset
' line) is true; all other lines are inverted by the hardware.

' Subroutine declarations
DECLARE SUB ShowPorts (CtrlPort%, DatPort%)
DECLARE SUB GetKbd (KbdKey$)

NullString$ = ""
ControlPort% = 0
DataPort% = 0

' Expected port addresses for Lpt1:
PrinterData% = &H3BC
PrinterRead% = PrinterData% + 1
PrinterControl% = PrinterData% + 2
' Init Control lines
AddrClock% = 1  ' Inverted
ReadWrite% = 2  ' Inverted
ResetAddr% = 4  ' True
Enable% = 8     ' Inverted
' Print menu of line testing options
CLS
StartCol% = 21
StartRow% = 2
LOCATE StartRow%, StartCol%: PRINT "** Printer port line tester **"
LOCATE StartRow% + 3, StartCol%: PRINT "R   To raise addr reset line"
LOCATE StartRow% + 4, StartCol%: PRINT "A   To clock address counter"
LOCATE StartRow% + 5, StartCol%: PRINT "W   To pulse write line"
LOCATE StartRow% + 6, StartCol%: PRINT "D   To raise disable line"
FOR LineNo% = StartRow% + 8 TO StartRow% + 15
   LOCATE LineNo%, StartCol%
   BitName$ = CHR$(ASC("0") + LineNo% - 10)
   PRINT BitName$; "   To raise line for data bit "; BitName$
NEXT LineNo%
LOCATE StartRow% + 17, StartCol%: PRINT "F   To flash all lines x5"
LOCATE StartRow% + 19, StartCol%: PRINT "Q   To quit  "
CALL GetKbd(KeyHit$) ' Which key was hit?
WHILE KeyHit$ <> "Q"
   SELECT CASE KeyHit$
    CASE "R": ControlPort% = ResetAddr%
    CASE "A": ControlPort% = AddrClock%
    CASE "W": ControlPort% = ReadWrite%
    CASE "D": ControlPort% = Enable%
    CASE "0" TO "7": DataPort% = 2 ^ (ASC(KeyHit$) - ASC("0"))
    CASE "F"
      ' Flash all lines on and off 5 times
      FOR Flash% = 1 TO 5
         OUT PrinterControl%, &HFF
         OUT PrinterData%, &HFF
         CALL ShowPorts(&HFF, &HFF)
         SLEEP 1 ' Delay 1 second
         OUT PrinterControl%, &H0
         OUT PrinterData%, &H0
         CALL ShowPorts(0, 0)
         SLEEP 1
      NEXT Flash%
   END SELECT
   ' Write data to ports
   OUT PrinterControl%, ControlPort%
   OUT PrinterData%, DataPort%
   CALL ShowPorts(ControlPort%, DataPort%)
   CALL GetKbd(KeyHit$)
WEND
END
' Get key hit, after waiting until key hit
SUB GetKbd (KbdKey$)
   KbdKey$ = ""
   WHILE KbdKey$ = ""
      KbdKey$ = INKEY$
   WEND
   KbdKey$ = UCASE$(KbdKey$)
END SUB
' Print current port values
SUB ShowPorts (CtrlPort%, DatPort%)
   LOCATE 23, 7
   PRINT "Current control port value : "; HEX$(CtrlPort%); " "
   LOCATE 23, 38
   PRINT ".  Current data port value : "; HEX$(DatPort%); "  "
END SUB


Copyright © 1994, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.