スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

hard-floatでコンパイル(buildroot + kernel)

前々回から Raspberry Pi 上で動くrootfsをbuildrootを使って作成していますが、今更ですが、コンパイラが soft-float版 になっているのに気がつきました。buildroot の raspberrypi_defconfig を信じきっていたのが徒となったのです。Raspberry Pi は hard-float に対応しているので、宝の持ち腐れになっては本末転倒です。なので、hard-float に対応したコンパイラを使って buildroot をコンパイルする事にしました。

と言っても、buildrootにはarmv6+vfp版のコンパイラは選択項目にありません。なのでクロスコンパイラを用意する必要があります。armv6+vfp版のgccは結構落ちていたりするのでそれを使うのも有りですが、どうせなら自分で作ってしまえと思いクロスコンパイラを作成するところから始めました。まぁ、これがドツボにはまる原因となったのですが。

PC-Linux環境(VMware等でも可)を持っているなら binutils,gcc,glibc,mpfr,gmp,mpc,isl,cloog のソースコードを取得してそれぞれをコンパイルしてやればできあがり……なのですが、それぞれのバージョンを合わせたりパッチをあてたりする必要があったりで大変なのです。そこで、今回は crosstool-NG というツールを使うことにしました。このツールをインストールするとメニューを選択することで目的のクロスコンパイラを作成することができるのです! サポートしていればですが。

まずは crosstool-NG 自体のコンパイルとインストールです。コンパイルに必要なパッケージはもっと少ないのですが、この後の作業の事も考えて一気にインストールしています。

$ sudo apt-get install flex bison automake libtool libncurses5-dev texinfo lzma gawk cvs patch g++ gperf subversion build-essential
$ mkdir ./tools
$ cd ./tools/
$ git clone git://crosstool-ng.org/crosstool-ng
$ cd crosstool-ng/
$ git checkout crosstool-ng-1.20.0
$ ./bootstrap
$ ./configure --prefix=/home/jujurou/tools/crosstool-ng-1.20.0
$ make
$ make install


毎度使うツールでもないのでインストール先をhome下にしました。使うときは指定先にパスを通します。作業用ディレクトリを作成してクロスコンパイラの作成です。

$ export PATH=/home/jujurou/tools/crosstool-ng-1.20.0/bin:$PATH
$ cd ../
$ mkdir gcc-rpi
$ cd ./gcc-rpi/
$ ct-ng menuconfig
$ ct-ng build


menuconfig では次の様に指定しました。
書いてない部分はデフォルトの値にしています。
Linux kernel version はこの後で作成するkernelのバージョンに近い物を選択しています。

Paths and misc options  --->
[*] Try features marked as EXPERIMENTAL
Prefix directory
${HOME}/tools/x-tools/${CT_TARGET}

Target options --->
Target Architecture
(X) arm
[*] Use the MMU
Endianness:
(X) Little endian
Bitness:
(X) 32-bit
Architecture level
armv6zk
Emit assembly for CPU
arm1176jzf-s
Tune for CPU
arm1176jzf-s
Use specific FPU
vfp
Floating point:
(X) hardware (FPU)
Default instruction set mode
(X) arm
[*] append 'hf' to the tuple (EXPERIMENTAL)

Toolchain options --->
Tuple's vendor string
rpi

Operating System --->
Target OS
(X) linux
Linux kernel version
(X) 3.12.24 (longterm)

Binary utilities --->
binutils version
(X) 2.24 (EXPERIMENTAL)

C-library --->
C library
(X) eglibc
eglibc version
(X) 2_18

C compiler --->
[*] Show Linaro versions
gcc version
(X) linaro-4.8-2014.01
[*] C++


ct-ng build を実行すると、各ソースコードを取得して来てコンパイルし、指定先にインストールまでしちゃいます。これにはチョッとビックリしました。私の環境では、/home/jujurou/tools/x-tools/arm-rpi-linux-gnueabihf 下にインストールされました。

念の為、浮動小数点演算を使用したプログラムをコンパイルして、逆アセンブルしてみたところ、vfp用の命令が入っていることを確認出来ました。

841c:       ed1b6b03        vldr    d6, [fp, #-12]
8420: ed9f7b12 vldr d7, [pc, #72] ; 8470
8424: ee267b07 vmul.f64 d7, d6, d7
8428: ed0b7b03 vstr d7, [fp, #-12]


これでarmv6+vfp用のクロスコンパイラの作成完了です。
実際にはこのコンパイラでコンパイルした物をraspbian上で実行して動作することを確認しています。実行時のログとかは取ってませんが…。


クロスコンパイラが準備できたということで、本命のbuildrootをコンパイルします。make menuconfig の選択項目以外は前々回の内容と同じです。

Target options  --->
Target Architecture
(X) ARM (little endian)
Target Architecture Variant
(X) arm1176jzf-s
Target ABI
(X) EABIhf
Floating point strategy
(X) VFPv2
ARM instruction set
(X) ARM

Build options --->
Download dir
$(TOPDIR)/../dl

Toolchain --->
Toolchain type
(X) External toolchain
Toolchain
(X) Custom toolchain
Toolchain origin
(X) Pre-installed toolchain
Toolchain path
/home/jujurou/tools/x-tools/arm-rpi-linux-gnueabihf
Toolchain prefix
arm-rpi-linux-gnueabihf
External toolchain kernel headers series
(X) 3.12.x
External toolchain C library
(X) glibc/eglibc
[*] Toolchain has C++ support?
[*] Enable MMU support
Target Optimizations
-pipe -mtune=arm1176jzf-s -march=armv6zk

System configuration --->
[*] Run a getty (login prompt) after boot
getty options --->
TTY port
ttyAMA0
Baudrate
(X) 115200
TERM environment variable
vt100

Kernel --->
[*] Linux Kernel
Kernel version
(X) Custom Git repository
URL of custom repository
git://github.com/raspberrypi/linux.git
Custom repository version
c256eb9968c8997dce47350d2075e42f1b3991d3
Defconfig name
bcmrpi_quick
Kernel binary format
(X) zImage

Target packages --->
Hardware handling --->
Firmware --->
[*] rpi-firmware
Firmware to boot
(X) default


この設定ではkernelのコンパイルとFirmwareの取得も行う事にしています。ここではまった事が2点あります。1つが hard-float専用コンパイラを使用したが故に発生した事で、もう1つは…buildrootのせいです。

これ、そのままmakeを行うと以下のエラーが出てしまいます。

arm-rpi-linux-gnueabihf-gcc: error: -mfloat-abi=soft and -mfloat-abi=hard may not be used together


これは「soft-floatなんて処理できないぜ」と言っているのです。ま~、コンパイラをmulti-lib対応してませんしね。そもそもsoft-floatを要求するのは誰だ! と思ったら、kernelでした。こいつは厄介で、multi-lib対応しないとダメかな……と思っていたら、何と ld-linux.so.3 というライブラリを用意すれば何とかなるらしいのです。

このあたりの情報を見ると、かなり強引ではありますが、hard-float版のライブラリ(ld-linux-armhf.so.3)へのシンボリックリンクを作成するといった荒技があるみたいです。

ln -s ./ld-linux-armhf.so.3 ./ld-linux.so.3


このようにしておいてmakeをすると程なくしてコンパイル完了となります。
それぞれのファイルをSDカードに入れて起動させると、無事に起動しました。あっ、出力先をttyAMA0に変更するのを忘れないようにしてください。

Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 3.12.28-quick (jujurou@ubuntu) (gcc version 4.8.3 20140106 (prerelease) (crosstool-NG 1.20.0) ) #1 PREEMPT Sun Feb 15 09:15:49 JST 2015
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] Machine: BCM2708
[ 0.000000] Memory policy: ECC disabled, Data cache writeback
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 104648
[ 0.000000] Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=720 bcm2708_fb.fbheight=480 bcm2708.boardrev=0xf bcm2708.serial=0xb9e9487d smsc95xx.macaddr=B8:27:EB:E9:48:7D sdhci-bcm2708.emmc_clock_freq=250000000 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 dwc_otg.fiq_fix_enable=1 sdhci-bcm2708.sync_after_dma=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/mmcblk0p2 rootwait
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Memory: 411552K/421888K available (3923K kernel code, 195K rwdata, 1684K rodata, 135K init, 610K bss, 10336K reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
[ 0.000000] vmalloc : 0xda000000 - 0xff000000 ( 592 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xd9c00000 ( 412 MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB)
[ 0.000000] .text : 0xc0008000 - 0xc0581fa4 (5608 kB)
[ 0.000000] .init : 0xc0582000 - 0xc05a3d38 ( 136 kB)
[ 0.000000] .data : 0xc05a4000 - 0xc05d4ca0 ( 196 kB)
[ 0.000000] .bss : 0xc05d4cac - 0xc066d6d8 ( 611 kB)
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] NR_IRQS:394
[ 0.000000] sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps every 4294967ms
[ 0.000000] Switching to timer-based delay loop
[ 0.000000] Console: colour dummy device 80x30
[ 0.000471] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
[ 0.000494] pid_max: default: 32768 minimum: 301
[ 0.000827] Mount-cache hash table entries: 512
[ 0.001564] CPU: Testing write buffer coherency: ok
[ 0.001955] Setting up static identity map for 0xc03daae0 - 0xc03dab3c
[ 0.003530] devtmpfs: initialized
[ 0.018901] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 5
[ 0.019504] regulator-dummy: no parameters
[ 0.019778] NET: Registered protocol family 16
[ 0.024680] DMA: preallocated 4096 KiB pool for atomic coherent allocations
[ 0.025026] cpuidle: using governor ladder
[ 0.025048] cpuidle: using governor menu
[ 0.025448] bcm2708.uart_clock = 0
[ 0.026770] hw-breakpoint: found 6 breakpoint and 1 watchpoint registers.
[ 0.026790] hw-breakpoint: maximum watchpoint size is 4 bytes.
[ 0.026805] mailbox: Broadcom VideoCore Mailbox driver
[ 0.026903] bcm2708_vcio: mailbox at f200b880
[ 0.026984] bcm_power: Broadcom power driver
[ 0.027003] bcm_power_open() -> 0
[ 0.027014] bcm_power_request(0, 8)
[ 0.527719] bcm_mailbox_read -> 00000080, 0
[ 0.527737] bcm_power_request -> 0
[ 0.527749] Serial: AMBA PL011 UART driver
[ 0.527905] dev:f1: ttyAMA0 at MMIO 0x20201000 (irq = 83, base_baud = 0) is a PL011 rev3
[ 0.847568] console [ttyAMA0] enabled
[ 0.872958] bio: create slab at 0
[ 0.878275] SCSI subsystem initialized
[ 0.882352] usbcore: registered new interface driver usbfs
[ 0.888042] usbcore: registered new interface driver hub
[ 0.893529] usbcore: registered new device driver usb
[ 0.898992] Advanced Linux Sound Architecture Driver Initialized.
[ 0.906136] Switched to clocksource stc
[ 0.910302] FS-Cache: Loaded
[ 0.913408] CacheFiles: Loaded
[ 0.928427] NET: Registered protocol family 2
[ 0.934149] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.941502] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.948065] TCP: Hash tables configured (established 4096 bind 4096)
[ 0.954489] TCP: reno registered
[ 0.957766] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.963611] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.970230] NET: Registered protocol family 1
[ 0.975018] RPC: Registered named UNIX socket transport module.
[ 0.981031] RPC: Registered udp transport module.
[ 0.985732] RPC: Registered tcp transport module.
[ 0.990459] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.997600] bcm2708_dma: DMA manager at f2007000
[ 1.002302] bcm2708_gpio: bcm2708_gpio_probe c05b0150
[ 1.007719] vc-mem: phys_addr:0x00000000 mem_base=0x1ec00000 mem_size:0x20000000(512 MiB)
[ 1.018629] FS-Cache: Netfs 'nfs' registered for caching
[ 1.024332] NFS: Registering the id_resolver key type
[ 1.029600] Key type id_resolver registered
[ 1.033786] Key type id_legacy registered
[ 1.038185] msgmni has been set to 803
[ 1.043360] io scheduler noop registered
[ 1.047438] io scheduler deadline registered
[ 1.051734] io scheduler cfq registered (default)
[ 1.056860] BCM2708FB: allocated DMA memory 59540000
[ 1.061863] BCM2708FB: allocated DMA channel 0 @ f2007000
[ 1.072563] Console: switching to colour frame buffer device 90x30
[ 1.083115] bcm2708_rng_init=da41a000
[ 1.094895] brd: module loaded
[ 1.102348] loop: module loaded
[ 1.105749] vchiq: vchiq_init_state: slot_zero = 0xda004000, is_master = 0
[ 1.113797] usbcore: registered new interface driver ax88179_178a
[ 1.120269] usbcore: registered new interface driver smsc95xx
[ 1.126253] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[ 1.332359] Core Release: 2.80a
[ 1.335512] Setting default values for core params
[ 1.340404] Finished setting default values for core params
[ 1.546137] Using Buffer DMA mode
[ 1.549458] Periodic Transfer Interrupt Enhancement - disabled
[ 1.555278] Multiprocessor Interrupt Enhancement - disabled
[ 1.560867] OTG VER PARAM: 0, OTG VER FLAG: 0
[ 1.565223] Dedicated Tx FIFOs mode
[ 1.568965] WARN::dwc_otg_hcd_init:1042: FIQ DMA bounce buffers: virt = 0xda422000 dma = 0x5958c000 len=9024
[ 1.578846] FIQ FSM acceleration enabled for :
[ 1.578846] Non-periodic Split Transactions
[ 1.578846] Periodic Split Transactions
[ 1.578846] High-Speed Isochronous Endpoints
[ 1.595605] WARN::hcd_init:473: FIQ at 0xc02d1190
[ 1.600343] WARN::hcd_init:474: FIQ ASM at 0xc02d1468 length 36
[ 1.606298] WARN::hcd_init:500: MPHI regs_base at 0xda41c000
[ 1.611966] dwc_otg bcm2708_usb: DWC OTG Controller
[ 1.616917] dwc_otg bcm2708_usb: new USB bus registered, assigned bus number 1
[ 1.624190] dwc_otg bcm2708_usb: irq 32, io mem 0x00000000
[ 1.629736] Init: Port Power? op_state=1
[ 1.633654] Init: Power Port (0)
[ 1.637190] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.643980] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.651239] usb usb1: Product: DWC OTG Controller
[ 1.655942] usb usb1: Manufacturer: Linux 3.12.28-quick dwc_otg_hcd
[ 1.662233] usb usb1: SerialNumber: bcm2708_usb
[ 1.667715] hub 1-0:1.0: USB hub found
[ 1.671532] hub 1-0:1.0: 1 port detected
[ 1.676989] bcm2708 watchdog, heartbeat=10 sec (nowayout=0)
[ 1.682805] bcm2835-cpufreq: min=700000 max=700000 cur=700000
[ 1.688731] bcm2835-cpufreq: switching to governor powersave
[ 1.694393] bcm2835-cpufreq: switching to governor powersave
[ 1.700201] sdhci: Secure Digital Host Controller Interface driver
[ 1.706423] sdhci: Copyright(c) Pierre Ossman
[ 1.710956] mmc-bcm2835: Unable to initialise DMA channels. Falling back to PIO
[ 1.756191] Load BCM2835 MMC driver
[ 1.759909] sdhci-pltfm: SDHCI platform and OF driver helper
[ 1.765852] usbcore: registered new interface driver usbhid
[ 1.771725] usbhid: USB HID core driver
[ 1.783840] TCP: cubic registered
[ 1.787284] NET: Registered protocol family 17
[ 1.793960] Key type dns_resolver registered
[ 1.807001] regulator-dummy: incomplete constraints, leaving on
[ 1.818172] ALSA device list:
[ 1.821154] #0: bcm2835 ALSA
 1.824650] Waiting for root device /dev/mmcblk0p2...
[ 1.843418] mmc0: host does not support reading read-only switch. assuming write-enable.
[ 1.853720] mmc0: new high speed SDHC card at address 59b4
[ 1.859747] mmcblk0: mmc0:59b4 NCard 29.4 GiB
[ 1.865718] mmcblk0: p1 p2
[ 1.868791] Indeed it is in host mode hprt0 = 00021501
[ 1.938015] EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities
[ 1.947638] EXT4-fs (mmcblk0p2): couldn't mount as ext2 due to feature incompatibilities
[ 2.046253] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 2.052866] Indeed it is in host mode hprt0 = 00001101
[ 2.080440] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[ 2.096233] VFS: Mounted root (ext4 filesystem) on device 179:2.
[ 2.117555] devtmpfs: mounted
[ 2.120976] Freeing unused kernel memory: 132K (c0582000 - c05a3000)
[ 2.286712] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
[ 2.293446] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.310705] hub 1-1:1.0: USB hub found
[ 2.314787] hub 1-1:1.0: 3 ports detected
[ 2.400570] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
Initializing random number generator... [ 2.596433] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
done.
Starting network...
[ 2.726595] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.733485] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.744307] smsc95xx v1.0.4

Welcome to Buildroot
buildroot login: [ 2.810197] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:e9:48:7d

Welcome to Buildroot
buildroot login:


入っているライブラリを検索すると、こんな感じになりました。

# find / -name "*.so*"
/lib/libc-2.18.so
/lib/libm.so.6
/lib/libpthread-2.18.so
/lib/libresolv-2.18.so
/lib/libc.so.6
/lib/librt.so.1
/lib/libcrypt.so.1
/lib/libpthread.so.0
/lib/modules/3.12.28-quick/modules.softdep
/lib/libnss_files-2.18.so
/lib/libutil-2.18.so
/lib/libnss_dns-2.18.so
/lib/ld-linux-armhf.so.3
/lib/libnss_dns.so.2
/lib/libgcc_s.so.1
/lib/libm-2.18.so
/lib/libnsl.so.1
/lib/libnsl-2.18.so
/lib/ld-2.18.so
/lib/libcrypt-2.18.so
/lib/libdl-2.18.so
/lib/libresolv.so.2
/lib/librt-2.18.so
/lib/libdl.so.2
/lib/libutil.so.1
/lib/libnss_files.so.2
/usr/lib/libstdc++.so.6.0.19-gdb.py
/usr/lib/libstdc++.so.6.0.19
/usr/lib/libstdc++.so.6
/etc/ld.so.conf
/etc/ld.so.cache
/etc/ld.so.conf.d


ld-linux-armhf.so.3 の方が入っているのですね。これからはこれをベースにして構築して行きます。
スポンサーサイト

tag : RaspberryPi

tag : buildroot

tag : Linux

buildrootでのDHCP接続(Raspberry Pi)

自宅にはルータがあり、DHCPサーバとして使用しています。なので Raspberry Pi もstatic IPではなく、DHCPサーバからIPを取得してLANに接続するように設定します。簡単だと思っていたのですが、以外と手こずらせてくれました。

buildrootには DHCP client として dhcpcd が入っています。これを有効化してLANに接続します。有効化の方法は、buildrootのフォルダで make menuconfig を実行して Target packages → Networking applications → dhcpcd にチェックを入れて make します。これでできあがった rootfs.tar をSDカードに展開します。そして Raspberry Pi の電源ON。出てきたログが以下です。

途中から…
[    2.035092] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 2.041948] Indeed it is in host mode hprt0 = 00001101
[ 2.167710] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
[ 2.255358] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
[ 2.262091] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
Initializing random number generator... [ 2.297191] hub 1-1:1.0: USB hub found
[ 2.301094] hub 1-1:1.0: 3 ports detected
done.
Starting network...

Welcome to Buildroot
buildroot login: [ 2.614872] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 2.735124] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.742011] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.752734] smsc95xx v1.0.4
[ 2.818653] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:e9:48:7d

Welcome to Buildroot
buildroot login:


eth0の設定をしていないので、"Starting network..." の所では何もおきません。eth0はDHCPで繋ぐ事を設定します。

# vi /etc/network/interfaces
# cat /etc/network/interfaces
# Configure Loopback
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp


これで再起動してみます。

途中から…。
[    1.970911] Freeing unused kernel memory: 124K (c0549000 - c0568000)
[ 2.035072] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 2.041963] Indeed it is in host mode hprt0 = 00001101
[ 2.148635] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
Initializing random number generator... [ 2.255437] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
[ 2.262172] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
done.
[ 2.318921] hub 1-1:1.0: USB hub found
[ 2.322871] hub 1-1:1.0: 3 ports detected
Starting network...
ip: SIOCGIFFLAGS: No such device

Welcome to Buildroot
buildroot login: [ 2.624862] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 2.745118] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.752007] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.762730] smsc95xx v1.0.4
[ 2.828660] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:e9:48:7d

Welcome to Buildroot
buildroot login:


何と、"Starting network..." の直後にeth0からDHCPサーバへ繋ごうとするのですが、"ip: SIOCGIFFLAGS: No such device" と言われてしまいます。ようはeth0が見つからないらしいのです。その証拠にもっと下の方でeth0を登録しています。どうやら Raspberry Pi は USB-Ethernet を使っているみたいなのですが、デバイスを認識するのに時間がかかっているんですね。なので、eth0を使おうとして ifup を実行してもデバイスが見つからないといった内容を吐き出してくれちゃってるのです。

これは…どうしてやろうかと思いましたよ。起動が速くなったので喜んでいたら、その弊害が出てしまったといったところでしょうか。といっても、ヘッドレス構成にするのでこの時点でLANに繋がっていないのは非常にマズイです。そこで、多少のロスは目をつむり、eth0が登録されるまで……正確には ifup が成功するまで繰り返すという方法をとることにしました。

修正方法は、初期化スクリプトを編集します。

# cat /etc/init.d/S40network
#!/bin/sh
#
# Start the network....
#

case "$1" in
start)
echo "Starting network..."
for x in $(seq 1 10)
do
if /sbin/ifup -a; then
break
else
echo "networek connect wait..."
sleep 1
fi
done
;;
stop)
echo -n "Stopping network..."
/sbin/ifdown -a
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac

exit $?


S40network の start のケースで ifup を実行してエラーであれば1秒待ってから再度 ifup を行う。というのを 10回までチャレンジさせます。この様に修正して再起動した時のログが以下です。

[    2.255343] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
[ 2.262076] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.309266] hub 1-1:1.0: USB hub found
[ 2.327877] hub 1-1:1.0: 3 ports detected
done.
Starting network...
ip: SIOCGIFFLAGS: No such device
networek connect wait...
[ 2.624835] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 2.745095] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.751981] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.762705] smsc95xx v1.0.4
[ 2.828620] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:e9:48:7d
ifup: interface lo already configured
[ 3.537596] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
udhcpc (v1.22.1) started
Sending discover...
[ 5.029596] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Sending discover...
Sending select for 192.168.11.12...
Lease of 192.168.11.12 obtained, lease time 172800
deleting routers
adding dns 192.168.11.1

Welcome to Buildroot
buildroot login:


一度失敗してますが、2回目に成功してIPを取得出来ています。念の為に確認してみると、ちゃんとIPが取得出来ています。

# ifconfig
eth0 Link encap:Ethernet HWaddr B8:27:EB:E9:48:7D
inet addr:192.168.11.12 Bcast:192.168.11.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2400 (2.3 KiB) TX bytes:700 (700.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)


少々起動に時間がかかるようになってしまいましたが、許せる範囲なので無問題です。

MPDを稼働させるまでにもう1、2箇所くらい難所がありそうですが、頑張ってみます。

tag : RaspberryPi

tag : buildroot

Raspberry Piへbuildrootでのrootfs構築

Raspberry Piへbuildrootで作成したrootfsを入れてシリアル(UART0)から入出力できる所まで行います。


Raspberry Pi を購入して 2年超となりました。私の使用方法はかなり確立していて、MPDを入れてUSB-DACとセットでジュークボックスとして使用しています。他の使い道は…今の所ないです。

rootfsに入れているディストリビューションはraspbianですが、これってジュークボックスとして使用するだけなら多くの機能が入りすぎています。不要な物を削って使用していたのですが、最近になってbuildrootの存在を思い出した。

buildrootは小ROM/RAM構成のハードにもLinuxを入れられる様にしたディストリビューション(?)で大概のコマンドは busybox という1つの代替コマンドで構成されています。代替できないコマンドはそれぞれの適切なバージョンを引っ張ってきて組み込みます。その内容を眺めていると…MPDの文字がありました。そう、buildrootでもMPDサーバとして動作させることが出来るのだ(と思う)。また、docを見ると Raspberry Pi にも対応していそうな事が書かれていたので、早速これを試してみる事にした。自力でソースコードをコンパイルしてインストールできるのであればディストリビューションに入って無くてもインストールすることは出来るのですがね。

buildrootは頻繁に更新されていてその最新をgitで持ってくる事ができるのですが、一定のレベルで固められた版が用意されていて、それをダウンロードできるので、今回はそれを持て来て構築します(gitで取得してtagをたどってcheckoutしてもおそらく同じ物になります)。因みに、buildroot自体の容量は小さい。が、入れるコマンド等を選択した後にそれぞれのソースコードをダウンロードしつつ全てコンパイルするので、コンパイル時はオブジェクトも含めるとそれなりな容量になるのと、時間がかかるので要注意です。……使用量を調べてみるとデフォルト構成でコンパイル中のオブジェクトを含めても4Mbyteくらいしか使用していなかった…。以外に少ない事にビックリ!

クロスコンパイルはWindows7(64bit)にインストールしたVMware上にUbuntu 14.04(32bit)をインストールし、その上で行いました。

一発目はデフォルト設定でとにかく起動するかの確認を行います。
以下の順でコンパイルをしました。

$ sudo apt-get install build-essential bison flex gettext libncurses5-dev texinfo autoconf automake libtool
$ wget http://buildroot.uclibc.org/downloads/buildroot-2014.11.tar.bz2
$ tar xvf buildroot-2014.11.tar.bz2
$ cd ./buildroot-2014.11/
$ make raspberrypi_defconfig
$ make


手順は buildroot-2014.11/board/raspberry_pi/readme.txt に記載されていました。
buildroot-2014.11/config/raspberrypi_defconfig に反映する内容が書かれているのですが、これ、カーネルも持ってきてコンパイルする事になってます。相当時間がかかりそうだったので、makeを実行してからしばし買い物に出かけて…6時間後くらいに様子を見てみたらコンパイルが終了していました。これは回線の速度にもよるので一概に何時間かかるとは言えないです。

もともと、kernelをコンパイルしていた環境だったのでコマンドの不足もなくエラーもなくすんなりと正常終了していました(apt-getの行は過去の記憶をたどって入れた物を記載しています)。これをSDカードに書き込みます。SDカードは raspbian を入れた物をそのまま使用したので、ファイルを全部削除するだけであえてフォーマットしてないです。構成は第一パーティションがvfat,約60Mbyte、第二パーティションがext4,約2Gbyte。

$ sudo rm -rf /media/boot/*
$ sudo rm -rf /media/rootfs/*
$ cp ./output/images/zImage /media/boot/
$ cp ./output/images/rpi-firmware/* /media/boot/
$ sudo tar xvf ./output/images/rootfs.tar -C /media/rootfs/


このSDカードをRaspberry Piへ装着して実行してみる。Raspberry Piとはシリアル-USB変換ケーブルで繋いでいるので、システム出力は全て拾える様にしている……。

Uncompressing Linux... done, booting the kernel.


あれっ!?
電源を入れてもこんな出力しか出てこないです…。

これはおそらくbootloaderの出力。カーネル以降のログが出力されていない状態。気になったので、HDMI出力をモニタに繋いでみると……カーネル以降の起動ログとログインプロンプトが表示されているではありませんか!! ヘッドレス(Headless:モニター、キーボードを繋がない)構成で使用する予定なので、このままでは都合が悪いです。まだLANの設定もしてないのでSSHで入る事もできないし。

とにかく調査開始です。
カーネル以降の出力がHDMI側へ出ているという事は、起動時のgettyのポート指定が間違っているという事。SDカードの中身をPCで確認してみることに。

rootfsの内容を確認してみると、普段使用しているLinux内容と大違い。まっ、ディストリビューション毎に構成が違うのはLinux(広義)の常ですからね。そこで分かったことはbuildrootのinitはSysVinit…というか busybox init !? だという事。普段使用しているUbuntuはUpstartですからね。まっ、知識の無いsystemdが使われてるよりましです。

/etc/inittab の内容を確認するとシリアル出力先がtty1になってました。これをRaspberry PiのUART0(ttyAMA0)に設定します。

# tty1::respawn:/sbin/getty -L  tty1 115200 vt100 # GENERIC_SERIAL
ttyAMA0::respawn:/sbin/getty -L ttyAMA0 115200 vt100 # GENERIC_SERIAL


それと起動時にkernelの引数として渡している値も変更します。これは第一パーティションに入れている cmdline.txt に記載してある内容を編集します。consoleの所です。何故かconsoleは2回定義されていたので不要と思われる方を削除しておきました。

dwc_otg.fiq_fix_enable=1 sdhci-bcm2708.sync_after_dma=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/mmcblk0p2 rootwait


で再起動してみると、カーネル起動以降の出力もUART0の方へ出力されるようになりました。

Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 3.12.28-quick (jujurou@ubuntu) (gcc version 4.8.3 (Buildroot 2014.11) ) #1 PREEMPT Fri Jan 9 12:15:18 JST 2015
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] Machine: BCM2708
[ 0.000000] Memory policy: ECC disabled, Data cache writeback
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 104648
[ 0.000000] Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=1920 bcm2708_fb.fbheight=1080 bcm2708.boardrev=0xf bcm2708.serial=0xb9e9487d smsc95xx.macaddr=B8:27:EB:E9:48:7D sdhci-bcm2708.emmc_clock_freq=250000000 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 dwc_otg.fiq_fix_enable=1 sdhci-bcm2708.sync_after_dma=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/mmcblk0p2 rootwait
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Memory: 411608K/421888K available (3867K kernel code, 195K rwdata, 1684K rodata, 135K init, 610K bss, 10280K reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
[ 0.000000] vmalloc : 0xda000000 - 0xff000000 ( 592 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xd9c00000 ( 412 MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB)
[ 0.000000] .text : 0xc0008000 - 0xc0573fcc (5552 kB)
[ 0.000000] .init : 0xc0574000 - 0xc0595c38 ( 136 kB)
[ 0.000000] .data : 0xc0596000 - 0xc05c6ca0 ( 196 kB)
[ 0.000000] .bss : 0xc05c6cac - 0xc065f6d8 ( 611 kB)
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] NR_IRQS:394
[ 0.000000] sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps every 4294967ms
[ 0.000000] Switching to timer-based delay loop
[ 0.000000] Console: colour dummy device 80x30
[ 0.000472] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
[ 0.000495] pid_max: default: 32768 minimum: 301
[ 0.000836] Mount-cache hash table entries: 512
[ 0.001588] CPU: Testing write buffer coherency: ok
[ 0.001974] Setting up static identity map for 0xc03ccf00 - 0xc03ccf5c
[ 0.003514] devtmpfs: initialized
[ 0.019360] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 5
[ 0.019959] regulator-dummy: no parameters
[ 0.020299] NET: Registered protocol family 16
[ 0.025172] DMA: preallocated 4096 KiB pool for atomic coherent allocations
[ 0.025508] cpuidle: using governor ladder
[ 0.025530] cpuidle: using governor menu
[ 0.025998] bcm2708.uart_clock = 0
[ 0.027300] hw-breakpoint: found 6 breakpoint and 1 watchpoint registers.
[ 0.027320] hw-breakpoint: maximum watchpoint size is 4 bytes.
[ 0.027335] mailbox: Broadcom VideoCore Mailbox driver
[ 0.027433] bcm2708_vcio: mailbox at f200b880
[ 0.027512] bcm_power: Broadcom power driver
[ 0.027532] bcm_power_open() -> 0
[ 0.027544] bcm_power_request(0, 8)
[ 0.528256] bcm_mailbox_read -> 00000080, 0
[ 0.528273] bcm_power_request -> 0
[ 0.528284] Serial: AMBA PL011 UART driver
[ 0.528439] dev:f1: ttyAMA0 at MMIO 0x20201000 (irq = 83, base_baud = 0) is a PL011 rev3
[ 0.846096] console [ttyAMA0] enabled
[ 0.871486] bio: create slab at 0
[ 0.876786] SCSI subsystem initialized
[ 0.880865] usbcore: registered new interface driver usbfs
[ 0.886555] usbcore: registered new interface driver hub
[ 0.892044] usbcore: registered new device driver usb
[ 0.897510] Advanced Linux Sound Architecture Driver Initialized.
[ 0.904736] Switched to clocksource stc
[ 0.908890] FS-Cache: Loaded
[ 0.911990] CacheFiles: Loaded
[ 0.926876] NET: Registered protocol family 2
[ 0.932558] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.939910] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.946470] TCP: Hash tables configured (established 4096 bind 4096)
[ 0.952893] TCP: reno registered
[ 0.956169] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.962016] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.968634] NET: Registered protocol family 1
[ 0.973427] RPC: Registered named UNIX socket transport module.
[ 0.979438] RPC: Registered udp transport module.
[ 0.984139] RPC: Registered tcp transport module.
[ 0.988868] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.996073] bcm2708_dma: DMA manager at f2007000
[ 1.000775] bcm2708_gpio: bcm2708_gpio_probe c05a2150
[ 1.006195] vc-mem: phys_addr:0x00000000 mem_base=0x1ec00000 mem_size:0x20000000(512 MiB)
[ 1.017084] FS-Cache: Netfs 'nfs' registered for caching
[ 1.022778] NFS: Registering the id_resolver key type
[ 1.028030] Key type id_resolver registered
[ 1.032217] Key type id_legacy registered
[ 1.036620] msgmni has been set to 803
[ 1.041761] io scheduler noop registered
[ 1.045834] io scheduler deadline registered
[ 1.050128] io scheduler cfq registered (default)
[ 1.055255] BCM2708FB: allocated DMA memory 59540000
[ 1.060258] BCM2708FB: allocated DMA channel 0 @ f2007000
[ 1.089326] Console: switching to colour frame buffer device 240x67
[ 1.113896] bcm2708_rng_init=da41a000
[ 1.126372] brd: module loaded
[ 1.133907] loop: module loaded
[ 1.137474] vchiq: vchiq_init_state: slot_zero = 0xda004000, is_master = 0
[ 1.145539] usbcore: registered new interface driver ax88179_178a
[ 1.151799] usbcore: registered new interface driver smsc95xx
[ 1.157823] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[ 1.363925] Core Release: 2.80a
[ 1.367157] Setting default values for core params
[ 1.371982] Finished setting default values for core params
[ 1.577735] Using Buffer DMA mode
[ 1.581058] Periodic Transfer Interrupt Enhancement - disabled
[ 1.586911] Multiprocessor Interrupt Enhancement - disabled
[ 1.592479] OTG VER PARAM: 0, OTG VER FLAG: 0
[ 1.596865] Dedicated Tx FIFOs mode
[ 1.600605] WARN::dwc_otg_hcd_init:1042: FIQ DMA bounce buffers: virt = 0xda422000 dma = 0x59594000 len=9024
[ 1.610495] FIQ FSM acceleration enabled for :
[ 1.610495] Non-periodic Split Transactions
[ 1.610495] Periodic Split Transactions
[ 1.610495] High-Speed Isochronous Endpoints
[ 1.627266] WARN::hcd_init:473: FIQ at 0xc02c6584
[ 1.631968] WARN::hcd_init:474: FIQ ASM at 0xc02c685c length 36
[ 1.637932] WARN::hcd_init:500: MPHI regs_base at 0xda41c000
[ 1.643604] dwc_otg bcm2708_usb: DWC OTG Controller
[ 1.648561] dwc_otg bcm2708_usb: new USB bus registered, assigned bus number 1
[ 1.655878] dwc_otg bcm2708_usb: irq 32, io mem 0x00000000
[ 1.661389] Init: Port Power? op_state=1
[ 1.665413] Init: Power Port (0)
[ 1.668924] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.675762] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.682982] usb usb1: Product: DWC OTG Controller
[ 1.687719] usb usb1: Manufacturer: Linux 3.12.28-quick dwc_otg_hcd
[ 1.693983] usb usb1: SerialNumber: bcm2708_usb
[ 1.699449] hub 1-0:1.0: USB hub found
[ 1.703267] hub 1-0:1.0: 1 port detected
[ 1.708797] bcm2708 watchdog, heartbeat=10 sec (nowayout=0)
[ 1.714627] bcm2835-cpufreq: min=700000 max=700000 cur=700000
[ 1.720572] bcm2835-cpufreq: switching to governor powersave
[ 1.726310] bcm2835-cpufreq: switching to governor powersave
[ 1.732053] sdhci: Secure Digital Host Controller Interface driver
[ 1.738275] sdhci: Copyright(c) Pierre Ossman
[ 1.742822] mmc-bcm2835: Unable to initialise DMA channels. Falling back to PIO
[ 1.784794] Load BCM2835 MMC driver
[ 1.788512] sdhci-pltfm: SDHCI platform and OF driver helper
[ 1.794466] usbcore: registered new interface driver usbhid
[ 1.800216] usbhid: USB HID core driver
[ 1.812551] TCP: cubic registered
[ 1.816004] NET: Registered protocol family 17
[ 1.822706] Key type dns_resolver registered
[ 1.837055] regulator-dummy: incomplete constraints, leaving on
[ 1.846233] ALSA device list:
[ 1.849217] #0: bcm2835 ALSA
 1.852722] Waiting for root device /dev/mmcblk0p2...
[ 1.866272] mmc0: host does not support reading read-only switch. assuming write-enable.
[ 1.874496] mmc0: new SDHC card at address 9c7d
[ 1.879629] mmcblk0: mmc0:9c7d SD08G 7.40 GiB
[ 1.886344] mmcblk0: p1 p2
[ 1.904974] Indeed it is in host mode hprt0 = 00021501
[ 1.966232] EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities
[ 1.979093] EXT4-fs (mmcblk0p2): couldn't mount as ext2 due to feature incompatibilities
[ 2.011844] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[ 2.020145] VFS: Mounted root (ext4 filesystem) on device 179:2.
[ 2.037752] devtmpfs: mounted
[ 2.042094] Freeing unused kernel memory: 132K (c0574000 - c0595000)
[ 2.095153] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 2.102099] Indeed it is in host mode hprt0 = 00001101
[ 2.203310] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
Initializing random number generator... [ 2.315399] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
[ 2.322138] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
done.
[ 2.375752] hub 1-1:1.0: USB hub found
Starting network...
[ 2.395685] hub 1-1:1.0: 3 ports detected

Welcome to Buildroot
buildroot login: [ 2.694925] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 2.815201] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.822089] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.832911] smsc95xx v1.0.4
[ 2.898830] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:e9:48:7d

Welcome to Buildroot
buildroot login:


因みにHDMIの出力はこんな感じでラズベリーの絵が表示されるだけになりました(元はこの下に上記のログが出力されてました)。

rpi_builroot_01.jpg

この状態でのRAMの使用状況はというと…。

# free
total used free shared buffers
Mem: 411740 8960 402780 0 512
-/+ buffers: 8448 403292
Swap: 0 0 0


あれれっ、totalのメモリ容量が少ない気が…。どうやらbuildrootで生成されるconfig.txtとimagesディレクトリに展開されるFirmwareはGPU用のメモリをそれなりに確保する方(デフォルト)のみでGPU使用メモリを最小限にした構成の方はファイルすら置かれていないようです(Memのtotalの量によって判断)。この部分の修正方法は簡単。必要なファイル(fixup_cd.dat, start_cd.elf)を持ってきてconfig.txtの内容を編集するだけ。

$ cp ./output/build/rpi-firmware-53162d55fa557e60453c0652aa00fa3daf4ed618/boot/fixup_cd.dat
$ cp ./output/build/rpi-firmware-53162d55fa557e60453c0652aa00fa3daf4ed618/boot/start_cd.elf


config.txt は gpu_mem=16 を追記します。gpu_mem_256, gpu_mem_512 は不要となるのでコメントアウトしておきました。

arm_freq=700
core_freq=250
kernel=zImage
disable_overscan=1
# gpu_mem_256=100
# gpu_mem_512=100
sdram_freq=400
over_voltage=0

#set GPU mem size
gpu_mem=16


これでGPU使用RAMを最小限にすることが出来ます。が、今のカーネルでは描画用の処理が走ってしまうのでこの部分も削除しておく必要があります。カーネルの再コンパイルとなるのでどのように設定するんだ? と思ったら、ちゃんと方法が用意されてました。以下のコマンドを打つとカーネルの menuconfig を実行出来ます。これはbuildrootのマニュアルにちゃんと書いてあります。

make linux-menuconfig


Device Drivers → Graphics support に出てくる項目全てのチェックを外します。後は make をするとできあがりですが、rootfs.tar も書き換えられちゃうので注意が必要です。/etc/inittab の編集をしないとまたシステム出力が出てくれません。実はこの点に限っては解決策があって、.config の内容を編集することで自動生成してくれます。buildrootのマニュアルを見直した時に気がつきました。

#
# getty options
#
BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200=y
BR2_TARGET_GENERIC_GETTY_BAUDRATE="115200"
BR2_TARGET_GENERIC_GETTY_TERM="vt100"
BR2_TARGET_GENERIC_GETTY_OPTIONS=""


これらを実施してSDカードに書き込んだ結果、以下の様になりました。

# free
total used free shared buffers
Mem: 497264 8388 488876 0 500
-/+ buffers: 7888 489376
Swap: 0 0 0


そして、HDMIに出力される内容はというと、おそらくBCM2835のデフォルト出力内容であろう内容が表示さてました。

rpi_builroot_02.jpg


既にDHCPをつかってLANに繋がるところまで確認していますが、その内容はおいおいという事で…。

tag : RaspberryPi

tag : buildroot

Raspberry Pi の環境構築(失敗談)

Raspberry Pi は2012年の年初に発売されて今年(2014年)はB+という改良版(?)が出てきている状況。今更感が否めないですが、オーディオプレーヤとして最小の構成を目指すべくkrenelのコンパイルと、rootfsの内容を最小構成から増やす方向での構築を試みてみました…が、失敗しました。得た事も多いので記録として残しておきます。


kernelのコンパイルは…多くの方がされているので、その追従です。rootfsの方は、今までSDカードイメージを書き込んでそこからいらない物を止めたり削除したりしていましたが、その逆で、最小構成の物を入れて必要な物を追加するようにします。具体的には、rootfsの方は Linaro にある nano を入れて、そこから apt-get で必要な物を取得して行きます。

何はともあれ、raspbianのSDカードイメージの内容を確認しておきます。これによって必要な物が見えてくると思います(この時点では過去の経験より U-Boot とDevice Tree が必要と思い込んでいました)。そこで、raspbian のSDカードイメージファイルをDLして Win32 Disk Imager でSDカードへ書き込みました。この状態で Raspberry Pi へ差し込んで電源を入れれば raspbian が起動するのですが、今回の目的はそこでは無いので、Raspberry Pi へは差し込まず、PC-Linuxマシンに差し込み、中身を確認しました(正確にはWindows上で動かしている VMware Player 上の Ubuntu で確認)。

$ df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdb1 vfat 57288 9656 47632 17% /media/jujurou/boot
/dev/sdb2 ext4 7515692 2350248 4814820 33% /media/jujurou/5d18be51-3217-4679-9c72-a54e0fc53d6b

$ sudo ls -l /media/jujurou/boot/
total 9656
-rw-r--r-- 1 jujurou jujurou 17824 Jun 19 19:59 bootcode.bin
-rw-r--r-- 1 jujurou jujurou 120 Jun 20 06:51 cmdline.txt
-rw-r--r-- 1 jujurou jujurou 1180 Jun 20 06:51 config.txt
-rw-r--r-- 1 jujurou jujurou 2090 Jun 19 19:59 fixup_cd.dat
-rw-r--r-- 1 jujurou jujurou 5845 Jun 19 19:59 fixup.dat
-rw-r--r-- 1 jujurou jujurou 8822 Jun 19 19:59 fixup_x.dat
-rw-r--r-- 1 jujurou jujurou 137 Jun 20 10:33 issue.txt
-rw-r--r-- 1 jujurou jujurou 3192224 Jun 19 19:59 kernel.img
-rw-r--r-- 1 jujurou jujurou 18974 Sep 25 2013 LICENSE.oracle
-rw-r--r-- 1 jujurou jujurou 512792 Jun 19 19:59 start_cd.elf
-rw-r--r-- 1 jujurou jujurou 2557720 Jun 19 19:59 start.elf
-rw-r--r-- 1 jujurou jujurou 3500744 Jun 19 19:59 start_x.elf

$ uname -a
Linux raspberrypi 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux


SD-USB変換を使っているので、デバイスとしては sdb として見えています。SDカードの中身は2つのパーティションに区切られていて、第1パーティションが VFAT(FAT32) で 第2パーティションが EXT4 でフォーマットされていました。第1パーティションの中身は…ファイル名から内容が分かる物と分からない物とが半々です。このあたりは Raspberry Pi の QA 広場に "How does Raspberry Pi boot?" という内容で起動の順が書かれています。簡単に書くとこんな感じでしょうか。

1. Raspberry Piに電源が入った時はGPUが起動し ARM core はoff、SDRAM も disabled な状態
2. GPUが1段階目のブートローダーを起動。
   → このブートローダーはSoCのROMにある。
   → ブートローダーはSDカードを読み込んで2段階目のブートローダー(bootcode.bin)をL2キャッシュに読み込み実行する。
3. bootcode.bin はSDRAMを有効にし、3段階目のブートローダー(loader.bin)をSDカードからRAMへ読み込んで実行する。
4. loader.bin は GPU firmware(start.elf) を読み込む
5. start.elf は config.txt、cmdline.txt の内容を元に kernel.img を SDRAM のアドレス0x8000に置く。
6. start.elf は ARM core をリセットして kernel.img のある 0x8000 から実行を開始させる。

loader.bin は elfファイルの読み込みとその先頭にジャンプするような簡単なプログラムと思われるので、bootcode.bin に取り込まれた可能性ありです。

この内容を見て驚いたのが、最初に起動する部分がGPUだという点です。いきなり ARM core に行くのではなく、GPUから起動させるという構成。何故そうなっているかは分からないですが、そこは "そういう物だ" と割り切りましょう。何せ、GPUのプログラム部分(bootcode.bin, start.elf)は作れないのですから。

GPUの動きは のぶさん のblog (bobuhiro11's diary) に 「CPUがカーネルを走らせ始めた後もGPUのコードはアンロード されないということが分かりました. GPUは,VCOS (Video Core Operating System)と呼ばれる小さなOSを走らせ, カーネル側とmailboxというプロトコルや割り込みを通して,グラフィックの 操作を行います. 驚いたことにGPUはグラフィックだけでなくクロック制御やオーディオの制御 も行うようです.」 と書かれていました(情報元は "Level of Hackability of raspberry pi" の様だ)。何か、マルチコアちっくな感じです。

Linux の kernel は 3.12.22 が使われています。私の記憶では kernel 3.1 から Device Tree が必要で、".dtb" ファイルが必要だと思っていたのですが、ここでは出現して来ませんでした。Device Tree が必要な場合は kernel のコンパイル時に設定するみたいです(Device tree driven kernel for raspberry pi)。

これである程度 Raspberry Pi に必要な構造が分かってきました。


と、ここで突然ですが、Linuxの大まかな構成について私が知っている事…というか知ったかぶりになっている構造を書いておきます。

Linux…特に Raspberry PiBeagleBone Black, pcDuino, ODROID といった組み込み系Linuxを触りだしてから分かったことは、非常に大雑把に区分けすると、bootloader, Linux kernel + kernel driver, rootfs(ユーザ空間の物) という3つの部分に分ける事ができると言う事です。

「bootloader」は圧縮されている kernel image を解凍してRAM上に展開します(物によっては非圧縮であったり、RAMに展開せずにROM上で動かす事もあります)。この部分はハードウェアにかなり依存していて、kernel を動かすボード毎に異なります。

「Linux kernel + kernel driver」はOSの中核機能を実行するのと、ハードウェアに依存する部分を kernel driver という形で一挙に引き受けています。

「rootfs(ユーザ空間の物)」はアプリケーションです。ハードウェアに依存する部分は kernel と driver が引き受けてくれているので、rootfs 部分はハードウェアにほとんど依存しない形で形成されています。"ls", "cd" といったコマンドもこの部分に該当します。大抵、アーキテクチャが同じであればコンパイル済みのバイナリを使い回す事ができます。

つまり、大抵の場合、用意する必要があるのは bootloader, Linux kernel + kernel driver の2つの部分です。Raspberry Pi に関して言えば、前述した様に bootloader 部分はバイナリ公開なので "Linux kernel + kernel driver" を用意すれば良いことになります(ここでアーキテクチャの事をもっとまじめに考えていれば失敗に至らなかったのに…)。

PC-Linuxで kernel と ドライバ をクロスコンパイルします。
以下のコマンドでコンパイルしました。回線速度にもよりますが、git clone のところで2時間くらいかかりました。

$ sudo apt-get update
$ sudo apt-get install git build-essential
$ git clone https://github.com/raspberrypi/linux.git
$ git clone https://github.com/raspberrypi/tools.git
$ git clone https://github.com/raspberrypi/firmware.git
$ export CROSS_COMPILE=`pwd`/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
$ export ARCH=arm
$ cd ./linux/
$ make mrproper
$ make ARCH=arm bcmrpi_defconfig
$ make ARCH=arm
$ make ARCH=arm modules
$ mkdir ../modules
$ sudo make ARCH=arm INSTALL_MOD_PATH=`pwd`/../modules modules_install
$ sudo make ARCH=arm INSTALL_MOD_PATH=`pwd`/../modules firmware_install


rootfsの内容は Linaro の armhf版を取ってきて使用します。
そのまま使用すると、システム出力先の ttyAMA0 にログが出力されないので、少々手を加えています。

$ wget http://releases.linaro.org/14.07/ubuntu/trusty-images/nano/linaro-trusty-nano-20140727-680.tar.gz
$ tar jxvf linaro-trusty-nano-20140727-680.tar.gz
$ cd ./binary/
$ cp ./etc/init/tty1.conf ./etc/init/ttyAMA0.conf
$ vi ./etc/init/ttyAMA0.conf
$ cat ./etc/init/ttyAMA0.conf
# ttyAMA0 - getty
#
# This service maintains a getty on ttyAMA0 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
not-container or
container CONTAINER=lxc or
container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

respawn
exec /sbin/getty -8 115200 ttyAMA0


後はこれらの内容をSDカードへ書き込みます。
今回は raspbian を書き込んだSDカードの内容にVFAT領域は上書きで、EXT4の領域は一端全て削除して書き込みを行いました。

$ sudo cp ./firmware/boot/* /media/jujurou/boot/
$ sudo cp ./linux/arch/arm/boot/Image /media/jujurou/boot/kernel.img
$ sudo rm -rf /media/jujurou/5d18be51-3217-4679-9c72-a54e0fc53d6b/*
$ cp -r ./binary/* /media/jujurou/5d18be51-3217-4679-9c72-a54e0fc53d6b/
$ cd ./modules/
$ sudo cp ./* /media/jujurou/5d18be51-3217-4679-9c72-a54e0fc53d6b/


これでSDカードの準備は出来ました。
SDカードを Raspberry Pi へセットし、電源ONします。
あっ、私は万が一を想定して Raspberry Pi の UART出力端子とPCを繋いで起動ログを取るようにしてから実行しました。

その結果が以下です。

[    0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 3.12.26+ (jujurou@ubuntu) (gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) ) #1 PREEMPT Sat Aug 9 18:03:44 JST 2014
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] Machine: BCM2708
[ 0.000000] cma: CMA: reserved 8 MiB at 1b800000
[ 0.000000] Memory policy: ECC disabled, Data cache writeback
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 113792
[ 0.000000] Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708.boardrev=0xf bcm2708.serial=0xb9e9487d smsc95xx.macaddr=B8:27:EB:E9:48:7D sdhci-bcm2708.emmc_clock_freq=250000000 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)

 中略

[ 2.824167] EXT4-fs (mmcblk0p2): recovery complete
[ 2.830518] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[ 2.841306] VFS: Mounted root (ext4 filesystem) on device 179:2.
[ 2.860680] devtmpfs: mounted
[ 2.865847] Freeing unused kernel memory: 140K (c05b8000 - c05db000)
[ 2.903622] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 2.903622]
[ 2.917044] CPU: 0 PID: 1 Comm: init Not tainted 3.12.26+ #1
[ 2.924189] [] (unwind_backtrace+0x0/0xec) from [] (show_stack+0x10/0x14)
[ 2.935638] [] (show_stack+0x10/0x14) from [] (panic+0x94/0x1d8)
[ 2.946397] [] (panic+0x94/0x1d8) from [] (do_exit+0x880/0x970)
[ 2.957170] [] (do_exit+0x880/0x970) from [] (do_group_exit+0x40/0xdc)
[ 2.968641] [] (do_group_exit+0x40/0xdc) from [] (get_signal_to_deliver+0x180/0x634)
[ 2.981453] [] (get_signal_to_deliver+0x180/0x634) from [] (do_signal+0xd0/0x440)
[ 2.994159] [] (do_signal+0xd0/0x440) from [] (do_work_pending+0xa4/0xb4)
[ 3.006191] [] (do_work_pending+0xa4/0xb4) from [] (work_pending+0xc/0x20)


最後の方を見れば分かりますが、起動時にカーネルパニックを起こして停止してしまいました。不安要素が沢山あったので、パニックになる事は想定内でしたが、この原因を調べているうちに超重要な事をこの計画段階で忘却していたのが分かってきました。

その原因とは……
「rootfsのアーキテクチャが異なっている!」
でした("あそびばLinux", Debian wiki)。

いやはや、この原因に行き着いたときには愕然としましたね。簡単な事です。Linaro で公開されている armhf版の rootfs の内容は ARMv7用(いわゆるCortex-A/Rシリーズ用) で、Raspberry Pi の ARM core は ARMv6 なんです。ARMv6でもVFPv2を搭載していて、armhf(hard float) のコンパイル結果を使用できるのですが、所詮 ARMv6+VFPv2、ARMv7 アーキテクチャとは異なります。現実をたたきつけられ、しばらくボーっとしてしまいました。



色々と考えはしてみたものの、良い案が浮かびませんでした。
なので、あても無くググってググって……を繰り返している時、偶然にも minibian なる物の存在を知ったのです。SDカードイメージで公開されてます。そうです、ココまでやってきた事全てを無かったことにして、簡単にSDカードの内容を構築する事ができる方法が合ったのです。

この minibian ですが、raspbian をサーバ用途に絞った構成で、描画関連を取り除いてRAMの確保と起動の早さをUPさせているみたいです。最初からSSHサーバが起動しているところを見ると、自分の仕様(MPDサーバ専用機)にでは必要の無い物が多く含まれている可能性はありますが、raspbian から削除しただけの構成なので、apt-get で raspbian 側のバイナリを取ってくる事ができる点が良いです。自分でソースコードからコンパイルをして構築する手もありますが、構築が大変な上に update まで大変になるので、このあたりで妥協しようと思います。

※ Arch Linux とかにするのも手ですが、Debian系(主にUbuntu)に慣れているので、これはパスしてます。

tag : RaspberryPi

tag : Linux

Raspberry Pi の電源強化

Raspberry Pi をジュークボックス(音楽プレーヤ専用機)として使い出して8ヶ月くらいたつ。このジュークボックスはスマホから操作できてかなり便利なのだが、妻もいつでもお手軽に使えるようにと常に電源を入れっぱなしの状態にしている。

Raspberry Pi は発売当初から電源が弱いと言われていて、事実USB周りでトラブルにあった事が多々ある。なので、AC電源を 5V/1.8A品 にして改善していた。しかし、それでも月に1回くらい調子が悪いときがあった。それも、妻が曲を再生している時だけ…。具体的には音楽を再生している時に急に曲が止まる。その後、最後に再生していた1曲しか再生出来ない。といった現象だ。

音楽を再生しながら家事をしているので、電圧変動が原因でUSB-HDDのマウントにしくっているのかと思ったのだが、AC電源の強化はしているし…、と対策に手を拱いていた。そんな中、blacknikkaというblogで Rspberry Pi の電源入り口にあるコンデンサの量を増やすと良さ気だという記事を見つけたので、試してみることにした。

やったことは参考にしたblog内容そのままで、追加のコンデンサはサトー電気で扱っていた低ESRのKZEシリーズ電解コンデンサ 470μF/25V を使用した。高目の耐圧を選んでいるのはより漏れ電流が少なくなる傾向にあるからで、気にしないのなら10V品でも問題無いと思われる。これで良くなる事を祈る。

RIMG0543.jpg

ググっていると何人か同様の改造をされている人(あっきぃ日誌, じとめすきーの覚え書き)がいるようだ。自分とは現象が異なるが、何れにしても電源が弱いのは致命的である。

tag : RaspberryPi

黒ねこ時計 くろック D02
プロフィール

jujurou

Author:jujurou
運営HP:チャコの部屋
Twitter:jujurou

カレンダー
08 | 2017/09 | 10
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
最新記事
最新コメント
カテゴリ
ユーザタグ

ぺるけ RaspberryPi Linux トランジスタ式ミニワッター TRminiWatterPart4 MPD OpenOCD イーサネットコンバータ FON2405E DAC buildroot FM3ペリフェラル BeagleBoneBlack FM3評価ボード library OpenGL mingw ODROID-U2 TL-WR700N Edison bitbake KiCad 計測 VMware シングル FM4 ミニワッター 6N6P プリアンプ 

月別アーカイブ
ランキング

FC2 Blog Ranking

カウンター
検索フォーム
リンク
RSSリンクの表示
QRコード
QRコード
ライセンス
クリエイティブ・コモンズ・ライセンス
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。