Always Blame The Software (Part One)...

A project log for rosco_m68k

A full-featured Motorola 68k retro computer, starring a 68010 running at 10MHz

Ross BamfordRoss Bamford 06/08/2019 at 19:162 Comments

It's been a very frustrating couple of days on the m68k project. All my own fault, of course.

Some background: I've been hooking up the MC68901 MFP which will give me some GPIO capabilities, a UART (actually a USART but I'm not using the S), some timers and support for vectored interrupts. All was going pretty well - it's a lot less wiring than most of the other chips on the board (five address lines, eight data, a few control lines and a bit of extra glue logic).

Because I want to use it for vectored interrupts, its eight data lines have to be wired to the lower half of the MC68000's data bus. The 68901's data strobe is then hooked up to /LDS on the CPU, allowing the chip to supply the needed data at autovectoring time. This set-up means that the MFP's registers are all accessed at odd addresses - in my case, it's mapped into IO space so the registers start at 0xF80001 and occupy all the odd addresses up to 0xF8002F. For the code, I decided to put these into a separate file I could include in the main assembler source (extract below).

; MFP GPIO Registers

MFP_AER     equ     MFPBASE+$03
MFP_DDR     equ     MFPBASE+$05

; ... etc ...

With all the wiring done I added a bit of code to the existing ram test program (on Github) to initialise the MFPs GPIO and toggle one of the lines after each run through the RAM, allowing me to hook up an LED and get some visual feedback that the MFP was working.

In short, it didn't work. Worse, it made the whole board hang. Time to start debugging then!

I quickly realised (thanks to my address decoder blinkenlights) that it was hung waiting for DTACK, for an address in IO space. I've built a simple circuit that takes care of that specific situation (as the MFP likes to generate DTACK itself) so immediately assumed that wasn't working. I don't (yet) have a watchdog on DTACK to generate a bus error, so if DTACK isn't acknowledged, currently the CPU will just wait forever.

I broke out the meter and the analyzer and got to work to find out why the IO DTACK generator wasn't working. I discovered it was working fine.

I checked the 68901 was receiving the requisite 4MHz clock from the divider I put on the system clock. It was.

I checked the voltages around the board, and noticed they were still a bit shaky. In light of this I switched from the old daisy-chained power setup that has grown with the board to a star setup and threw some more capacitors on. The voltages were now rock solid (still a bit more drop than I'd have liked but well within tolerances) and the board still didn't work.

I checked all the connections, and found I'd accidentally wired the output of timer D to one of the address lines instead of the transmitter clock line. Since I wasn't enabling the timers yet I figured this wasn't the problem, but fixed it anyway. It wasn't the problem.

Eventually I realised that the CPU wasn't asserting LDS as expected for an odd address, and was instead asserting UDS. Cue several WTFs, more continuity checks to make sure I hadn't wired UDS and LDS backwards into the bus (I hadn't), and a serious amount of head scratching.

After a (long) while spent re-reading the CPU datasheets, staring at the code, checking various connections and swearing, my mistake dawned on me. You see, the extract of code above is the fixed version. The original had lines like this:

MFP_GPDR    equ     MFPBASE + $01

Which, with the assembler I'm using (I'm still using Easy68k for quick stuff as it has a convenient way to dump odd/even binaries) means "Set MFP_GPDR to 0xF80000, and then ignore the rest of the line because it's a comment". 0xF80000 is an even address, and all the registers were mapped there. The CPU is asserting UDS correctly instead of LDS. Lack of LDS means the MFP isn't aware it's supposed to be generating DTACK, and so it doesn't.

Cue major facepalm. Removing the spaces fixed it right up, the code ran perfectly, and the LED on the GPIO line flashed away merrily. I'd also fixed the power issues (which I've been putting off for a while) and tidied things up a bit, so I considered it a win (admittedly, a hard-won one).

You'd think after struggling with that for the best part of a day, getting the UART working so I can finally see something on a screen would be a piece of cake, right? Well, you'd be wrong. Stay tuned for part two...


Ken Yap wrote 06/09/2019 at 00:14 point

That sounds like you need a better assembler. A decent one would have flagged the "extra characters", not silently made a comment out of them. It's interesting that an online guide to it ( dissuades everybody from using it.

If you need to split the binary into odd even parts, I can recommend srecord ( which can do that and much more.

  Are you sure? yes | no

Ross Bamford wrote 06/09/2019 at 18:35 point

Yeah, Easy68k is pretty terrible to be honest, but this was the worst experience I've had with it so far. I've built a GCC cross toolchain with VASM as the assembler (I dislike GAS) for when I get into the "real" code and have just been using Easy68k for the small test programs to prove the hardware, but after this I think I'll make the switch.

Thanks for the tip on srecord, I'll take a look! I was planning to write a little utility that runs as part of the build to split the binaries, but it looks like I won't have to :)

  Are you sure? yes | no