有點慘,上篇說得想辦法把FPU塞進來的路給打通,但是實在受限硬體資源,有點悲劇。
我是已經訂了一張85F的orangecrab,但是送來大概也是鐵人賽後了。
但沒辦法,我們fallback回來soft-fp的路子吧。要打造soft-fp的musl-porting其實在近日已經沒有太大的狀況,然而目前系列所提及的工程手法有點粗糙,那就是沒有好好打造 phase1、phase2的cross-compiler,也就是先用host-tool打出一套完全不帶library的phase1 cross-compiler,而後以該cross-compiler去編譯libc跟其他fundamental library (e.g. libgcc/libcompiler-rt)、並且配上來自kernel的header( e.g. include/linux/*.h) 等等,最後統一裝進一個sysroot裡面的phase2 compiler,這其實會導致在交叉編譯工具時,有些麻煩事情發生。
musl習慣性的操作方式是直接使用 gcc 的spec file 機智覆蓋掉原本的builtin spec。但對於日後需要大量交叉編譯usperspace program來講,這是很不方便的、因為prefix不符合慣性。
所以這一章節我們偷一下riscv-gnu-toolchain來用:
git clone https://github.com/riscv/riscv-gnu-toolchain
./configure --musl-src /path/to/our/musl --with-arch=rv32imac --withabi=ilp32
make musl
這兩個步驟都會非常的久。
在成功後,我們會獲得一包prefix統一的riscv32-unknown-linux-musl-*
的cross toolchain。
用這套我們終於可以擺脫要靠 spec file跟各式makefile/configure hack的路,以後遇到有考慮過cross build的專案,基本上設好 CROSS_COMPILE=riscv32-unknown-linux-musl-
或著在configure時將make tuple的host
設定為 riscv32-unknown-linux-musl
,多半都會動。(極少量我們還是會需要改一下autotool的檔案)
事不宜遲,將上一篇的busybox以這套toolchain重編,便可以丟到OrangeCrab上了。
這邊順便說一聲,Lite/VexRiscv的linux-soc為了可以serial sideload,把baudrate條得非常快,是 1000000
這個非標準的baudrate,所以一些terminal的支援可能會出狀況。如果一定要用僅能支援標準baudrate的環境,可以修改 soc_linux.py
,將 uart_baudrate
設定的邏輯直接幹掉(LiteX預設是115200)或著重訂為想要的baudrate。
那麼,我們就透過litex的terminal、litex_term示範一次:
$ cat ./boot.json #rootfs/Linux Image是buildroot編的、OpenSBI按照readme、dts是透過 make.py時,LiteX會從自己的meta data生出來
{
"Image": "0x40000000",
"rv32.dtb": "0x40ef0000",
"rootfs.cpio": "0x41000000",
"opensbi.bin": "0x40f00000"
}
$ lxterm --images ./boot.json --speed 1e6 /dev/ttyACM0
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2020 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Sep 19 2021 12:10:02
BIOS CRC passed (a774e300)
Migen git sha1: 3ffd64c
LiteX git sha1: 080ecad5
--=============== SoC ==================--
CPU: VexRiscv SMP-LINUX @ 64MHz
BUS: WISHBONE 32-bit @ 4GiB
CSR: 32-bit data
ROM: 64KiB
SRAM: 2KiB
L2: 2KiB
SDRAM: 131072KiB 16-bit @ 256MT/s (CL-6 CWL-5)
--========== Initialization ============--
Initializing SDRAM @0x40000000...
Switching SDRAM to software control.
Read leveling:
m0, b0: |00111000| delays: 03+-01
m0, b1: |00000000| delays: -
m0, b2: |00000000| delays: -
m0, b3: |00000000| delays: -
best: m0, b00 delays: 03+-01
m1, b0: |00111000| delays: 03+-01
m1, b1: |00000000| delays: -
m1, b2: |00000000| delays: -
m1, b3: |00000000| delays: -
best: m1, b00 delays: 03+-01
Switching SDRAM to hardware control.
Memtest at 0x40000000 (2MiB)...
Write: 0x40000000-0x40200000 2MiB
Read: 0x40000000-0x40200000 2MiB
Memtest OK
Memspeed at 0x40000000 (2MiB)...
Write speed: 16MiB/s
Read speed: 10MiB/s
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[LXTERM] Received firmware download request from the device.
[LXTERM] Uploading ./Image to 0x40000000 (7420864 bytes)...
[LXTERM] Upload complete (181.0KB/s).
[LXTERM] Uploading ./rv32.dtb to 0x40ef0000 (2404 bytes)...
[LXTERM] Upload complete (202.6KB/s).
[LXTERM] Uploading ./rootfs.cpio to 0x41000000 (3781632 bytes)...
[LXTERM] Upload complete (172.8KB/s).
[LXTERM] Uploading ./opensbi.bin to 0x40f00000 (49636 bytes)...
[LXTERM] Upload complete (227.9KB/s).
[LXTERM] Booting the device.
[LXTERM] Done.
Executing booted program at 0x40f00000
--============= Liftoff! ===============--
OpenSBI v0.8-2-ga9ce3ad
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : LiteX / VexRiscv-SMP
Platform Features : timer,mfdeleg
Platform HART Count : 8
Boot HART ID : 0
Boot HART ISA : rv32imas
BOOT HART Features : time
BOOT HART PMP Count : 0
Firmware Base : 0x40f00000
Firmware Size : 120 KB
Runtime SBI Version : 0.2
MIDELEG : 0x00000222
MEDELEG : 0x0000b101
[ 0.000000] Linux version 5.12.0-rc4 (ruinland@ruinland-x1c) (riscv32-buildroot-linux-gnu-gcc.br_real (Buildroot 2021.08-370-gd4877e6f88) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #2 SMP Mon Sep 20 11:13:18 CST 2021
[ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[ 0.000000] printk: bootconsole [sbi0] enabled
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000040000000-0x0000000047ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000040000000-0x0000000047ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000047ffffff]
[ 0.000000] SBI specification v0.2 detected
[ 0.000000] SBI implementation ID=0x1 Version=0x8
[ 0.000000] SBI v0.2 TIME extension detected
[ 0.000000] SBI v0.2 IPI extension detected
[ 0.000000] SBI v0.2 RFENCE extension detected
[ 0.000000] SBI v0.2 HSM extension detected
[ 0.000000] riscv: ISA extensions acim
[ 0.000000] riscv: ELF capabilities acim
[ 0.000000] percpu: Embedded 10 pages/cpu s19148 r0 d21812 u40960
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32512
[ 0.000000] Kernel command line: mem=128M@0x40000000 rootwait console=liteuart earlycon=sbi root=/dev/ram0 init=/sbin/init swiotlb=32
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[ 0.000000] Sorting __ex_table...
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 113720K/131072K available (5594K kernel code, 576K rwdata, 860K rodata, 211K init, 221K bss, 17352K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] rcu: Hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] plic: cpu0: parent irq not available
[ 0.000000] plic: interrupt-controller@f0c00000: mapped 32 interrupts with 1 handlers for 2 contexts.
[ 0.000000] riscv-intc: 32 local interrupts mapped
[ 0.000000] random: get_random_bytes called from start_kernel+0x360/0x4d0 with crng_init=0
[ 0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [0]
[ 0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0xec2a6fa00, max_idle_ns: 440795202120 ns
[ 0.000119] sched_clock: 64 bits at 64MHz, resolution 15ns, wraps every 2199023255546ns
[ 0.026829] Console: colour dummy device 80x25
[ 0.040585] Calibrating delay loop (skipped), value calculated using timer frequency.. 128.00 BogoMIPS (lpj=256000)
[ 0.068034] pid_max: default: 32768 minimum: 301
[ 0.102046] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.122393] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.319270] ASID allocator using 9 bits (512 entries)
[ 0.351630] rcu: Hierarchical SRCU implementation.
[ 0.409578] smp: Bringing up secondary CPUs ...
[ 0.421674] smp: Brought up 1 node, 1 CPU
[ 0.478165] devtmpfs: initialized
[ 0.720391] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.746906] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
[ 0.808814] NET: Registered protocol family 16
[ 2.329851] FPGA manager framework
[ 2.458798] clocksource: Switched to clocksource riscv_clocksource
[ 4.120316] NET: Registered protocol family 2
[ 4.222024] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes, linear)
[ 4.252992] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 4.280403] TCP bind hash table entries: 1024 (order: 1, 8192 bytes, linear)
[ 4.304197] TCP: Hash tables configured (established 1024 bind 1024)
[ 4.334340] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
[ 4.360514] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
[ 4.505214] Unpacking initramfs...
[ 13.504868] Initramfs unpacking failed: invalid magic at start of compressed archive
[ 14.912822] Freeing initrd memory: 8192K
[ 15.020777] workingset: timestamp_bits=30 max_order=15 bucket_order=0
[ 17.608218] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[ 17.629962] io scheduler mq-deadline registered
[ 17.645960] io scheduler kyber registered
[ 17.780964] LiteX SoC Controller driver initialized: subreg:4, align:4
[ 27.928935] f0001000.serial: ttyLXU0 at MMIO 0x0 (irq = 0, base_baud = 0) is a liteuart
[ 27.976351] printk: console [liteuart0] enabled
[ 27.976351] printk: console [liteuart0] enabled
[ 27.992680] printk: bootconsole [sbi0] disabled
[ 27.992680] printk: bootconsole [sbi0] disabled
[ 28.460324] libphy: Fixed MDIO Bus: probed
[ 28.497698] i2c /dev entries driver
[ 28.565869] i2c i2c-0: Not I2C compliant: can't read SCL
[ 28.573041] i2c i2c-0: Bus may be unreliable
[ 28.721886] mmc_spi spi0.0: SD/MMC host mmc0, no WP, no poweroff, cd polling
[ 29.108570] NET: Registered protocol family 10
[ 29.472782] Segment Routing with IPv6
[ 29.489829] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[ 29.632967] NET: Registered protocol family 17
[ 29.876327] Freeing unused kernel memory: 208K
[ 29.884613] Kernel memory protection not selected by kernel config.
[ 29.896105] Run /init as init process
[ 30.005564] mmc0: host does not support reading read-only switch, assuming write-enable
[ 30.020648] mmc0: new SDHC card on SPI
[ 30.220442] mmcblk0: mmc0:0000 ASTC 29.1 GiB
[ 30.896845] mmcblk0: p1
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Saving random seed: [ 63.681305] random: dd: uninitialized urandom read (512 bytes read)
OK
Starting network: OK
Welcome to Buildroot
buildroot login: root
__ _
/ / (_)__ __ ____ __
/ /__/ / _ \/ // /\ \ /
/____/_/_//_/\_,_//_\_\
/ _ \/ _ \
__ _ __ _ _\___/_//_/ ___ _
/ / (_) /____ | |/_/__| | / /____ __ / _ \(_)__ _____ __
/ /__/ / __/ -_)> </___/ |/ / -_) \ // , _/ (_-</ __/ |/ /
/____/_/\__/\__/_/|_|____|___/\__/_\_\/_/|_/_/___/\__/|___/
/ __/ |/ / _ \
_\ \/ /|_/ / ___/
/___/_/ /_/_/
32-bit RISC-V Linux running on LiteX / VexRiscv-SMP.
login[70]: root login on 'console'
root@buildroot:~#
root@buildroot:~# mount /dev/mmcblk0p1 /mnt
root@buildroot:/mnt# cp ./busybox_unstripped ~
root@buildroot:~# ./busybox_unstripped
BusyBox v1.35.0.git (2021-09-20 12:50:09 CST) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.
Usage: busybox [function [arguments]...]
or: busybox --list[-full]
or: busybox --show SCRIPT
or: busybox --install [-s] [DIR]
or: function [arguments]...
BusyBox is a multi-call binary that combines many common Unix
utilities into a single executable. Most people will create a
link to busybox for each function they wish to use and BusyBox
will act like whatever it was invoked as.
Currently defined functions:
[, [[, addgroup, adduser, ar, arch, arp, arping, ash, awk, base32,
base64, basename, bc, blkid, bunzip2, bzcat, cat, chattr, chgrp, chmod,
chown, chroot, chrt, cksum, cmp, cp, cpio, crond, crontab, cut, date,
dc, dd, delgroup, deluser, devmem, df, diff, dirname, dmesg, dnsd,
dnsdomainname, dos2unix, du, echo, egrep, eject, env, ether-wake, expr,
factor, fallocate, false, fbset, fdflush, fdformat, fdisk, fgrep, find,
flock, fold, free, freeramdisk, fsck, fsfreeze, fstrim, fuser, getopt,
getty, grep, gunzip, gzip, halt, hdparm, head, hexdump, hexedit,
hostid, hostname, hwclock, i2cdetect, i2cdump, i2cget, i2cset,
i2ctransfer, id, ifconfig, ifdown, ifup, inetd, init, insmod, install,
ip, ipaddr, ipcrm, ipcs, iplink, ipneigh, iproute, iprule, iptunnel,
kill, killall, killall5, klogd, last, less, link, linux32, linux64,
linuxrc, ln, logger, login, logname, losetup, ls, lsattr, lsmod, lsof,
lspci, lsscsi, lsusb, lzcat, lzma, lzopcat, makedevs, md5sum, mdev,
mesg, microcom, mim, mkdir, mkdosfs, mke2fs, mkfifo, mknod, mkpasswd,
mkswap, mktemp, modprobe, more, mount, mountpoint, mt, mv, nameif,
netstat, nice, nl, nohup, nologin, nproc, nslookup, nuke, od,
partprobe, passwd, paste, patch, pidof, ping, pipe_progress,
pivot_root, poweroff, printenv, printf, ps, pwd, rdate, readlink,
readprofile, realpath, reboot, renice, resume, rm, rmdir, rmmod, route,
run-init, run-parts, runlevel, sed, seq, setarch, setfattr, setpriv,
setserial, setsid, sh, sha1sum, sha256sum, sha3sum, sha512sum, shred,
sleep, sort, start-stop-daemon, strings, stty, su, sulogin, svc, svok,
swapoff, swapon, switch_root, sync, sysctl, syslogd, tail, tar, tc,
tee, telnet, test, tftp, time, top, touch, tr, traceroute, true,
truncate, ts, tty, ubirename, udhcpc, uevent, umount, uname, uniq,
unix2dos, unlink, unlzma, unlzop, unxz, unzip, uptime, usleep,
uudecode, uuencode, vconfig, vi, vlock, w, watch, watchdog, wc, wget,
which, who, whoami, xargs, xxd, xz, xzcat, yes, zcat
一如預期,這是個可以用的busybox,我們的模擬器與實際硬體是對得上的 :-)