Dual-boot ARM machine

Dual boot machines are usually thought as single computer booting two OSes. Mine is different - it is single OS (Linux 2.6.34 in this case) running on the same virtual CPU emulated on two different microcontrollers. You select your MCU by really hardware way - by physically inserting particular device into its socket.

Recently I noticed this project from Dmitri Grinberg. It is emulator of ARMv5TE class CPU running on AtMega1284. After a bit problems with sourcing 16MB 30-pin SIMM module I finally got one and tried his code. I designed my breadbord work to include two MCUs actually - one is original Mega1284, another one is place for 64-pin Microchip MCU. In fact, there could be PIC32 or PIC24/dsPIC33, as they are pin compatible. I populated it with PIC32MX795F512H, quite capable piece with MIPS core.
Using PIC32 to emulate ARM to run Linux is pure technical perversion, as PIC32 is itself capable of running BSD UNIX, at least two orders of magnitude faster than this toy. However it is nice academic excercise. You may try to run BSD UNIX on PIC32 emulated on Linux host system running on ARM emulated on PIC32. Sounds like great fun for long winter evenings.

dual boot ARM machine

Porting the emulator sources for PIC32 wasn't that difficult, main problem was rewriting DRAM routines. Interesting is that DRAM requires standard TTL voltage levels (2,4V as high level) on its inputs, however memory didn't accept 3,3V levels from MCU. Using open-drain feature and 2,2kOhm pullups on all IO pins solved this problem. Conversion from memory to MCU (5V domain to 3,3V domain) was simple, as I used 5V tolerant IO lines of PIC32.
Dmitri's original SD driver wasn't optimal. In order to simplify hardware he omitted CS line, so part of initialization seqence tries to get to sync with state machine in SD card by applying single clock pulse after every byte while waiting for valid response. After this procedure, there is no byte synchronization (usually ensured by CS signal), so noise can bring communication down. It works, but I found it unreliable with some SD cards or at higher clock speeds - anything above 2MHz failed, sometimes after tens or hundreds of megabytes of succesfully transferred data, sometimes after three sectors. That's why I replaced original SD driver with the one from elm-chan's fatfs. After this, reading and writing SD cards works as expected with clock speed 20MHz.
Dmitri's original work expects AtMega1284 running at 24MHz (overclocking from guaranteed 20MHz operation), however it refused to run correctly for me despite correct bypassing and stable 5V power. I don't like violating specifiactions, so I didn't try to figure what's wrong. Using 12MHz crystal I had at hand fixed all problems, however it ran at half the original speed.

PIC32 version is - no surprise - much faster than the AVR one. AVR emulator boots linux in 5'20 (five hours and twenty minutes) at 12MHz, yielding 3'12 boot time at maximal 20MHz. Response to simple commands is within minutes, ls command takes quarter of hour. PIC version boots the same Linux build in 15 minutes at 80MHz, with second Dmitri's SD image in 13 minutes, reply to simple commands in seconds, what makes emulator somehow usable. Effective emulation speed is cca 110kHz at 80MHz, compared to original 6,5kHz at 24MHz.

Hardware is quite simple - it comes from original schematics with a few changes. I used LF33 regulator to get 3,3V for powering SD card, level converting for SD card was done with 2,2/3,3kOhm reistors, LEDs got 330Ohm series resitors, not to mention decoupling capacitors on power rails of SD card and AVR MCU.
To this I connected PIC32. Address lines come to port D, data lines to port E, WE is port F0, RAS F4 and CAS is F1. All those lines are equipped with 2,2kOhm pull-ups to 5V. Yellow RED for SD read activity is at port B1, red LED indicating write activity is at B0. SD card is connected to SPI2 with CS line at port G9 (pull-down 22kOhm to keep compatibility with Dmitri's code). Serial console at 115kbaud is on UART5. Button is at port F5. Device expects 8MHz crystal, PLL is set to generate 80MHz internally. I'm too lazy to draw schematics for now, everything needed can be tracked from sources or from information above.

There is room for improvements, like implementing multi-byte DRAM access, like Dmitri did it in his second version that could bring serious performace increase. Fiddling with icache values didn't help as much as I hoped for, differences were in order of seconds for complete boot sequence. Interesting would be using modern SDRAMs instead of 80's style DRAMs (getting 16MB SIMM-30 module for appropriate price is really hard) or even SRAMs. More improvements can be done on Linux side, however building light-weight one is out of my knowledge by now. Volunteers are welcomed.

For download - sources for PIC32, boot log for AVR version and boot log for PIC32 version.
I used MPLAB 8.84 as IDE for development, Microchip C32 1.12 as compiler, all files were compiled with "-g -O3 -funroll-loops -fomit-frame-pointer" options, except of main_p32.c file, with options "-g -O2", linker set to 256B heap and 256B min. stack size. There is binary file and also MPLAB project in package.
See the LINCENCE.txt and README.txt files.



More pictures in my picassa album.



Updated 7.5.2012
Back to topics