68000 SBC bring up

      No Comments on 68000 SBC bring up

Five MINI000 boards arrived just after Christmas. Annoyingly I got stung for the import duty, but fair enough. They were still very cheap! The quality looks fantastic, though its hard to tell from a camera-phone shot:

The following was done over the course of a few weeks. Unlike the MAXI09 board bringup, I took my time and found I enjoyed the task of testing out the board much more. First up I beeped out a few critical connections, especially some Vcc and ground pads. Everything appeared to be in order.

As per the usual process I soldered parts in an order where I could test out the board in a sensible sequence. First up, the power supply parts: the SR05S05 (PDF) switching regulator, barrel connector and LED. So far so good: 5V on the Vcc rail and a glowing LED.

Next was the CPLD and JTAG header, along with the LED attached to the CPLD, and the oscillator can. My plan was to program the CPLD with a trivial flasher design using a 24bit counter to divide down the 8MHz oscillator I had installed. A 24 bit counter will wrap after 16 million (approximately) counts, meaning the LED, when attached to the high bit of the counter, should stay on and off for about a second. This all worked first time, and I took a picture to prove it:
The biggest bit of work needed to get this going was to setup the pinning on the CPLD. Though I didn’t need to assign all the pins to get the flasher working, I did it here anyway.

Next was the reset circuit: 74HC03 (quad NAND gates with open collector outputs), DS1813 (PDF) reset generator, and push button. I immediately noticed my first problem: the power pins on the 74HC03 were not connected. This was annoying. The cause was the strange arrangement for power pins used in gates in KiCAD. Unlike LSI or MSI type parts, individual gates do not have an explicit power connection, so the netlist for a gate does not include links to the power rails. Reading up on the subject, it seems that power connections are in another “Unit” and these symbols must be added to the schematic so the IC as a whole gets power. Oops! History repeated itself and this was quickly solved with some small jumper wires on the bottom of the board. The reason I did not spot this problem when laying out the board is, of course, the hidden power planes, which do not require any trace routing.

After fixing the missing power connections, and attaching my old Logic 16 logic analyser: success, the /RESET signal appeared correct.

Next, the job of soldering enough parts to get the board capable of running code: the 68000 itself, and the two EEPROMs. Naturally the computer would be programmed to flash the LED attached to the CPLD.

First up, a description of the new memory map and the changes needed to the software, relative to the previous breadboard based 68008.

The MINI000’s memory map, currently, is as follows:

  • 0x000000 – 0x0fffff : SRAM (1MB)
  • 0x1xxxxx : LED
  • 0x2xxxxx : DUART
  • 0xf00000 – 0xf0ffff : EEPROM (64KB)

The CPLD on the board is attached to A23, A22, A21 and A20. Ie. the top nibble of the 6 used by the 680000. These four signals are used to generate the needed chip selects.

To complicate things a little, the MINI000 uses a trick used on nearly all 68000 based microcomputers – as originally described by Motorola in Application Note 897 (PDF) – to put the EEPROM at the beginning of the memory map whilst (and only whilst) the initial Stack Pointer and initial Program Counter are fetched. This allows the 256 entry exception vector table to be stored in RAM, instead of it being fixed in ROM. This works by counting /AS assertions after reset: four bus cycles are needed to obtain the initial stack pointer and initial program counter. Before four /AS assertions have been counted, the address decoder always selects the EEPROMs, regardless of whats on the address bus. None of this affects the memory map of the running computer. Of course, at this point there actually wasn’t any RAM attached to the computer so reads of the exception table will result in nonsense being read back, but I’d previously proved this mechanism on the 68008 breadboard.

The changes to the software (code and the linker script) accommodate the changes to the memory map, but more then that is needed: unlike the 8 bit databus’ed 68008, to run on a 68000 the ROM image must now be spread across two EEPROMs, with the upper byte (on even addresses) and the lower byte (on odd addresses) being on two different ROMs. This requirement exists because of not using EEPROMs which are 16 bit wide.

Splitting out odd and even addresses from a source image was made easy by the usage of binutil’s objdump program, which has the ability to copy out the N’th byte into different files. For completeness the code in my 68k-tests repo can build both 68008 code for my breadboard computer, and code for the MINI000 board computer. At some point I will abandon the breadboard target, as the breadboards have, in the course of soldering up MINI000, been scavenged for parts.

I figured I’d need to pretty often program AT28C256 (PDF) EEPROMs in the course of the MINI000 bringup, so I decided to finally hack my old EEPROM programmer to attach it to the computer nicely. For some reason, when I designed the programmer I used a 3.5mm jack to attach the USB UART cable. This has since been long lost. I’ve since soldered on a USB UART cable directly to the board:(Wow, I can’t believe it’s been 5 years since I built that little programmer.)

A nice improvement I think, even if it does look ugly. The programmer can also now be powered directly from a single USB connection, instead of needing power via the USB-B socket.

I initially had great trouble getting the MINI000 running, when equipped only with EEPROMs and the LED attached to the CPLD. It somehow took me several hours to realise I was missing the write protect jumper. Without this soldered and jumpered to write protect,  the /WRITE pin on the EEPROMs was left floating. It was unsurprising that the MPU could not run any code stored there. After soldering the jumper pins on and attaching a jumper, success: a nice flashing LED, this time under control of the 68000!

Adding the two 512KB SRAMs, and exercising them by holding a flashing rate in those RAMs and modifying that rate as the LED flashed, did not present any challenge. Here’s a picture of the board in that state:

At this point I was pretty pleased. Other then the missing power connections on the 74HC03 everything was going well. Adding the DUART, though, proved to be a draw-out exercise in frustration. Eventually however, I overcome the problems.

First of all, when I came to solder the socket for the 28 pin DIP part, I realised I was out of such sockets.

(I really need to get more organised when I start projects and move the parts I need for a build into a project box, then I would have known I was missing DIP28 sockets earlier and ordered some in advance.)

Not wanting to wait around for a few days while the parts I ordered arrived, I decided to have a go at desoldering a socket from one of my old 6809 boards. This took a while but I eventually managed to extract a socket. This is by far the biggest bit of desoldering I’ve done and it wouldn’t have been possible without a decent solder sucker:

These pumps are better then the more common type because the nozzle is made of silicon and not ridged plastic, which means it can get much better suction. If I was serious about desoldering I’d invest in a desoldering station, but I can’t really justify the cost.

Anyway, after installing the salvaged socket, 3.864Mhz crystal and accompanying 22p caps, and actually inserting the SC2681 (PDF), it was time to see if I could get any serial data out of the board.

The first issue I encountered was the sending of nonsense characters. This turned out to be a dry joint on one of he address pins. How this happened I’m not sure, but beeping out all the connections between the DUART and the 68000 MPU clearly revealed a broken connection. I initially feared it was a defect with the PCB manufacturing process, but thankfully this wasn’t the case.

After fixing this, some success: the board could send a single character and then nothing, seeming to hang inside the loop which polls the SPA register in the DUART. Here is the code from the putchar routine, as I initially wrote it:

| put the char in d0

putchar:        btst.b #2,SRA2681               | busy?
                beq putchar                     | yes, look again
                move.b %d0,THRA2681             | put that byte

The btst instruction will read from the SPA register in the DUART, then set the condition code based on bit 2, which is used to indicate wether the UART is ready to receive the next character.

Since it’s almost impossible to debug problems like this without knowing what’s in the SRA register, I decided to add a LED bar graph and output the value on 8 of the expansion connector’s user IO pins, in a similar way to how I implemented an 8 bit wide addressable latch on the 68008 breadboard computer. Since I already had an 8 bit wide addressable register implemented in the CPLD to control its LED, it was trivial to extend the output to cover all 8 bits, in this register instead of just bit 0, which was used to control to the CPLD’s LED.

Here’s a picture of the board in this state to more easily explain what I was trying to accomplish:

I then modified the putchar routine to look like this:

putchar:        move.b SRA2681,%d7              | get the SRA
                move.b %d7,CPLDLED              | output it
                btst.b #2,%d7                   | busy?
                beq putchar                     | yes, look again
                move.b %d0,THRA2681             | put that byte

At this point things started entering The Twilight Zone: the putchar routine was working, and the DUART was in fact sending out whole strings nicely. This had, and has, me scratching my head: the changes should have made no difference. I thought at first it might be a weird timing issue, so I replaced the output to the latch with a bunch of nops to introduce the same delay – no result; the UART was inoperative still and would only send one character. Seemingly only sending a byte (any byte value) out on the latch would cause the UART to work correctly.

I still have no idea why this is happening, but in a fit of desperation I replaced the SC2681 with my only XR88C681 (PDF) used in my first 6809 SBC and I had some joy: the DUART was working flawlessly with my original putchar routine.

I really need to understand this problem. I also need to properly dig into the timing diagrams for the operation of the busses, both for the 68000 and for ICs like the SC2681. I’ve had good success so far, but I feel a chunk of that is down to luck and not design.

One of the things I’ll need to tackle when I replace the 8MHz can oscillator with a 20Mhz one – the rated speed of the MC68HC000 I have in the board – is to properly insert wait states by holding off /DTACK on at least the EEPROM, in addition to the DUART which I’m currently doing. Calculating the number of needed wait states for each IC is going to be an interesting activity.

Luckily I now have a working board. I can experiment with the SC2681 in a more controlled environment by attaching one to some breadboard and playing with it there to understand exactly why it doesn’t work with the vanilla putchar routine.

The latest thing I’ve done is added in-place reprogramming of the EEPROM via the UART port, using the same mechanism and Linux-side code as the MAXI09 used. Initially I had a significant problem with this: starting up the board with the EEPROM write protect jumper set at Read/Write caused the computer to fail to start. It was fortunately pretty easy to determine what was going on.

For reasons currently unknown, at startup just before reading the initial vectors, the R/W pin on the MPU shows as write (ie. low). Since the ROM is aways selected at this point regardless of what’s on the address bus this causes the EEPROM to enter a write cycle, which inhibits read access for a small time (the write interval). I’m currently working around this in the VHDL by forcing the /WRITE line to high if the vectors have not yet been fetched, but I expect a more elegant solution is possible: within the address decoder, in the pre-vector state, only assert the EEPROM’s select line if the EEPROM is actually addressed to get the vectors ie. A23 down to A20 is 0000. This should cause the /WRITE line to go low on the EEPROMs, but with the chips not selected, resulting in no write cycle being entered.

On the bootloader front, there is one difference relative to the MAXI09 implementation of the flashing routine. The bootloader must always be present in the EEPROM, since there is no external ROM (MAXI09’s bootloader ROM is in the MuDdy FPGA). The EEPROM in the MINI000 is arranged as follows:

  • 0x0000 : Start of initial vectors (this is just to get the bootloader running, at run-time the vectors will be in RAM) (1KB)
  • 0x0400 : Start of the bootloader code (1KB)
  • 0x0800 : Start of real code

The flash routine writes received data into the EEPROM from 0x0800, after copying itself into RAM and running there. The booloader should itself never change except when the EEPROMs have been removed from their sockets.

This all works really well: I finally do not have to extract the EEPROMs from their sockets and program them in my programmer. I have tested this by uploading a couple of example programs:

  1. The first is a get string/put string demo which utilises a UART channel.
  2. The second is the program which outputs patterns to the still-attached bar graph.

I have yet to finish attaching all the parts to the board. The main ones currently missing being the dual RJ45 socket and MAX232 (PDF) level shifter. I’m hopeful this will go well; hooking up a proper RS232 console cable seems much more civilised then using a fiddly USB UART. Attaching and exercising a piezo buzzer is also going to be fun. I guess I should also solder the various decoupling caps.

After that, I really need to start on that machine code monitor, and upload the latest code to github in case anyone is interested.

In the mean time I’ve also been making decent progress with the MPCNC build, but I think I’ll write about that in another post…


Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.