How to connect a parallel ATA hard disk to a microcontroller

Index


0> Preface

TOP

In this document I will describe how to connect a parallel ATA harddisk (further on simply called HDD by me) to a 8Bit microcontroller (MCU). 8Bit, because I use these ones myself. Of course it should be possible with a 16Bit or any other MCU, with a 16Bit one it might be even simpler.
But before you think: "Wow, I need to build that, because thatīs what Iīve been ever looking for!", read the Considerations.


1> Considerations

TOP

A HDD connected to a MCU is useful where you have to log or compute large amounts of data. But for something up to 4M or more, a FLASH device may be better suited. Keep in mind that a HDD, because of its mechanical components, is shock sensitive, so donīt mount it on your mountian bike. You may find it interesting, that Compact Flash (CF) Cards can be used like HDDs. So you may use them in this case. A HDD also needs a lot more power than a single FLASH chip and needs +5V and +12V (except some notebook types and the CF-Cards). This is what it makes them absolutely unsuited for battery-powered devices. What you have to expect in puncto data rates: First, the data rate mainly depends on the speed of your MCU. 0.5kB/s to 3kB/s should be possible without big troubles. If you need some MB/s, you need a horrendous fast MCU and you may have to use DMA and/or interrupts what complicates it. Another drawback is, that a HDD can only read and write blocks of 512B. If you have a really tiny one (like the one I used for the serial interface) you donīt have the RAM to prepare a block for reading/writing.
If you still think a HDD is the right thing for your MCU application, read on.


2> Hardware

TOP

The power connector

I think everyone knows the standard power connector.

 Drive side (with commonly used cable colors on power cable)
  _______
 /       \
| o o o o |
'---------'
  | | | |
  | | | '- 12VDC
  | | '--- 12V return (12V GND)
  | '----- 5V return (5V GND)
  '------- 5VDC

The ATA connector

I will only explain the 40-Pin connector (the standard includes more), because it is the most spreaded one. But it shouldnīt matter since only the pin position is different.

   .-----------------------------------------.
39 | . . . . . . . . . . . . . . . . . . . . | 1
40 | . . . . . . . . . . . . . . . . . . . . | 2
   '-----------------------------------------'

The Signal names with short description

A slash ("/") before a signal name indicates, that the signal is inverted.
Signal names
Pin #Host DeviceNameDescription
1-->/RESETThis signal from the host system shall be asserted beginning with the application of power and held asserted until at least 25 us after voltage levels have stabilized within tolerance during power on and negated thereafter unless some event requires that the device(s) be reset following power on.
2-GND 
3<-->DD7Data signal
4<-->DD8Data signal
5<-->DD6Data signal
6<-->DD9Data signal
7<-->DD5Data signal
8<-->DD10Data signal
9<-->DD4Data signal
10<-->DD11Data signal
11<-->DD3Data signal
12<-->DD12Data signal
13<-->DD2Data signal
14<-->DD13Data signal
15<-->DD1Data signal
16<-->DD14Data signal
17<-->DD0Data signal
18<-->DD15Data signal
19-GND 
20-(keypin) 
21<--DMARQUsed for DMA data transfers between host and device.
22-GND 
23-->/DIOWWrite strobe signal from host. rising edge latches the data on DD0-DD15 into the device.
24-GND 
25-->/DIORRead strobe signal from host. Falling edge enables the data from the device on DD0-DD15
26-GND 
27<--IORDYThe use of IORDY is required for PIO modes 3 and above and otherwise optional.
28 CSELUsed for automatic detection of device0 / device1
29-->/DMACKThis signal shall be used by the host in response to DMARQ to initiate DMA transfers.
30-GND 
31<--INTRQThis signal is used to interrupt the host system.
32-reserved 
33-->DA1For register selection
34 /PDIAGThe host shall not connect to the PDIAG- signal.
35-->DA0For register selection
36-->DA2For register selection
37-->/CS0For register selection
38-->/CS1For register selection
39 /DASPIndicates that a device is active, or that device 1 is present. Most of the time a LED is connected to it.
40-/GND 

Of course, you donīt need all them for basic interfaceing. The ones I used are:
DA0, DA1, DA2, /CS0, /CS1, DD0-DD15, /RESET, /DIOR, /DIOW, /DASP
Where I put the following ones on GND:
GND, CSEL
For /CSEL you donīt need a I/O Pin of you MCU, because only the HDD-busy-LED is connected to it. You know that from your PC. Use a 1k pullup and a LED in the following way:


                         ^ +Ub
/DASP                    |
  o----|<|---\/\/\/\-----'
       LED     1k
I put CSEL on GND to be on the safe side, but I donīt use it, since I am jumpering the HDD as Master or Slave and not for CSEL use. I think this is the minimal wiring which works, but you still need a lot of I/O pins of your MCU.


3>The HDD registers

TOP

The HDD is used like as a set of registers. The bidirectional data bus is DD0-DD15 and the address selection is done by DA0-DA2, /CS0 and /CS1. Many of them have a bitwise meaning.

HDD registers
AddressesFunctions
/CS0/CS1DA2DA1DA0Read (/DIOR)Write (/DIOW)
NNxxxData bus high impendanceNot used
NA0xxData bus high impendanceNot used
NA10xData bus high impendanceNot used
NA110Alternate StatusDevice control
NA111ObsoleteNot used
AN000DataData
AN001ErrorFeatures
AN010Sector countSector count
AN011Sector number
LBA 0-7
Sector number
LBA 0-7
AN100Cylinder low
LBA 8-15
Cylinder low
LBA 8-15
AN101Cylinder high
LBA 16-23
Cylinder high
LBA 16-23
AN110Device/Head
LBA 24-27
Device/Head
LBA 24-27
AN111StatusCommand
AAxxxInvalid addressInvalid address
A = signal asserted, N = signal negated, x = donīt care
Asserted means: Signal high, if it is a normal signal; Signal low, if it is a inverted signal
Negated means: Signal low, if it is a normal signal; Signal high, if it is a inverted signal

Alternate status register

This register contains the same information as the Status register in the command block.

Command register

This register contains the command code being sent to the device. Command execution begins immediately after this register is written.

Cylinder high register

If the LBA bit is cleared to zero in the Device/Head register, this register contains the high order bits of the staring cylinder address for any hard disk access. If the LBA bit is set to one int the Device/Head register, this register contains Bits 16-23 of the LBA for any media access.

Cylinder low register

If the LBA bit is cleared to zero in the Device/Head register, this register contains the low order bits of the starting cylinder address for any media access. If the LBA bit is set to one in the Device/Head register, this register contains Bits 8-15 of the LBA for any media access.

Data register

Data transfer from and to the device is performed by a series of writes/reads to this register. This is the only 16Bit wide register.

Device control register

This register allows a host to software reset attached deviced and enable/disable interrupts.
Bit 1: nIEN: Inverted interrupt enable bit. I set this to 1, to diable interrupts.
Bit 2: SRST: If this bit is set to 1, the device performs a software reset. I donīt use this, since I have full control over the hard reset wire.

Device/Head register

This register chooses either LBA or CHS translation and defines the Head ot provides the LBA Bits 24-27
Bits 0-3: The head is selected with these 4 Bits. LBA bits 24-27 if LBA is selected
Bit 4: HS0-HS3: Whether device 0 or 1 is selected (0 = Master, 1 = Slave)
Bit 5: Always 1
Bit 6: LBA: LBA Bit. Set this to enable LBA translation (if supported)
Bit 7: Always 1

Error register

This register contains which error encountered.
Bit 0: AMNF: Address mark not found. indicates the data address mark has not been found after finding the correct ID field.
Bit 1: TK0NF: Track 0 not found. Indicates, that track 0 has not been found during a RECALIBRATE command.
Bit 2: ABRT: Aborted command. Indicated, that the command has been aborted, because a parameter is invalid or a error encountered.
Bit 3: MCR: Media change request.
Bit 4: INDF: ID not found. Indicates, that the requested sectors ID hasnīt been found.
Bit 5: MC: Media changed.
Bit 6: UNC: Uncorrectable data error. Indicates that an uncorrectable data error has been encountered.
Bit 7: Reserved.

Features register

This register is command specific

Sector count register

This register contains how many sectors of data have to be transferred from or to the host. A value of 0 indicates 256 sectors.

Sector number register

This register contains the starting sector number of the LBA Bits 0-7.

Status register

Conatins the status os the device.
Bit 0: ERR: Indicates, that an error has occured during the execution of the command.
Bit 1: IDX: Vendor specific
Bit 2: CORR: Corrected data. Indicates, that a data error has been corrected. What this means, is vendor specific.
Bit 3: DRQ: Indicates, that the device is ready for data transfer.
Bit 4: DSC: Device seek complete. This indicated, that the head has settled over a track.
Bit 5: DF: Device fault.
Bit 6: DRDY: Device ready. Device is capable of accepting all commands.
Bit 7: BSY: Busy.


4>HDD protocol, reset and practical interfaceing

TOP

Reading and writing registers

To write a register do the following:

  1. Set the address by setting /CS0, /CS1, DA0-DA2
  2. Enable the outputs if you have a tristate output in your MCU or interface. (To put the data on the bus. You should already have loaded the data latch before enabling the tristate output.) Keep the data on the bus till after point 4.
  3. Put /DIOW low
  4. Put /DIOW high
  5. Disable the tristate outputs. (I think that doesnīt have to be done, but I do it to be on the safe side.)
To read a register do the following:
  1. Set the address by setting /CS0, /CS1, DA0-DA2
  2. Make sure, that the MCU/interface inputs/outputs are in high impendace mode.
  3. Put /DIOR low
  4. Read the data bus
  5. Put /DIOR high
Of course, for all this exists a minimum timing, but I dindīt to take care of that (but maybe you have to), because my MCU has a cycle time of 1us and the longest minimum time mentioned in the standard is 600ns and this is the whole cycle time. Reading/writing data from the HDD is done by performing a series of the steps like described.

Issuing read/write commands

I will describe here how *I* did the interfaceing. This does not mean that it sticks absolutely to the standard, but it works (at least for me). I only use the READ SECTOR(S) with retries and the WRITE SECTOR(S) with retries commands. (Command code: 0x20 and 0x30).

To read a sector from the hdd do the following, assuming that interrupts are turned off:

  1. Wait till the BSY bit is low
  2. Set the DEV bit in the Device/Head register to 0 or 1, depending on which device you want to access.
  3. Wait till the BSY bit is low
  4. Load the Device/Head, Cylinder low, Cylinder high, Sector number and Sector count register.
  5. Issue the read or write command.
  6. Wait till the BSY bit is low
  7. Wait till the DRQ bit is high
  8. Transfer one data block (256 reads/writes from/to the Data register = 512B)
  9. Check the Status register, if an error occured
  10. If you selected to transfer more than 1 block, proceed with 6.
Now, this is not exactly what the standard wants (I simplified it something by checking only once for errors etc.), but it seems to work fine. If you omit steps 2 and 3, you may get the works - works not - works - works not effect. Depending on wheter the hard disk is fast enough or not. This happened to me. I used 3 HDDs for testing. 2 worked fine and one (obviously the slowest one) occasionally produced an error

The HDD reset

I descibe only the hardware reset and only for a one-device-configuration, since Iīve never used software reset or two devices. To do the reset, you have to pull the /RESET wire low and keep it low for at least 25us. Then reset it to high. After that you should poll the Status register and wait till the the BSY bit is low and the DRDY is high. Thatīs all.


5> Schematic/Source of the PIC16F628 serial ATA hard disk interface

TOP

All MCU firmware downloadable here is for a MCU clock frequence of 20MHz even if the schematic says 4MHz

The assembler source for Microchips MPLAB can be downloaded here:
V7.2 (for board Rev. 0.35): serhdd72.asm (Baud rate: 57600)
V7.3 (for board Rev. 0.35): serhdd73.asm (Baud rate: adjustable)

There is also a INTEL-Hex-file available here:
V7.2 (for board Rev. 0.35): serhdd72.hex (Baud rate: 57600)
V7.3 (for board Rev. 0.35): serhdd73.hex (Baud rate: adjustable)

A GIF of the schematic is available here:
Rev. 0.35: rev0_35.gif

A high resolution (360dpi) GIF of both sides of the board is available here:
Rev. 0.35: rev0_35_toplayer.gif, rev0_35_bottomlayer.gif
You have to resize them to 100mm x 80mm.

A face plan is available here:
Rev. 0.35: rev0_35_faceplan.gif

The source of the Linux program I used to the test whole thing can be downloaded here: hdd3.c [view online]
Note: The program is fairly incomplete. In fact these are more code fragments than a really usable program, but you can use it for testing and experimenting. It only works with firmware Rev. 7.3.


6> Information on the PIC16F628 serial ATA hard disk interface

TOP

As the name says, the modules is intended to be an interface. If you build it, you still need another MCU or a PC which is controlling it. It is absolutely useless otherwise. The module uses only Device 0 (Master) for the HRDCHS, HWRCHS, HRDLBA, HWRLBA and HIDENT commands.

Commands and protocol of software revision 7.2

A command is one byte which is sent to the module over the serial cable.
Command table
Command synonymHex codeShort description
HNOP0x00Interface NOOP. Sends the HNOP code back to the host.
HWBSY0x01Waits while the HDD is busy.
HWDRQ0x02Waits till the HDD is ready for data transfer.
HRESET0x03Does a HDD hardware reset.
HRDREG0x04Read a HDD register.
HWRREG0x05Write a HDD register.
HIDENT0x06Issues the IDENTIFY DEVICE command and sends the data.
HRDDATA0x07Read the data register.
HWRDATA0x08Write the data register.
HRDCHS0x09Read a block at a given CHS address.
HWRCHS0x0AWrite a block at a given CHS address.
HRDLBA0x0BRead a block at a given LBA address.
HWRLBA0x0CWrite a block at a given LBA address.

In many cases a status byte is returned by the interface.
Status byte table
Status byte synonymHex codeShort description
ERR0x20Error
CSUMERR0x21Checksum error
RDY0x22Ready
NOSUPP0x23Command not supported. (Not used in V7.2. A not supported command does simply nothing.

Address bytes for HRDREG and HWRREG
RegisterHex codeBits
Data0x0200000010b
Error/Features0x0600000110b
Sector count0x0A00001010b
Sector number0x0E00001110b
Cylinder low0x1200010010b
Cylinder high0x1600010110b
Device/Head0x1A00011010b
Status/Command0x1E00011110b
Features/Device control0x1D00011101b

Detailed explanation and protocol:

Changes from software revision 7.2 to 7.3

A small HDD protocol bugfix and a new command to allow the host software to adjust the baudrate. After reset (power on or reset button) the module starts with a baudrate of 9600.

Notes on contructing the board

For the capacitators you should use the following ones:
Capacitator types
Cap. numberType
C1, C2, C10, C11, C13, C12, C14Ceramic, 16V or higher
C20, C21, C22, C23, C19Tantal, 16V or higher
C8, C9, C3, C4, C5, C6, C7Elko, 16V or higher

If you use a selfmade PCB board, the holes are not through-contacted so you have to solder the top and the bottom layer seperately. To avoid problems you should solder it in the following order:

  1. Solder C10, C11, C12, C13, C14
  2. Solder IC1, IC4, IC2, IC3, IC5, IC10, IC9
  3. Solder X4, X1, X2, X3, X5, C8, C9, C4, C5, C6, C7, C3, Q1, C1, C2
  4. Solder C20, C21, C22, C23, X6, C19, R1, LED1, R8, R11, R12, R2, R7, D1, S2, IC7, IC8
  5. Solder R3, R4, R5, R6. YOu shouldnīt solder LED2, LED3, LED4 and LED5 as in the current firmware version of the board, the usage of these LEDs is not implemented. They would be on all the time.
After soldering, you should do the following steps to power up the board:
  1. Set your power supply to a current limit of about 20mA-30mA (if you have one).
  2. Connect the power.
  3. Check VCC on all ICs.
  4. Disconnect the power.
  5. Put IC4 in. Check for ~+10V on pin 2 and ~-10V on pin 6.
  6. Disconnect the power.
  7. Put the other ICs in.
  8. Set your power supply to a current limit of about 150mA.
  9. Connect the power. The circruit should drain about 75mA-120mA, if you use LS-TTL ICs. I donīt know what it drains if you use HCT ICs, because Iīve only used LSTLL yet.
You HDD interface board should be ready. The on-board voltage regulators are able to supply about 900mA +5V and 1A +12V. These voltages can be used to power a HDD. Note that they need a heat sink. If you donīt power the HDD with the board you need at least a small heat sink on the +5V regulator (7805), because the board drains about 100mA with LSTTL ICs.

Which HDDs I used for testing

As you can see, I didnīt use any new ones, because I didnīt know if I would blow up one (or more) during testing. I used them, because I can live without them (Which means that I donīt need them really.). You should also use a not-needed HDD for testing, because you wouldnīt love it if you blow you brand new ultra high speed 15TB harddisk because of e.g. a silly soldering mistake.

Pictures of the interface

You can view them here


7> Additional documentation (or: where I got all this from)

TOP

The main resource was the ATA3 standard draft revision 3. It can be found here:
d2008r7b.pdf

I also used this text file a bit for orientation:
ide.txt

Thatīs all. You shouldnīt need more for what Iīve done.


8> FAQ

TOP

Q: What about CDROM drives?
A: I donīt think that a CDROM drive is really needed for a MCU application. Most drives use ATAPI commands. You would have to implement them (firmware + host software) but the interface itself might be the same.

Q: What about CD-Writers?
A: Youīd have to be very good to prevent a buffer underrun. Read "What about CDROM drives?".

Q: What about Floppy drives?
A: At the beginning of this project (the planning in my head) I wanted to make a floppy disk drive, because of the removable media. But floppies are *very* stupid drives. To write to any magntical storage media you need to modulate the data. This modulation has to be done *external* for floppy drives. You canīt transfer the data directly like with the HDD. This makes is very complicated unless you use a floppy disk controller IC which are not easy to get and SMD most of the time.


HOME

Copyright (C) 2003 by Wiesner Thomas

Last change: November 11th 2006