This is part III of my HOWTO on running Linux on Microblaze. The outline is as follows:
- Part I: Introduction and setting up the Microblaze processor
- Part II: Compiling the kernel
- Part III: Preparing for boot and booting (this page)
- Part IV: Compiling user space applications
Generating the ACE file
The ACE file is what the System ACE chip reads from, and programs the FPGA accordingly. It consists of a sequence of JTAG operations for each necessary task: Configure the FPGA itself, load the software into memory, set the software execution entry point, and kick the software off. All is done with JTAG commands, which the System ACE generates as it scans through its ACE file.
So let’s get down to business.
Create a directory to gather the relevant files, and copy the following into it:
- The Tcl script for generating ACE file: Found at ISE_DS/EDK/data/xmd/genace.tcl (relative to the path where Xilinx ISE is installed)
- The bitstream (system.bit) file created by the EDK (explained in part I). Found in the ‘hw’ subdirectory in the export bundle from EDK to SDK. Or just under ‘implementation’ in the processor’s working directory. It’s the same file.
- The kernel ELF file (simpleImage.xilinx, or the unstripped simpleImage.xilinx.unstrip) created by the kernel build system (explained in part II), found in arch/microblaze/boot/ in the kernel source tree.
Open a command shell (Project > Launch Xilinx Shell if you like), change to this directory and go:
xmd -tcl genace.tcl -hw system.bit -elf simpleImage.xilinx -ace linuxmb.ace -board sp605 -target mdm
which generates a lot of junk files (.svf most notably, which contain JTAG commands in a portable format), and eventually the linuxmb.ace is created (any file name is OK).
In the example above, I assumed that the target is the SP605 board. Looking at the genace.tcl script reveals easily which boards are supported. If it isn’t, it’s not such a big deal. The only reason the board matters is because the System ACE needs to know which device in the JTAG chain to talk with plus some programming parameters. The -board flags to this scrips allows setting the options in a “genace option file” (whatever that means). I would hack the script, though. It looks easier. See here for more information.
Writing to the Compact Flash
First and foremost: If you have a compact flash which boots anything to the FPGA, don’t format it unless you really have to. The System ACE chip (by Xilinx) which reads from the flash directly is a bit picky about the file system format. Preferably use the card which came with the development kit.
And this too: If you just bought a 2 GB flash or so in a general electronics store, odds are that you’ll need to format it.
I explain how to format the flash in another post of mine.
Assuming that the flash is formatted OK, copy the ACE file to the Compact Flash’ root directory. Make sure that
- there is no other *.ace file in the root directory
- there is no xilinx.sys in the root directory
It is perfectly OK to have unrelated directories on the flash, so if there are some files on the flash already, I’d suggest creating a directory with just any name (say, “prevroot”) and move everything in the root directory into that one. And then copy the desired ACE file (linuxmb.ace in the example above) into the root directory.
That’s it. The Linux kernel should now boot, but it will complain (the kernel will panic, actually) that it doesn’t have any root filesystem. So…
Setting up the root filesystem
Once the kernel is up, it needs something to mount as a root filesystem, in which it expects to find its init executable and quite a few other files. Xilinx supplies an image of this bundle which were downloaded along with the cross compilers (see part II), in the same directory.
You may recall that I chose to mount root over the network, using NFS. So to create a useful root directory to work with, just change directory to whatever is going to be root (in my case, the one exposed via NFS) and go
zcat /path/to/microblaze_v1.0_le/initramfs_minimal_le.cpio.gz | cpio -i -d -H newc --no-absolute-filenames
This bundle includes a practical set of executables (well, it’s actually a lot of symbolic links to busybox) including vi, watch, dd, grep, gzip, tar, rpm, nc and even httpd (a web server…!). There’s also a rootfs.cpio.gz in the kernel sources when downloaded from Xilinx’ git (linux-2.6-xlnx.git in part II) which I haven’t tried out. But it’s opened in the same way.
You may, of course, compile your own programs, which is discussed in part IV.
There’s no “shutdown” executable, though. There’s “halt” instead.
A test run
Well, plug in the Compact Flash card, turn the power on, and hope to see a green LED blinking, which turns to steady green after a few seconds. When the LED is steady, expect some output on the UART. A typical log for SP605 is given at the end of this post.
At times, the SP605 board’s green LED went on, but nothing runs until SYS_ACE_RESET is pressed (the middle button out of three close to the Compact Flash jack). Looks like a powerup issue.
Is it fast? Is it fast?
This is maybe not such a fair comparison, and still the facts speak for themselves:
On Microblaze @ 75 MHz clock (37 BogoMIPS):
# dd if=/dev/zero of=/dev/null bs=1M count=10k 10240+0 records in 10240+0 records out 10737418240 bytes (10.0GB) copied, 1058.304486 seconds, 9.7MB/s # dd if=/dev/zero of=/dev/null bs=512 count=100k 102400+0 records in 102400+0 records out 52428800 bytes (50.0MB) copied, 9.531130 seconds, 5.2MB/s
The same thing on my own computer @ 1.2 GHz (5600 BogoMIPS):
$ dd if=/dev/zero of=/dev/null bs=1M count=10k 10240+0 records in 10240+0 records out 10737418240 bytes (11 GB) copied, 0.941238 s, 11.4 GB/s $ dd if=/dev/zero of=/dev/null bs=512 count=100k 102400+0 records in 102400+0 records out 52428800 bytes (52 MB) copied, 0.0443318 s, 1.2 GB/s
According to the BogoMIPSes, Microblaze should have been 150 times slower, not 1000 times slower!
A typical boot log
early_printk_console is enabled at 0x40600000 Ramdisk addr 0x00000003, Compiled-in FDT at 0xc03c2348 Initializing cgroup subsys cpuset Initializing cgroup subsys cpu Linux version 22.214.171.124 (firstname.lastname@example.org) (gcc version 4.1.2) #19 Fri Aug 5 16:40:02 IDT 2011 setup_cpuinfo: initialising setup_cpuinfo: Using full CPU PVR support cache: wt_msr_noirq setup_memory: max_mapnr: 0x8000 setup_memory: min_low_pfn: 0xc0000 setup_memory: max_low_pfn: 0xc8000 On node 0 totalpages: 32768 free_area_init_node: node 0, pgdat c04f515c, node_mem_map c05ca000 Normal zone: 256 pages used for memmap Normal zone: 0 pages reserved Normal zone: 32512 pages, LIFO batch:7 pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 pcpu-alloc:  0 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512 Kernel command line: console=ttyUL0 ip=::::::dhcp rootfstype=nfs root=/dev/nfs rw nfsroot=10.11.12.13:/shared/nfsroot,tcp PID hash table entries: 512 (order: -1, 2048 bytes) Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) allocated 655360 bytes of page_cgroup please try 'cgroup_disable=memory' option if you don't want memory cgroups Memory: 123204k/131072k available SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 NR_IRQS:32 xlnx,xps-intc-1.00.a #0 at 0xc8000000, num_irq=8, edge=0x60 xlnx,xps-timer-1.00.a #0 at 0xc8004000, irq=7 Heartbeat GPIO at 0xc8008000 microblaze_timer_set_mode: shutdown microblaze_timer_set_mode: periodic Console: colour dummy device 80x25 Calibrating delay loop... 37.17 BogoMIPS (lpj=185856) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 512 Initializing cgroup subsys ns ns_cgroup deprecated: consider using the 'clone_children' flag without the ns_cgroup. Initializing cgroup subsys cpuacct Initializing cgroup subsys memory Initializing cgroup subsys devices Initializing cgroup subsys freezer Initializing cgroup subsys net_cls devtmpfs: initialized NET: Registered protocol family 16 PCI: Probing PCI hardware bio: create slab <bio-0> at 0 XGpio: /axi@0/gpio@40040000: registered XGpio: /axi@0/gpio@40020000: registered XGpio: /axi@0/gpio@40000000: registered vgaarb: loaded Switching to clocksource microblaze_clocksource microblaze_timer_set_mode: oneshot Switched to NOHz mode on CPU #0 NET: Registered protocol family 2 IP route cache hash table entries: 1024 (order: 0, 4096 bytes) TCP established hash table entries: 4096 (order: 3, 32768 bytes) TCP bind hash table entries: 4096 (order: 2, 16384 bytes) TCP: Hash tables configured (established 4096 bind 4096) TCP reno registered UDP hash table entries: 256 (order: 0, 4096 bytes) UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) NET: Registered protocol family 1 RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. PCI: CLS 0 bytes, default 32 Skipping unavailable RESET gpio -2 (reset) GPIO pin is already allocated audit: initializing netlink socket (disabled) type=2000 audit(0.429:1): initialized VFS: Disk quotas dquot_6.5.2 Dquot-cache hash table entries: 1024 (order 0, 4096 bytes) squashfs: version 4.0 (2009/01/31) Phillip Lougher fuse init (API version 7.16) msgmni has been set to 240 Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254) io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled 40600000.serial: ttyUL0 at MMIO 0x40600000 (irq = 6) is a uartlite console [ttyUL0] enabled brd: module loaded loop: module loaded of:xsysace 41800000.sysace: Xilinx SystemACE revision 1.0.12 of:xsysace 41800000.sysace: capacity: 3980592 sectors xsa: xsa1 Xilinx SystemACE device driver, major=254 Generic platform RAM MTD, (c) 2004 Simtec Electronics xilinx_spi 40a00000.spi: at 0x40A00000 mapped to 0xc8080000, irq=0 of:xilinx_emaclite 40e00000.ethernet: Device Tree Probing Xilinx Emaclite MDIO: probed of:xilinx_emaclite 40e00000.ethernet: MAC address is now 00:0a:35:49:b2:00 of:xilinx_emaclite 40e00000.ethernet: Xilinx EmacLite at 0x40E00000 mapped to 0xC80A0000, irq=5 device-mapper: uevent: version 1.0.3 device-mapper: ioctl: 4.19.1-ioctl (2011-01-07) initialised: email@example.com nf_conntrack version 0.5.0 (1925 buckets, 7700 max) ip_tables: (C) 2000-2006 Netfilter Core Team TCP cubic registered Initializing XFRM netlink socket NET: Registered protocol family 17 Registering the dns_resolver key type registered taskstats version 1 Sending DHCP requests . PHY: c0020918:07 - Link is Up - 100/Full ., OK IP-Config: Got DHCP answer from 10.11.12.13, my address is 10.11.12.155 IP-Config: Complete: device=eth0, addr=10.11.12.155, mask=255.255.255.0, gw=10.11.12.13, host=10.11.12.155, domain=, nis-domain=(none), bootserver=10.11.12.13, rootserver=10.11.12.13VFS: Mounted root (nfs filesystem) on device 0:13. devtmpfs: mounted Freeing unused kernel memory: 147k freed Starting rcS... ++ Mounting filesystem ++ Starting telnet daemon rcS Complete /bin/sh: can't access tty; job control turned off / # NET: Registered protocol family 10 eth0: no IPv6 routers present