Slides from a <a>talk</a> given at the UKUUG 2006 conference derived from my final year project on the UWE CRTS degree which involved porting uCLinux to the Pluto 6 gaming control board.
4. ● Heber have developed their own in-
house monitor/executive
– It has drivers written from scratch by
Heber
– It is fast, and well understood
– We provide to customers drivers compiled
to Library object files
● However there is a problem...
– Future boards may use more complex
peripheral buses
– We will require more complex software
● E.G. TCP/IP stack, USB hosting
Project Origin
5. ● A version of the Linux kernel for
microcontrollers without a MMU
● First port in January 1998 by Rt-Control
● Differences to Linux - uClinux has:
– No virtual address spaces; applications must
be linked to absolute addresses
– No memory protection
– To have drivers altered to operate through
local bus instead of ISA/PCI, with bigger
interrupt vector ranges
Background to uClinux
6. ● Create development environment
– Obtain tool chain
– m68k-elf-gdb
● Create new board configuration
● Edit entry assembly in crt0_ram.S
– Set variables _rambase, _ramstart, _ramend,
_ramvec.
● Edit linker script in ram.ld
– Link to DRAM at 0x60000000
Porting uClinux to the Pluto 6
7. ● Crashed in kernel during boot:
– Assembly variables were wrong
● #define MEM_SIZE 0x0016fefc
– PAGE_OFFSET was wrong
– Stack corruption
● Set SP to end of external SRAM
– MBAR wrongly set to address of SRAM
● #define MCF_MBAR 0x10000000
Porting uClinux to the Pluto 6
8. – Romfs too big
● _ramstart
calculated >
_ramend
Porting uClinux to the Pluto 6
RAM
.text
.data
.romfs
0x60000000 _stext
_sdata
_sbss
_ebss
Dynamic
memory
0x6016FEFC
A0
A1
A0 + ROMFS size
A1 + ROMFS size
Copy data
from end
forwards
– VBR set to start of RAM, overwriting kernel
– Set _ramvec to ColdFire internal SRAM
● Finally a working kernel!
– But...
9. ● 2Mb of DRAM doesn't give even uClinux
much room to do anything
– After 3 commands, memory is too
fragmented to load programs:
Porting uClinux to the Pluto 6
– Romfs contents restricted
– Tools are required to test drivers
/bin> vi
__alloc_pages: 0-order allocation failed (gfp=0x1d2/0)
__alloc_pages: 4-order allocation failed (gfp=0x1f0/0)
Allocation of length 65000 from process 20 failed
Free pages: 136kB ( 0kB HighMem)
Zone:DMA freepages: 0kB
Zone:Normal freepages: 136kB
Zone:HighMem freepages: 0kB
( Active: 5, inactive: 27, free: 34 )
= 0kB)
6*4kB 2*8kB 2*16kB 0*32kB 1*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB = 136kB)
= 0kB)
10. Running the kernel from VRAM
● Problem: program counter incrementing incorrectly
● Possibly cache related
11. ● Initial solution to use video card RAM
● Solution found and borrowed from Heber:
Getting more memory
● Finally a working USABLE kernel!
FPGA for DRAM
to local bus
decoding
DRAM
Battery
16Mb local
bus interface
DRAM card
12. ● Vacuum Fluorescent Display
– Simple character device
– Clock ASCII characters in through 2 line serial
port
Time to write some drivers!
/> echo hello world! > /dev/vfd0
13. ● FPGA controls 256 lamps as 16 strobes of
32, each has 8 brightness levels
● Every 1ms, software must:
– fill 8 32 bit data registers, each bit
corresponds to one lamp
– Write the strobe number to illuminate to the
MPX control register in the FPGA
● The FPGA splits the 1ms period into 8
segments, using 1 data register for each
● Each bit of each data register = 1/8ms
Multiplexed lamp driver
14. ● Problem:
– Kernel timer used to rewrite lamp registers
every millisecond
– Interrupt set for next jiffy, which is
incremented by timer interrupt
– Timer interrupt frequency determined by HZ
– HZ default is 100 (every 10ms)
– Lamps flash (on for 1ms, off for 9ms)
– Increased HZ to 1000
Multiplexed lamp driver
15. ● Choosing interface to user space
– Write a char for brightness of each lamp
● 1 file for all 256 lamps
– Big overhead to change 1 lamp
● 1 file for each lamp
– 256*3*2=1536 context switches
● Best compromise
– 1 file for each lamp strobe
Multiplexed lamp driver
17. Frame buffer driver
● Graphics were a key part of project
● Two options
– Port a Denx Coral P X server on a PPC board
accessed through PCI running full Linux
– Write a frame buffer driver from scratch
Cremson video
controller
DRAM
Fujitsu Calypso 32 Graphics card
18. Frame buffer driver
● Not a lot of design
required
● But understanding
of sub system is
required
● Values written to
Cremson stored in
a par structure
– Initial par instance
with set values
used for testing
● 1024x768x16
fb_info
fb_var_screeninfo
fb_fix_screeninfo
fb_monospecs
fb_ops * fb_ops
fbgen_get_fix()
fbgen_get_var()
fbgen_set_var()
fbgen_get_cmap()
fbgen_set_cmap()
fbgen_pan_display()fb_cmap
display * display
Par *
cremsonfb_info
fb_info_gen
fbgen_hwswitch * cremsonfb_switch
cremson_detect()
cremson_encode_fix()
cremson_decode_var()
cremson_encode_var()
cremson_get_par()
cremson_set_par()
cremson_get_getcolreg()
cremson_set_getcolreg()
cremson_pan_display()
cremson_blank()
cremson_set_disp()
uint32_t fbcon_cmap[256]
void *screen_base_phys
void *screen_base_virt
uint32_t vid_mem_len
par
Cremson register
copies
unsigned int parsize
27. IDE
● Used a generic driver provided by uClinux
● FPGA outputs same interrupt level for
CompactFlash and Cremson
● Lots of trouble with Cremson Vsync interrupt
while unmasking in ColdFire for the IDE
– Mask Vsync on Cremson
– Unmask interrupt vector on ColdFire
● Copied romfs to CompactFlash card
● Altered kernel command line to mount as
root FS
28. eXecute In Place
● Tried XIP with romfs
– Romfs scrambled when copying .data and .init
from ROM area to RAM area
– No need for romfs with a working disk present
● Added initial vector table to crt0_rom.S
● Split DRAM card into 2 Mb "ROM" and the
rest as RAM area
● Could finally boot straight into uClinux at
power on
MEMORY {
flash : ORIGIN = 0x00000000, LENGTH = 0x00200000
ram : ORIGIN = 0x00200000, LENGTH = 0x00E00000
}
29. ● Project was successful
● Verdict
– Board is rather slow
– Accumulated knowledge for future Heber
boards
● Lessons learned
– Understand code before starting
● learned lesson porting
● used lesson on frame buffer
– Learned lots about kernel programming
Conclusion