Just Linux (without Root Filesystem) ==================================== .. include:: header.rst .. contents:: Contents Overview -------- This chapter describes only how to build and test the Linux kernel; The root file system (aka "userspace") is much harder to build than the Linux kernel and therefore that is described in its own separate chapters. .. Some topics worth covering that are not covered here are: .. - Building an EABI port of Linux. EABI is better suited for embedded .. systems. .. - ftp://sources.redhat.com/pub/binutils/ppc-docs/ .. .. - ppc-eabi-1995-01.pdf .. - ppc-eabi-calling-sequence .. - .. - http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF77852569970071B0D6 "Developing PowerPC Embedded Application Binary Interface (EABI) Compliant Programs" .. - http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF7785256996007558C6 "The PowerPC Compiler Writer's Guide" .. http://pages.infinit.net/jtabel/embedded/build-ppc.sh EABI build Prerequisites ------------- The Linux Kernel Source ~~~~~~~~~~~~~~~~~~~~~~~ You'll actually need the Linux kernel. There are a few possible options; You can get the linux-2.6-xlnx branch from git.xilinx.com. Or you can get the main kernel tree. Or you might be able to use the linux-denx branch (but I haven't tried this yet). - Option #1: Use Xilinx's branch. This branch contains more up-to-date patches and has better support for Xilinx peripherals, such as networking):: git clone git://git.xilinx.com/linux-2.6-xlnx.git cd linux-2.6-xlnx - Option #2: Use the official, mainline kernel. Version 2.6.28 does not support the Xilinx network cores (EMACLITE, LLTEMAC), so it is better to use linux-2.6-xlnx if you want those features:: wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.bz2 tar xjvf linux-2.6.28.tar.bz2 cd linux-2.6.28 - Option #3: Use linux-denx. I think the benefit of using this option is that it has more Xenomai hard-realtime support (but I don't yet know if the Xilinx interrupt controller support has been ported to Xenomai):: git clone git://git.denx.de/linux-2.6-denx.git EMACLITE Patch ~~~~~~~~~~~~~~ If you want EMACLITE support, you might need to do a simple, painless patch. EDK 10.1 SP3 provides xps-ethernetlite-2.00.b, but the Linux tree might only support up to 2.00.a. Here's how to fix that (you can use emacs, vim, nano, or whatever editor you are comfortable with):: nano drivers/net/xilinx_emaclite/adapter.c # <-- older versions of kernel nano drivers/net/xilinx_emaclite.c # <-- newer versions of kernel Then, find these lines (near line 1000) and add a new line for 2.00.b:: static struct of_device_id xemaclite_of_match[] __devinitdata = { { .compatible = "xlnx,opb-ethernetlite-1.01.a", }, { .compatible = "xlnx,opb-ethernetlite-1.01.b", }, { .compatible = "xlnx,xps-ethernetlite-1.00.a", }, { .compatible = "xlnx,xps-ethernetlite-2.00.a", }, { .compatible = "xlnx,xps-ethernetlite-2.00.b", }, // <-- you add this { .compatible = "xlnx,xps-ethernetlite-2.01.a", }, { /* end of list */ }, }; Boot Loader "link_address" Patch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Edit "arch/powerpc/boot/wrapper" to move the link_address to a higher location, as shown in this patch (see `Help with Patch Files `_ if you need help understanding this):: index 965c237..7679f76 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -138,7 +138,7 @@ objflags=-S tmp=$tmpdir/zImage.$$.o ksection=.kernel:vmlinux.strip isection=.kernel:initrd -link_address='0x400000' +link_address='0x800000' This will mitigate the chance of encountering this error message:: zImage starting: loaded at 0x00400000 (sp: 0x0061deb0) Allocating 0x48505c bytes for kernel ... Insufficient memory for kernel at address 0! (_start=00400000, uncompressed size=00405128) Building Linux -------------- 1. Setup your environment for cross-compiling Linux. For example, if you are using crosstool-ng, you might need to do something like this:: export ARCH=powerpc export CROSS_COMPILE=powerpc-405-linux-gnu- export PATH=/home/xilinx/crosstool-ng-1.3.2/powerpc-405-linux-gnu/bin:$PATH You can test that this worked by trying to run the compiler:: powerpc-405-linux-gnu-gcc then you should get the message:: powerpc-405-linux-gnu-gcc: no input files If you are using ELDK 4.2, then you might need to do something like this:: export ARCH=powerpc export CROSS_COMPILE=ppc_4xx- export PATH=/home/xilinx/eldk-4.2/usr/bin:$PATH ppc_4xx-gcc # Expect to see: ppc_4xx-gcc: no input files 2. Configure Linux (see the section `Configuring Linux`_ for more information):: make menuconfig The result of configuration is a file called ".config". I highly recommend that you copy this file into a safe location so that you can simply reuse it in the future. To use an old config file, instead of doing a completely fresh menuconfig, run the following commands:: cp my-old-config-file .config make oldconfig 3. Copy your device tree (the one that you generated from EDK: xilinx.dts):: cp xilinx.dts arch/powerpc/boot/dts/virtex405-mine.dts WARNING: It is important that you use the "virtex405-" (or "virtex440-") prefix because the Linux build process does pattern matching on this name. If it finds "virtex405-" as part of the name, then the build process does a few extra magic tricks to make things come out right for Xilinx parts (specifically, I think it enables the Xilinx PPC cache errata). 4. Build Linux ("-j 4" is to take advantage of your quad-core computer, if you are using one):: nice make -j 4 simpleImage.virtex405-mine The result of this process is an ELF executable file which can be loaded to the FPGA using XMD or via CompactFlash+SystemACE:: arch/powerpc/boot/simpleImage.virtex405-mine.elf .. 5. (Optional) If you have an initrd disk image, copy it into the tree:: .. TODO Configuring Linux ----------------- Here are a couple screen shots of what the menuconfig system looks like: .. figure:: im-edited/linux-menuconfig-01.png .. figure:: im-edited/linux-menuconfig-02.png Here are specific settings which you need to configure: - Processor support - Processor Type: AMCC 40x :: Processor support ---> Processor Type (AMCC 40x) - Platform support: - Walnut: No - Generic Xilinx Virtex board: Yes :: Platform support ---> [ ] Walnut [*] Generic Xilinx Virtex board - Kernel options: - Time frequency: 250 HZ (this could be an interesting option to tweak) :: Kernel options ---> Timer frequency (250 HZ) - Bus options: - PCI support: No - PCCard (PCMCIA/CardBus) support: No :: Bus options ---> [ ] PCI support < > PCCard (PCMCIA/CardBus) support - Networking support: - Networking options: - IP: kernel level autoconfiguration: Yes (to enable NFS root) .. - Wireless: No :: Networking support ---> Networking options ---> [*] IP: kernel level autoconfiguration - Device Drivers: - Block devices: - Xilinx SystemACE support: No (you can come back and change this later, but to keep things simple, just say no for now) - Network device support: **WARNING**: The following options are not available in the mainline 2.6.28 tree. You must use linux-2.6-xlnx if you want these features. - Ethernet (10 or 100Mbit) - Xilinx 10/100 OPB EMACLITE support: Yes - Ethernet (1000Mbit) - Xilinx LLTEMAC 10/100/1000 Ethernet MAC driver: Yes - Xilinx LLTEMAC PHY Support: TODO: GMII or MII? (for ML403) - Character devices: - Serial drivers: - Xilinx uartlite serial port support: Yes - Support for console on Xilinx uartlite serial port: Yes - GPIO Support: - Xilinx GPIO support: Yes :: Device drivers ---> [*] Block devices ---> < > Xilinx SystemACE support [*] Network device support ---> [*] Ethernet (10 or 100Mbit) ---> < > Xilinx 10/100 OPB EMAC support <*> Xilinx 10/100 OPB EMACLITE support [*] Ethernet (1000 Mbit) ---> < > Xilinx TEMAC 10/100/1000 Ethernet MAC driver <*> Xilinx LLTEMAC 10/100/1000 Ethernet MAC driver Xilinx LLTEMAC PHY Support (MARVELL 88E1111 using MII...) Character devices ---> Serial drivers ---> <*> Xilinx uartlite serial port support [*] Support for console on Xilinx uartlite serial port <*> Xilinx HWICAP Support [*] GPIO Support ---> [*] Xilinx GPIO support - Filesystems: - Second extended fs support: Yes - Ext2 execute in place support: Yes (this is an advanced option, search Google for "execute in place" or "XIP") - Network File Systems: - NFS client support: Yes (to enable NFS root) - Root file system on NFS: Yes (if you don't see this, it is because you need to enable "IP: kernel level autoconfiguration" in "Networking options") :: File systems ---> <*> Second extended fs support [*] Ext2 execute in place support [*] Network File Systems ---> <*> NFS client support [*] Root file system on NFS Running Linux via XMD --------------------- From within your EDK project directory (Note: if you are mssing etc/xmd_ppc405_0.opt, it is because you need to choose the menu option: "Debug: XMD Debug Options" then click "OK"):: impact -batch etc/download.cmd rlwrap -c xmd -opt etc/xmd_ppc405_0.opt Then, from the XMD prompt, change to the location where you built Linux and download the ELF executable:: XMD% cd /home/dbaird/tmp/xilinx/linux-build/linux-2.6-xlnx XMD% cd arch/powerpc/boot XMD% dow simpleImage.virtex405-mine.elf XMD% run Observe your serial terminal. When you start running Linux, you should see:: zImage starting: loaded at 0x00400000 (sp: 0x005d1fb0) Allocating 0x439064 bytes for kernel ... gunzipping (0x00000000 <- 0x0040d000:0x005d0e9f)...done 0x3b9134 bytes Linux/PowerPC load: console=ttyUL0 root=/dev/ram Finalizing device tree... flat tree at 0x5de300 [ 0.000000] Using Xilinx Virtex machine description [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Linux version 2.6.28 (dbaird@takoyaki) (gcc version 4.3.2 (crosstool-NG-1.3.2) ) #2 Sun Mar 8 00:51:10 MST 2009 [ 0.000000] Zone PFN ranges: [ 0.000000] DMA 0x00000000 -> 0x00010000 [ 0.000000] Normal 0x00010000 -> 0x00010000 [ 0.000000] HighMem 0x00010000 -> 0x00010000 [ 0.000000] Movable zone start PFN for each node [ 0.000000] early_node_map[1] active PFN ranges [ 0.000000] 0: 0x00000000 -> 0x00010000 [ 0.000000] MMU: Allocated 1088 bytes of context maps for 255 contexts [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024 [ 0.000000] Kernel command line: console=ttyUL0 root=/dev/ram [ 0.000000] Xilinx intc at 0x81800000 mapped to 0xff7ff000 [ 0.000000] PID hash table entries: 1024 (order: 10, 4096 bytes) [ 0.000000] clocksource: timebase mult[1400000] shift[22] registered [1266810336.351522] Console: colour dummy device 80x25 [1266810336.351800] console [ttyUL0] enabled [1266810336.449030] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes) [1266810336.459534] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes) [1266810336.512209] allocated 1310720 bytes of page_cgroup [1266810336.516239] please try cgroup_disable=memory option if you don't want [1266810336.607852] Memory: 253952k/262144k available (3620k kernel code, 7896k reserved, 164k data, 508k bss, 148k init) [1266810336.617693] SLUB: Genslabs=10, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [1266810336.625446] Calibrating delay loop... 399.36 BogoMIPS (lpj=798720) [1266810336.719650] Security Framework initialized [1266810336.724078] SELinux: Disabled at boot. [1266810336.728344] Mount-cache hash table entries: 512 [1266810336.735202] Initializing cgroup subsys ns [1266810336.738537] Initializing cgroup subsys cpuacct [1266810336.743305] Initializing cgroup subsys memory [1266810336.759532] net_namespace: 1012 bytes [1266810336.765172] NET: Registered protocol family 16 [1266810336.847966] XGpio: /plb@0/gpio@81420000: registered [1266810336.854149] XGpio: /plb@0/gpio@81400000: registered [1266810336.859945] XGpio: /plb@0/gpio@81440000: registered [1266810336.897048] NET: Registered protocol family 8 [1266810336.900569] NET: Registered protocol family 20 [1266810336.906890] NetLabel: Initializing [1266810336.909468] NetLabel: domain hash size = 128 [1266810336.914395] NetLabel: protocols = UNLABELED CIPSOv4 [1266810336.919920] NetLabel: unlabeled traffic allowed by default [1266810336.942199] NET: Registered protocol family 2 [1266810336.994781] IP route cache hash table entries: 2048 (order: 1, 8192 bytes) [1266810337.004945] TCP established hash table entries: 8192 (order: 4, 65536 bytes) [1266810337.012777] TCP bind hash table entries: 8192 (order: 3, 32768 bytes) [1266810337.019349] TCP: Hash tables configured (established 8192 bind 8192) [1266810337.025250] TCP reno registered [1266810337.038796] NET: Registered protocol family 1 [1266810337.068651] audit: initializing netlink socket (disabled) [1266810337.073857] type=2000 audit(0.571:1): initialized [1266810337.203759] VFS: Disk quotas dquot_6.5.1 [1266810337.207791] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes) [1266810337.223789] msgmni has been set to 496 [1266810337.234954] alg: No test for stdrng (krng) [1266810337.238936] io scheduler noop registered [1266810337.242724] io scheduler anticipatory registered [1266810337.247790] io scheduler deadline registered [1266810337.252848] io scheduler cfq registered (default) [1266810339.159041] Serial: 8250/16550 driver4 ports, IRQ sharing enabled [1266810339.184097] 84000000.serial: ttyUL0 at MMIO 0x84000003 (irq = 16) is a uartlite [1266810339.255647] brd: module loaded [1266810339.259076] xsysace 83600000.sysace: Xilinx SystemACE revision 1.0.12 [1266810339.266061] xsysace 83600000.sysace: capacity: 990864 sectors [1266810339.272074] xsa: xsa1 [1266810339.287488] Xilinx SystemACE device driver, major=254 [1266810339.293598] xilinx_emaclite 81000000.ethernet: Device Tree Probing 'ethernet' [1266810339.300579] xilinx_emaclite 81000000.ethernet: MAC address is now 2: 0: 0: 0: 0: 0 [1266810339.308123] xilinx_emaclite 81000000.ethernet: using fifo mode. [1266810339.314456] eth0 (): not using net_device_ops yet [1266810339.324454] xilinx_emaclite 81000000.ethernet: Xilinx EMACLite at 0x81000000 mapped to 0xD1060000, irq=18 [1266810339.340360] input: Macintosh mouse button emulation as /devices/virtual/input/input0 [1266810339.375342] mice: PS/2 mouse device common for all mice [1266810339.393678] TCP cubic registered [1266810339.400431] RPC: Registered udp transport module. [1266810339.404626] RPC: Registered tcp transport module. [1266810339.418944] registered taskstats version 1 [1266810339.422775] drivers/rtc/hctosys.c: unable to open rtc device (rtc0) [1266810339.432673] List of all partitions: [1266810339.435605] fe00 495432 xsa (driver?) [1266810339.440209] fe01 494896 xsa1 [1266810339.444414] No filesystem could mount root, tried: cramfs [1266810339.450311] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0) [1266810339.459072] Rebooting in 180 seconds.. Running Linux via SystemACE --------------------------- .. Contributed by: Tim Sander Creating the ACE file. The ACE file is created with the xmd-tool. This tool is available with the xilinx enviroment variables set. There still is a bug in the build scripts for the Xilinx tools which prevents building the ACE file. So according to `AR #23192 `_ you first have to edit the file: $XILINX_EDK/data/xmd/genace.tcl. (where XILINX_EDK can be found by issuing "echo $XILINX_EDK"). Line 452 has to look like this (NOTE: rather than actually edit the original file, you probably should make a copy of it and tell XMD to use your copy):: if { [catch {set saddr [exec powerpc-405-linux-gnu-objdump -x $elffile | grep -w "start address"]} err] } { If you are not patching the file you will get the error that the size of the ELF file is not known. Now you have to create a option file for the xmd debugger. You can place this file anywhere you want, but i have put it into the "etc" directory of the xps project: etc/genace.opt:: -jprog -board user -target ppc_hw -hw ./implementation/download.bit -elf ../linux-2.6-xlnx/arch/powerpc/boot/simpleImage.virtex405-mine.elf -configdevice devicenr 1 idcode 0x1127e093 irlength 14 partname xc2vp30 -debugdevice devicenr 1 cpunr 1 -ace system.ace With this stuff all set you can now run the xmd command within your xps project directory:: xmd -tcl genace.tcl -opt etc/genace.opt You should now find a file named "system.ace" in your xps project directory. The next paragraph describes how this file i loaded into the fpga via the CF card. The XUP Board features a CF-card connector. This connector has an ACE controller which is able to program the Virtex 2 Pro by itself and is also able to initialize the volatile memory on the board. To use this functionality the first primary partition on the cf disk should be a FAT16 partition with a maximum size of 2GB. When creating partitions you should be extremely careful to work on the right disk. You can make sure that you are working on the right disk by issuing a:: dmesg | tail right after you have plugged your CF-disk into your CF-disk reader. You should see a message like this:: sd 2:0:0:1: [sde] 15858864 512-byte hardware sectors (8120 MB) Which means that "/dev/sde" is the right device to create a partion on. Then you should create a partition which is large enough to hold the kernel and the bitfile for the virtex2vp30. 16MB seems to be big enough, if you want to have enough space for a big kernel you probably should choose 20MB. Cou can now use:: cfdisk /dev/insert_your_disk_device_here Typically new CF-disks come with one large partition. You should delete this partition by pressing "d". Now you can create a new partition by pressing "n". Choose a primary partition and enter "20" as size. After that you should press "t" to change the partition type to "06". Finally you should write your partition to the CF-disk by pressing "W". You can create root or other partitions on this disk later on, but right now the result is to be tested. After the cf-card has been partitioned you have make a new file system on the disk. First some zeros are written to the partition and format it with:: # I'm not sure why/if this dd is necessary: dd bs=1024 count=1 if=/dev/zero of=/dev/insert_your_disk_device_here # I think this is the way you are *supposed* to format the card # (with 1 reserved sector, a requirement of SystemACE): mkfs.msdos –s 64 –F 16 –R 1 /dev/insert_your_disk_device_here # ...but I have gotten a report that this works as well (to my # surprise): mkfs.msdos -F16 /dev/insert_your_disk_device_here After this you can now copy your ace file to the newly created partition:: mount /dev/insert_your_disk_device_here /mnt cp system.ace /mnt umount /mnt Remove the card *after* the "umount" command is finished since write access is buffered, otherwise you might loose data. Now your card is ready to be plugged into the XUP board. Power down the board, plug in the cf-card and then power up your board. The red blinking should stop and there should be a green led blinking. When the green led is lit, you should see the linux boot messages on your serial console. Suggestions to Improve Your Workflow ------------------------------------ Here are some trips to make building Linux less tedious: - Always keep a tar file of the Linux tree. Downloading it is slow, especially if fetching a new tree with git. - Sometimes (often times) you can reuse the same configured Linux tree for several projects. Once you have done "make menuconfig" or "make oldconfig", save that tree. If you change your EDK project, simply copy over the new device tree file (.dts) and run "make simpleImage.virtex405-xxx". - Rebuilding a new kernel with a new device tree, or with a new initrd, goes extremely quickly. So, if you can reduce your workflow to these steps, then it will be easier for you.