• Long time, no C!

    Tobias Rathje08/14/2018 at 18:46 5 comments

    It's been a long time since I have posted any updates on this project. Family life has taken up most of my spare time, but mostly in a good way :-)

    But in the limited spare time I have left, I can't seem to let this project go. Whether I'm just bitten by the m68k-bug or that I find it incredibly cool to be able to run a modern OS with virtual memory and all the bells and whistles on a homebrew board with a 30 year old CPU, I don't know.

    The rather fragile prototype has been sitting on a shelf mostly just humming along, often reaching over 100 days uptime. In an earlier log I stated that I consider the hardware part done, but as time went by I realized that this is not entirely true. The project is not done before I have made the T030 into one single board capable of running Linux. Preferably something others can build and learn from without too much hassle.

    So the T030 mk.II is very much work in progress at the moment. Here is what the new board looks like:

    It is pretty much the original prototype merged into one single board, with a few notable differences:

    The DRAM controller can now handle 16 MB SIMMs giving a total of 64 MB. You might ask why I didn't just take the plunge and use 72-pin SIMMs instead of the ancient 8 bit 30-pin SIMMs. The only reasons I have is that I already had bought a number of 30-pin SIMM sockets and that I want to be careful not too change too many things at a time when doing the new design. Well, the mk.III will probably use 72-pin SIMMS.

    While it is cool to have the ubiquitous 555 in any hobbyist project, I have replaced the original reset circuitry with a DS1233 MPU supervisor to provide a stable power-on reset.

    Last but not least, I have added an IDE port for attaching either a real harddisk or a CF card for much faster storage that the slow SPI-based SD card interface. The IDE interface is basically just two 74LS245 bi-directional buffers (still not mounted in the picture) with a little additional logic added to the glue CPLD, so it appears as a 16 bit memory mapped port. From a couple of other designs a have noted that it is a good idea to swap the two bytes in the 16 bit port to provide easy compatibility with disks from little-endian systems ie. x86.

    Thats it for now, more project logs to come!

  • Linux driver progress

    Tobias Rathje09/11/2016 at 19:23 0 comments

    A working serial driver for the UART in the 68901 MFP is now a reality:

    This presentation provided a lot of valuable clues:

    http://free-electrons.com/doc/serial-drivers.pdf

    At it's present state my serial driver only implements the most basic functionality. The mctrl and set_termios calls are not implemented and the driver relies upon the ROM BIOS to initialize the UART.

    And now we have a shell:

    But Linux is not much fun without storage and networking, is it? So I have also managed to create a rudimentary SPI master driver for the TP3465 MID chip.

    And with the SPI bus initialized as follows:

    /*
     * SD card SPI node
     */
    static struct spi_board_info mmc_spi_info[] = {
        {
          .modalias         = "mmc_spi",
          .mode             = SPI_MODE_0,
          .max_speed_hz     = 3125000,
          .chip_select      = 0,
        },
    };
    
    /*
     * Ethernet SPI node
     */
    static struct spi_board_info enc28j60_spi_info[] = {
        {
          .modalias         = "enc28j60",
          .mode             = SPI_MODE_0,
          .irq              = IRQ_USER + 15,
          .max_speed_hz     = 3125000,
          .chip_select      = 1,
        },
    };
    
    
    we have the TP3465 driver talking to both the SD card and the ethernet module:

    Root filesystem on SD card:

    Ethernet is working, and we can reach stuff on the internet:

    Notice the very round ping times, I believe they are caused by the MFP timer driving the scheduler only having 8 bit resolution.

    I have configured two GPIO lines on the MFP as interrupt inputs, one for the ENC28J60 and one for the TP3465. Ethernet interrupts are working fine, but I have not yet managed to get interrupt based SPI transfers to work even though it is supported by my SPI master driver. Right now I am unsure if it's a hardware related problem or if there's a bug in the driver.

    Naturally the SPI transfer speed is very limited, and that shows particularly with the SD card device:

    Ughh, painfully slow!

    Trying to boot using the standard Debian based root filesystem proved a bad idea, so in order to make a somewhat usable system, I have created a very simple startup script using the busybox-based init. The script creates a tmpfs-based ramdisk at /rbin and installs a static busybox binary onto that. /rbin is then prepended to $PATH when a user logs in which results in the simple busybox versions of ls, cat etc being used.

    Output from the startup script:

    I have also installed the Dropbear lightweight SSH server. Once a SSH session has been established it runs fine with no noticeable lag, but the initial key exchange takes a good three minutes. Retrocomputing demands patience... :-)

    And of course the lynx web browser is working with the retro-site:

  • But does it run Linux?

    Tobias Rathje08/02/2016 at 12:42 1 comment

    Getting a recent Linux kernel to run on the T030 turned out to be much less painful than I first anticipated. Mostly because someone had allready done a lot of the hard work.

    When I started putting the T030 together, I was not aware of any recent homebrew projects using the 68030 processor, but a couple of months ago I found this:

    https://www.retrobrewcomputers.org/doku.php?id=boards:ecb:kiss-68030:start


    The KISS-68030 is designed by John Coffman and features a very nice, clean and simple design with a DRAM controller implemented in three GALs capable of running two 72 pin SIMMs.

    And Will Sowerbutts has ported Debian Linux to the KISS-68030:


    https://www.retrobrewcomputers.org/forum/index.php?t=msg&th=38&start=0&


    Check out his videos, they are very informative.


    Will's kernel patch has been the most valuable resource I have found online for porting a recent Linux kernel to a homebrew m68k-based board. With that at hand, it didn't take many hours of work before I had the first kernel messages spewing out on the console of the T030.


    I did run in to a few obstacles though. Normally the Linux kernel expects RAM at address 0x0 and starts from 0x1000, but the T030 has ROM at 0x0 and the chunk of 16 MB RAM at 0x1000000.


    It took me a while to figure out, but the assembly code in arch/m68k/kernel/head.S is fully relocatable and runs fine from 0x1000000. No need to mess with the kernel linker script, which I tried at first which didn't work. All I needed was to add transparent address translation for the MMU for the second last 16 MB chunk of the address space for the memory mapped IO (ROM, SRAM, IO and DRAM areas are mirrored throughout the address space).


    I have added functionality in my ROM BIOS to supply the bootinfo structure at the end of the kernel image, which contains parameters like RAM location and size and the kernel command line.


    With that in place, and with timer A in the 68901 MFP set up as timer tick for the scheduler, I was able to load the kernel to the point where it tries mount a root file system and start init. Without any real storage available yet, I have created a small initrd image with a statically linked busybox binary and a small shell script which outputs some stuff to /dev/kmsg (no real TTY device available yet, only the simple boot console).


    Then I ran into another problem. No matter what I tried to use as init, the kernel just got an "unexpected bus error" and died. Further debugging revealed that the culprit was floating point instructions. But shouldn't the FPU emulation take care of that? A good number of hours later, I found the real problem: An error in the glue logic caused the ROM to respond during coprocessor bus cycles in CPU address space, resulting in a bus error exception instead of the F-line emulation exception needed for the FPU emulation to work. Doh!

    Glue logic CPLD updated and we're good to go:


    Notice the kernel messages with the 68901 serial driver. That is work in progress and it doesn't work yet. Before this project, I have never done anything with the Linux kernel source apart from just compiling it for different platforms. In other words, I still have a lot to learn about kernel programming and device drivers, so it will probably take a good number of attempts before I have a real TTY driver for the 68901 UART.

    When that is complete someday, it should be possible to get at real shell. Then the next thing will be a SPI master driver for the TP3465.


    Until then, the T030 can only spew out the output from a couple of commands to /dev/kmsg, but I guess it's enough to say: Yes, the T030 runs Linux... :-)

  • Hardware complete, sort of...

    Tobias Rathje06/18/2016 at 21:36 0 comments

    The T030 has now been equipped with an ENC28J60-based ethernet module along with an SD card adapter. At first I created a simple SPI bitbang driver that used a couple of the GPIO pins on the 68901 MFP. It worked fine, but naturally it was pretty slow. My first intention was to make a SPI master with yet another CPLD chip, but then I discovered the TP3465 Microwire Interface Device, which is essentially a complete SPI master with an 8 bit parallel interface to the host processor. This has been added on a separate daughterboard as I ran out of space on the prototype DRAM board. The TP3465 communicates perfectly with both the SD card and the ethernet module.

    I now consider the hardware part completed for what I am trying to accomplish with this project.

    The ROM BIOS for the T030 is also progressing. I have created a rudimentary TFTP client on top of a the simple TCP/IP stack from tuxgraphics.org, which I have modified to run on the T030. I have also integrated the FatFs library, so it is now possible to download binary images from a local TFTP server, and store and load them from the SD card.

  • I hate DRAM!

    Tobias Rathje05/15/2016 at 22:43 1 comment

    The time has come to add a lot more RAM. In order to boot a recent Linux kernel, I guess I need at least 8 MB and probably even 16 MB to be on the safe side.

    32 AS6C4008's (or equivalent through hole SRAM) would require several additional boards and more importantly break the budget for this project.

    So I have no other options than to dive into the wonders of dynamic RAM. After having tinkered with a DRAM extension board for a couple of weeks, I can certainly understand why a lot of hobbyists place these devices somewhere between "black magic" and "just not that easy to work with".

    But now I have a 16 MB RAM board based on 4 x 4 MB 30 pin SIMM's which is stable most of the time...

    I have implemented a DRAM controller in a second MAX 7128 CPLD. The controller is implemented as a FSM in VHDL and performs CAS before RAS refresh, address mux and data size decoding. I have never used VHDL before but a design example along with some sample code from an RD document from Lattice got me going in the right direction.

    The DRAM controller code could use a cleanup and several wait states could probably be eliminated, but for now I consider it a huge success that it can pass a RAM test without crashing :-)

    I have also added some more bypass capacitors to even out the current spikes that the DRAMs generate.

  • Software progress

    Tobias Rathje04/06/2016 at 22:14 0 comments

    I now have a working cross-compiler and a C runtime environment and libc based on gcc 4.9.2 and newlib 1.18.0 with floating point emulation. I have created a linker script for the T030 along with some startup code and the first prototype of my own C based ROM monitor is now ready:

    T030 ROM BIOS v1.00                                                                               
    -------------------                                                                               
                                                                                                      
    Checking RAM: 512 KB OK                                                                           
                                                                                                      
    #> h                                                                                              
    d - Dump address: d                                                                         
    h - Help                                                                                          
    g - Run: g                                                                                  
    r - Dump registers                                                                                
    u - Run in user mode: u                                                                     
    w - Write single byte: w                                                              
    x - Transfer file with XMODEM: x                                                            
                                                                                                      
    #> x 90000
    Starting XMODEM receive...                                                                        
    CCC
    
    Done, bytes received: 36992, write errors: 0
    #> g 90000
    
    T030 TEST MONITOR v0.02
    -----------------------
    
    *> r
    SR: 2100
    SSP: 000fffa0
    USP: fffffffe
    VBR: 00080000
    CACR: 00000000
    
    *> g 000000
    Exception #4 (illegal instruction) SR: 2104 PC: 00000000
    
    

    A simple interrupt routine to use one of the MFP timers to blink a led can be written like this:

    void __attribute__ ((interrupt)) timerb_isr()
    {
    	static uint8_t c;
    
    	if (c++ >= 50)
    	{
    		if (bit_is_clear(MFPGPDR, 0))
    			bit_set(MFPGPDR, 0);
    		else
    			bit_clear(MFPGPDR, 0);
    		c = 0;
    	}
    }
    
    void enable_led()
    {
    	MFPTBCR = 0;
    	MFPTBDR = 255;
    
    	// enable interrupt for timer B
    	bit_set(MFPIERA, 0);
    	bit_set(MFPIMRA, 0);
    
    	set_vector(72, timerb_isr);
    
    	// start timer B
    	MFPTBCR = 7;
    }
    

    I have also updated the glue logic in the CPLD so the CPU now runs at the full speed, a whopping 25 Mhz.

  • It's Alive!

    Tobias Rathje03/17/2016 at 21:47 0 comments

    The board is now fully assembled:

    Notice the adapter I had to make to correct my design mistake with the RAM address bus. Apart from that It's very satisfying to see the finished board, as this is my first real PCB design.

    But does it actually work?

    To test the board, I have borrowed the monitor program from Jason Westervelt's 68020 project: https://hackaday.io/project/8725-rhombus

    As my hardware and glue logic is a little different than that from the original application note from Motorola, I have changed the base addresses for the ROM, RAM and MFP.

    The first attempt to fire up the board didn't result in any output on the serial port :-(

    The logic analyzer revealed that the processor was indeed alive and executing instructions, so far so good. But it was stuck waiting for an empty transmit buffer on the MFP, hmmm... The scope showed no output from timer D and C on which the serial port depends, so maybe the MFP wasn't getting properly initialized.

    After going through my schematic and the data sheet for the MFP, I discovered another design glitch: The register select lines for the MFP (RS1-RS5) are supposed to start from A1 and not A0 as I have done. I assume this is for compatibility with the 68000 without dynamic bus sizing. But this should be no problem on my 68030, so I can just omit the one byte spacing between the MFP register.

    Second attempt:

    Woohoo, it's alive! :-D

    I have yet to find out why the memory detection only shows 32KB as I have 512KB and it all appears to be addresable and functional.

    As the monitor program allready has TRAP 15 routines defined to be compatible with the Easy68K simulator it should be pretty straight forward to get EhBasic running on my board.

    The first attempt made it to the "Ready" prompt, but it didn't react to any input on the console. After some debugging I found an error in a conditional branch in the trap code resulting in an invalid instruction exception. Once again the old HP dinosaur with its state listing was incredibly handy in figuring out what the processor is actually doing. Here shown during the initial RAM test:

    With the trap code fixed:

    The next step will be to setup a cross-compiler toolchain based on gcc and probably the newlib libc implementation, and try to create my own monitor, trap code and exception handlers. I have an idea that I will try to hook up an SD card to the GPIO pins on the MFP and implement a FAT32 library so I can load stuff easily.

    Btw, I am quite surprised at the modest power consumption of my board. I was worried that I had screwed up the power distribution to the processor with way too narrow tracks, but the board in its current state only draws about 250 mA when running code and outputting stuff on the serial port. It should be noted that currently I am only running the processor at 12.5 Mhz, so I guess it will draw more current running at full 25 Mhz.

  • Board assembly part II - Free run

    Tobias Rathje03/02/2016 at 22:21 2 comments

    With the CPLD, crystal oscillator and reset circuitry in place, it's time to mount the CPU and try to get it to cycle through the address space by grounding the data lines.

    This is also known as free running mode, more on that here:

    http://www.bigmessowires.com/2014/10/29/68k-free-run

    As Steve puts it: "It seems that blinking an LED in free run mode is a rite of passage for 68K projects."

    And this is exactly what I am going to do next.

    I have buffered address lines A21 to A25 through the CPLD in order to avoid driving LEDs directly from the address bus. DSACK0 and DSACK1 are grounded.

    And it works! :-D

    Here with the LED connected to A21 and the logic analyzer hooked up to four of the lower address lines. The plug with the frayed ribbon cable is a makeshift adapter to ground the data lines.

    The result is one of the worlds most complicated LED blinking circuits. But it proves that the CPU is functional.

  • Board assembly part I

    Tobias Rathje03/02/2016 at 01:13 0 comments

    I started with the CPLD the ensure I have a working JTAG interface:

    After verifying that the JTAG port is alive and the CPLD is programmed with the first version of the glue logic, the oscillator is mounted and the various clock signals checked:

    In the first version the 25 Mhz clock is divided to 12.5 Mhz to match the clock in the Application Note 1015 for the 68020. According to the documentation my 68030RC25 can run down to 12.5 Mhz, when I have a working prototype I can increase the clock. The clock is also divided by four as clock for th MFP.

    Btw, I got a HP 1631D, It's awesome! :-) (and noisy).

    Reset generation also in place:

  • Board designed

    Tobias Rathje03/02/2016 at 00:52 0 comments

    I have now finished the first board design:

    After I sent the gerber files off for fabrication, I found out that I have made a damn stupid mistake necessitating an adapter for the RAM chip. When I contemplated a viable design I first made a schematic with a 32 bit RAM interface, and after I changed the design to a simpler 8 bit design, I forgot to change the adressing so the address bus for the RAM is shifted two bits. Oh well, this is my first time using KiCad and the first time I have ever designed a real PCB, so I guess such mistakes are bound to happen. If the rest is OK, I can live with that. On a second note I also think I could have made the power distribution better, anyway, time will tell if it works.

    After waiting for some days, I received the finished PCB from the manufacturer:

    Nice stuff!