Sunday, April 10, 2011

OR1200, Cygwin, SDRAM, Interrupts & the Red zone

So I didn't quite reach my goal of procedural images on the touch screen. I did run into some setbacks along the way that slowed me down but all of that is now resolved and I will go into that more below. The highlights of the week have been getting the SDRAM working, Getting interrupts enabled on the processor, learning about the red zone and just moments ago compiling the toolchain on Cygwin.


After much frustration I was unable to get a core from OpenCores that worked with the SDRAM. I had to port a bunch of code to compile on Quartus since it's Verilog support is incomplete. But all was for nothing since it didn't work at all. In the end I ripped the SDRAM module out of the DE0 SPOC example. The issue with that is that it is for the Avalon bus and a 16 bit one at that. With some finagling I built a bridge between it and the wishbone bus that takes care of most everything. There is still a bug in reads that causes more transactions to the ram than needed but I will look into that later. I will also probably need to use a wishbone-wishbone bridge to run the ram at 100MHz since at present it is taking 9 clock ticks to do a read. I am unsure if this will be fast enough to operate the ping-pong buffer for the touch screen but only time will tell.


I am not certain but it would appear that interrupts 0 and 1 are non-maskable. However unmasking them in the PICMR (Programmable Interrupt Controller Mask Register) is not enough. Interrupts in general must be enabled in the Supervisor Register. It is worth noting that the supervisor register can only be modified using a Read, Modify, Write method. Thus use GREAT CARE if you ever decide you need to modify a setting in the register. You need to be careful that you do not modify the register in an interrupt or exception whilst a lesser priority interrupt or the normal flow of execution is also modifying it (Your changes will be lost). My recommendation is set it and forget it. After that, only modify the register for critical sections (disable/enable interrupts) and everything will be fine.

Red zone

It is a little known fact (I didn't know it till 4AM this morning) that the OR1200 toolchain utilizes a Red zone. This means that code is free to use 128bytes beyond the stack pointer for temporary data. Which also means that your interrupt/exception handlers need to decrement the stack pointer by 128 on entry or you will screw something up (makes for a psychedelic experience on my touch screen). This isn't really documented and only after I asked the IRC about why GCC was generating negative stack references did I find out about it.


I got back to trying to make Cygwin work, I had long abandoned the subversion repository in favor of the one in GIT for my compilation on my laptop. I tried this on Cygwin and the results were less than satisfying. After some digging I found out why.

So heres how to get a working toolchain in Cygwin that can compile both c and c++ for the OR1200.
[Check comments for better tips on setting up cygwin from scratch]

Clone the GIT repository (Do not build!) following the instructions at

It is about 600MB so it will take a while.

Now we need to patch the uClibc build process.

So modify in the uClibc folder.

This bug has the lines that need to be changed.

Make sure you have the flex package in Cygwin

Now run "make". Thats it, no command line parameters.

Wait 1-3 hours.

When it is done the toolchain-out directory should have everything you need. I am still refining my makefile so there may still be kinks in that department.



That is basically the conclusion, don't do it. I have made so many subtle changes to the example it isn't even funny. BootReset.S in my firmware directory is the modified/fixed/hacked remanence of that example. At the very least take it but I recommend salvaging as much of the helper stuff from my code as much as possible. I am still working on it so I should improve over the next month and a half.

As always you can find my latest code here:
Till next time,


1 comment:

Noah said...

1) Get cygwin. Get these packages in cygwin:
-- git
-- gcc
-- make
-- Flex
-- libiconv
-- GMP 4.2+ (devel)
-- MPFR 2.3.1+ (devel)
-- MPC 0.8.0+ (devel)
-- zlib (devel)

2) Git the repo.
3) Git the submodules.
4) make on the directory

-- Be sure to get the development versions
of the cygwin packages that I put the
(devel) note next to.

-- Either use the cygwin git or make sure
that your windows git doesn't screw with
the line endings.

-- Take note to edit the correct
file (toolchain/uClibc/