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...