Usually this represents the very basic program someone can compile. In this case it's a true salutation to the whole world - The Internet.
With the FPGA around, connecting a simple ethernet controller from Microchip (the enc28j60) was a piece of cake. The chip interface is a simple SPI slave port that even provides 5V tolerant IO's.
An experimental linux driver for kernel 2.4 is easily found here: http://elinux.org/Enc28j60 (linux kernel 3.x tree already has support fot this chip). So, all I had to do was to rewrite the SPI function calls, and that was it...
My kernel image size has grown significantly with the addition of network support, so memory limitation is (again!) my greatest pain.
Here is a small video showing the system running the 'boa' web server (it show nice comments during playback):
Having reached this far, and starting to struggle with low memory issues, I've lost my mind and decided to put all this stuff on a PCB!
On the next post I'll show the specifications, peripherals and the PCB itself.
Having a working kernel image and a serial port is just not enough! I needed peripherals...
Old peripheral chips are hard to find and I din't have any around, but I had in my junk box some old FPGA from Xilinx. It's a XC4010E in a PGA package with 191 pins and it runs from 5V... perfect!
Also, since I need to add more features to the system I also need more ram and flash. I've brought 4x 512Kb cheap (around 3€ each) SRAM and replaced all the ram in the breadboard. Also bought 2x512Kb FLASH and replaced the old (smaller) FLASH chips.
Ended up with 2Mb RAM and 1Mb FLASH memory. This should be enough to start porting kernel 2.4.x. for the board.
After some long hours of coding and re-coding it finally booted!
I've used the latest pre-compiled GCC toolchain (4.2.4) and the latest (at that moment) uClinux-dist (20111111). Re-used most of the code from the Motorola Dragonball family (MC68328).
So, having a nicer and newer kernel booting and running up, I decided to wire up that old FPGA.
My first attempts were just to see if that thing was still alive. The big headache was to wire all those ground and vcc pins. After finally finished, I've coded up a very simple verilog counter and programmed that old silicon piece using the JTAG port. And there it was, counting up (like it was supposed to be).
The FPGA can be programmed as if it is a simple 8-bit parallel peripheral. I've wired up the 8 data bits directly to the cpu databus, the address decoded feeds the FPGA chip select pin and the write/read pins are connected to the respective pins in the system (provided by one of the GALs). This way, the FPGA is seen by the CPU as a 1 byte memory location.
To program the FPGA all that is needed it so send byte by byte the generated bitstream. If everything ok, the DONE led goes bright.
4GB SDHC card
Mass storage memory is so cheap these days. Having a large amount of memory available in my system will allow me to move most of the romfs contents to the sdcard and more important at the moment, whenever I want to try new stuff, simply compile in the laptop and copy to the SDcard.
The new cards are 3.3V parts. I needed a voltage converter to wire the sdcard to the system so I used a simple 5V to 3.3V converter. Only the signals that go to the SDcard get converted because the FPGA can nicely handle 3.3V signals (just set the voltage thresholds to TTL in the FPGA config).
Having everything wired up, I wrote a simple verilog SPI master module.
The module when receiving a byte from the CPU, dumps the byte to the SPI mosi pin while at the same time, samples the miso pin. When reading the FPGA the CPU gets the last sampled byte.
The clock source for the FPGA is an oscilator module I had around rated at 35MHz.
I divide the clock by 2 in the FPGA and feed the CPU with a magnificent 17.5MHz clock! (remember that this is a 8MHz rated CPU). I've also tried using a 40MHz module, but if I sneeze or take a deeper breath, the system hangs!
Here is a video showing the kernel boot, mounting the sdcard and running some shell commands.
Next step is to add connectivity to the world: the internet!
A few months ago I was dumping out some old things to the trash when accidentally stumbled into those old yellowish breadboards still holding tight the magnificent 68000 cpu. I stood there for about 5 minutes admiring all the patience I had a decade ago wiring up all those pins. Suddenly a nostalgic feeling had taken over my mind, and all I could think at that moment was "I really need 5 volts".
I was about to know if the mighty 68breadboard000 was still rock n' rolling. I've connected the serial port and applied power and there it was, the system was up and running ready to accept commands from the serial port!
After playing some time with it, doing some memory dumps and tests, the same old question came back: "What the hell am I going to do with this?".
For a few days the whole system was left untouched in my desk... as usual. And one day I was googling around when the word "uClinux" made a spark in my brain. I looked to the 68000, looked back to the word "uClinux" and its fate was obvious: "Run some linux code in that old junk beauty!".
I've had an experience with uClinux in the past with a Coldfire microcontroller although I hadn't done much back in that time since I used a pre-compiled kernel image.
Dressing up for the party
The system was far from being able to run such operating system. It had a small amount of ram, the serial port and was slow and I had no timer for periodic interrupt. The flash memory was enough for the boot, but userland binaries had to be cut to the minimum.
SRAM: The system only had 128k SRAM (4x32Kb) and I had four old 128Kb around. What I didn't have was room to place those huge chips so I've wired them up in two extra breadboards (I had to dismantle a Z80 to get those!). Once wired up it was time to connect that half megabyte of ram to the 68k totaling 640KBytes of ram.
Memory upgrade: Check!
Serial port: The system had a USART chip (from the 8051 microcontroler series) wired up. It only had a 1byte buffer and without hardware flow control, buffer overruns occurred frequently. Since a uClinux kernel + romfs can be significantly large, I needed to have a way to upload the image to the system, fast!
I had this spare USB module where the interface is an 8-bit parallel bus, with 4 control signals (/rd, /wr, txe, rxf). Wired it up to the cpu upper half of the databus and connected the control signals with basic logic ports. When connected to the PC USB port it is seen as a standard (fast) serial port.
Fast serial port: Check!
Bootloader: The way I always used the system was loading to the ram and running code from there. Since I needed the ram available fot the kernel, I had to write the image directly in the flash so I've coded a simple bootloader in that beautiful assembly language (no kidding, it is really beautiful!). The working principle is simple:
Wait for a key press on the serial port for 3 seconds (not accurate seconds).
If no keypress, boot from a specific flash address where hopefully kernel code is located.
If a key is pressed, start the bootloading part.
Bootloader receives srecord files. If it detects that the destination address is flash, load everything to the ram and at the end of the load cycle, write everything to the flash (and verify). At last boot from flash.
If the destination of the srecord if ram, load to ram and boot from there.
I was facing some weird behaviour during the flash write, later I realized that the bootloader can't be executed from the flash and write on it at the same time! The solution was simple: When the bootloader starts, it copies itself to the ram and then runs from there.
Bootloader: Check!
Periodic timer interrupt: This final piece of hardware was missing from the system. It is a vital component to enable any multitasking operating system to run. It is responsible to make the cpu enter a 'supervisor' mode and switch between tasks. My first approach was to use a counter and connect one of the upper bits to the interrupt logic with some latch so that I could reset it in the interrupt routine. It was a bad idea... Didn't work well so I just ended up with a simpler solution: a 555 timer! The interrupt interval is set by a resistor and capacitor. It's not accurate but it's good enough to do the job!
Timer interrupt: Check!
Let the compiling begin!
As a first approach I've used as base code the board from Weiss Electronics: SM2010. Apparently that board also uses an 68000 cpu. From the few documentation I could find I know It's some kind of industrial controller board with 6 serial ports and (at least) 2 hardware timers. The guy that ported uClinux to that board did most of the work. He ported kernel 2.0.x and for a start it was good enough. I ended up by adapting the hardware part of the kernel: hardware timer, ftdi245 serial driver and ram/rom locations for the linker.
A few compilations later there it was! The old 68000 up and running uClinux!
I've also made a small video showing the kernel bootup and some commands being issued.
But the job wasn't completed! My ultimate goal is to run kernel 3.x in this old piece of hardware!
So my next step was to make a fully functional kernel 2.4.x. and there was no SM2010 board in the kernel tree!