背景
由於項目需要使用了Banana Pi R2這塊板子。參考的資料主要是官方的wiki、GitHub以及論壇。
- 官網:http://banana-pi.org/
- Wiki:http://wiki.banana-pi.org/Main_Page
- 論壇:http://forum.banana-pi.org/
- 鏡像:https://dev.banana-pi.org.cn/Image/BPI-R2/Ubuntu16.04/
- BSP:https://github.com/BPI-SINOVOIP/BPI-R2-bsp-4.14
初探
先使用官方提供的鏡像,製作SD卡啓動盤,查看效果。
宿主機環境:
root@liu:~# uname -a
Linux liu 4.15.0-45-generic #48~16.04.1-Ubuntu SMP Tue Jan 29 18:03:48 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
從官網下載最新鏡像:
2017-11-28-ubuntu-16.04-mate-desktop-bpi-r2-sd-emmc.img.zip
安裝工具:
root@liu:~# apt install -y gcc-arm-linux-gnueabihf u-boot-tools curl pv
root@liu:~# curl -sL https://github.com/BPI-SINOVOIP/bpi-tools/raw/master/bpi-tools | sudo -E bash
格式化SD卡 (需要保證SD卡的容量是8G或者以上的)
查看SD卡對應的盤符
root@liu:~# fdisk –l
刪除SD的所有分區
root@liu:~# fdisk /dev/sdx
格式化SD卡位FAT模式
root@liu:~# mkfs.vfat /dev/sdx -I
燒寫鏡像到SD卡
root@liu:~# dd if=[imagename] of=/dev/sdx bs=10M
定製系統
官方的鏡像太龐雜,希望自己可以定製一個。
編譯BSP
先清空之前的內容
root@liu:~# cd /root/src/BPI-R2-bsp-4.14、
root@liu:~# ./build.sh
選擇 7
重新編譯
root@liu:~# ./build.sh
選擇 1
需要等待一會,該過程會編譯u-boot、kerenl、以及打包。
創建文件系統
安裝依賴工具包
root@liu:~# apt-get install qemu-user-static debootstrap binfmt-support parted zip
從官網下載Ubuntu16的最小文件系統
http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/
root@liu:~# mkdir rootfs
root@liu:~# tar xvf ubuntu-base-16.04-core-armhf.tar.gz -C rootfs
利用qemu和chroot
cp /etc/resolv.conf rootfs/etc/resolv.conf
root@liu:~# cp /usr/bin/qemu-arm-static rootfs/usr/bin/
root@liu:~# chroot /root/image/rootfs
現在通過qemu模擬器進入了剛製作的根文件系統
root@liu:/# ls
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
root@liu:/# pwd
/
更新apt源
root@liu:~# vi /etc/apt/sources.list
deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial universe
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial multiverse
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial multiverse
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
root@liu:~# apt update
root@liu:~# apt upgrade
root@liu:~# apt-get dist-upgrade
安裝必備包
root@liu:~# apt install language-pack-en-base sudo ssh net-tools ethtool wireless-tools ifupdown network-manager iputils-ping rsyslog bash-completion vim minicom lrzsz gcc
設置主機名
root@liu:~# echo "bpi-r2" >/etc/hostname
root@liu:~# vi /etc/hosts
127.0.0.1 localhost
127.0.1.1 bpi-r2
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
設置root用戶對於的密碼
root@liu:/# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
創建普通用戶
root@liu:~# useradd -m -G users,sudo,ssh -s /bin/bash bpi
root@liu:~# passwd bpi
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
設置時區
root@liu:~# locale-gen en_US
root@liu:~# locale-gen en_US.UTF-8
root@liu:~# dpkg-reconfigure tzdata
root@liu:~# update-locale LANG=en_US.UTF-8
設置fstab
root@liu:~# vi /etc/fstab
proc /proc proc defaults 0 0
LABEL=BPI-BOOT /boot vfat errors=remount-ro 0 1
LABEL=BPI-ROOT / ext4 defaults,noatime 0 0
設置網絡
root@liu:~# vi /etc/network/interfaces
# loop
auto lo
iface lo inet loopback
#first set the upstream-Port (NIC between CPU and MT7530-Switch) up
auto eth0
iface eth0 inet manual
pre-up ip link set $IFACE up
post-down ip link set $IFACE down
auto eth1
iface eth1 inet manual
pre-up ip link set $IFACE up
post-down ip link set $IFACE down
#then configure the lan-ports
auto lan0
iface lan0 inet static
address 172.16.30.252
netmask 255.255.255.0
gateway 172.16.30.1
pre-up ip link set $IFACE up
post-down ip link set $IFACE down
修改ssh配置
root@liu:~# vi /etc/ssh/sshd_config
PermitRootLogin yes
PubkeyAuthentication no
#AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
清理不必要的包
root@liu:~# rm -rf /var/lib/apt/lists/*
root@liu:~# apt clean
退出qemu
root@liu:~# exit
root@liu:~# rm /root/image/rootfs/usr/bin/qemu-arm-static
製作鏡像文件
創建一個新的image文件,大小爲8G
root@liu:~# dd if=/dev/zero bs=1M count=7296 | pv | dd of=bpi.img
加載該鏡像爲虛擬盤
root@liu:~# losetup /dev/loop8 bpi.img
分區並且格式化
root@liu:~# parted -s /dev/loop8 mklabel msdos
root@liu:~# parted -s /dev/loop8 unit MiB mkpart primary fat32 -- 100MiB 356MiB
root@liu:~# parted -s /dev/loop8 unit MiB mkpart primary ext2 -- 356MiB 7295MiB
root@liu:~# partprobe /dev/loop8
root@liu:~# mkfs.vfat /dev/loop8p1 -I -n BPI-BOOT
root@liu:~# mkfs.ext4 -O ^has_journal -E stride=2,stripe-width=1024 -b 4096 /dev/loop8p2 -L BPI-ROOT
root@liu:~# sync
掛載文件系統
root@liu:~# mkdir /mnt/rootfs
root@liu:~# mount /dev/loop8p2 /mnt/rootfs
root@liu:~# mkdir /mnt/rootfs/boot
root@liu:~# mount /dev/loop8p1 /mnt/rootfs/boot
拷貝之前製作的文件系統到該鏡像
root@liu:~# cp -a /root/image/rootfs/* /mnt/rootfs
進入BSP目錄
root@liu:~# cd /root/src/BPI-R2-bsp-4.14
拷貝boot分區文件:BPI-BOOT-bpi-r2.tgz
root@liu:~# tar xvf SD/BPI-BOOT-bpi-r2.tgz --keep-directory-symlink -C /mnt/rootfs/boot
拷貝內核文件:4.14.34-BPI-R2-Kernel.tgz、4.14.34-BPI-R2-Kernel-net.tgz
root@liu:~# tar xvf SD/4.14.34-BPI-R2-Kernel.tgz --keep-directory-symlink -C /mnt/rootfs
root@liu:~# tar xvf SD/4.14.34-BPI-R2-Kernel-net.tgz --keep-directory-symlink -C /mnt/rootfs
拷貝BootLoader文件:BOOTLOADER-bpi-r2.tgz
root@liu:~# tar xvf SD/BOOTLOADER-bpi-r2.tgz --keep-directory-symlink -C /mnt/rootfs
把電源按鍵放到黑名單
root@liu:~# echo "blacklist mtk_pmic_keys" > /mnt/rootfs/etc/modules-load.d/mtk_pmic_keys.conf
卸載文件系統
root@liu:~# umount /mnt/rootfs/boot
root@liu:~# umount /mnt/rootfs
寫入頭文件: BPI-R2-HEAD440-0k.img、BPI-R2-HEAD1-512b.img
droot@liu:~# d if=mt-pack/mtk/bpi-r2/bin/BPI-R2-HEAD440-0k.img of=/dev/loop8 bs=1024 seek=0
root@liu:~# dd if=mt-pack/mtk/bpi-r2/bin/BPI-R2-HEAD1-512b.img of=/dev/loop8 bs=512 seek=1
寫入preloader:preloader_iotg7623Np1_sd_1600M.bin 和u-boot:u-boot.bin
root@liu:~# dd if=mt-pack/mtk/bpi-r2/bin/preloader_iotg7623Np1_sd_1600M.bin of=/dev/loop8 bs=1024 seek=2
root@liu:~# dd if=u-boot-mt/u-boot.bin of=/dev/loop8 bs=1024 seek=320
root@liu:~# sync
刪除loop盤
root@liu:~# losetup -d /dev/loop8
把鏡像寫入SD卡
root@liu:~# fdisk -l
root@liu:~# dd if=/root/image/bpi.img of=/dev/sdx bs=10M
腳本
上面的命令,集成到腳本文件中
#!/bin/bash -v
IMAGE=/root/image/bpi.img
BSP=/root/BPI-R2-bsp-4.14
[ -f $IMAGE ] && rm $IMAGE
sudo dd if=/dev/zero bs=1M count=7296 | pv | dd of=$IMAGE
sudo losetup /dev/loop8 $IMAGE
sudo parted -s /dev/loop8 mklabel msdos
sudo parted -s /dev/loop8 unit MiB mkpart primary fat32 -- 100MiB 356MiB
sudo parted -s /dev/loop8 unit MiB mkpart primary ext2 -- 356MiB 7295MiB
sudo partprobe /dev/loop8
sudo mkfs.vfat /dev/loop8p1 -I -n BPI-BOOT
sudo mkfs.ext4 -O ^has_journal -E stride=2,stripe-width=1024 -b 4096 /dev/loop8p2 -L BPI-ROOT
sync
[ -d /mnt/rootfs ] || sudo mkdir /mnt/rootfs
sudo mount /dev/loop8p2 /mnt/rootfs
[ -d /mnt/rootfs/boot ] || sudo mkdir /mnt/rootfs/boot
sudo mount /dev/loop8p1 /mnt/rootfs/boot
sudo cp -a /root/image/rootfs/* /mnt/rootfs
cd $BSP
sudo tar xvf SD/BPI-BOOT-bpi-r2.tgz --keep-directory-symlink -C /mnt/rootfs/boot
sudo tar xvf SD/4.14.34-BPI-R2-Kernel.tgz --keep-directory-symlink -C /mnt/rootfs
sudo tar xvf SD/4.14.34-BPI-R2-Kernel-net.tgz --keep-directory-symlink -C /mnt/rootfs
sudo tar xvf SD/BOOTLOADER-bpi-r2.tgz --keep-directory-symlink -C /mnt/rootfs
sudo umount /mnt/rootfs/boot
sudo umount /mnt/rootfs
sudo dd if=mt-pack/mtk/bpi-r2/bin/BPI-R2-HEAD440-0k.img of=/dev/loop8 bs=1024 seek=0
sudo dd if=mt-pack/mtk/bpi-r2/bin/BPI-R2-HEAD1-512b.img of=/dev/loop8 bs=512 seek=1
sudo dd if=mt-pack/mtk/bpi-r2/bin/preloader_iotg7623Np1_sd_1600M.bin of=/dev/loop8 bs=1024 seek=2
sudo dd if=u-boot-mt/u-boot.bin of=/dev/loop8 bs=1024 seek=320
sync
sudo losetup -d /dev/loop8
sudo dd if=$IMAGE of=/dev/sdc bs=10M
應用
業務層面需要使用操作GPIO和UART,需要注意的的一些細節如下。
GPIO
查看GPIO的基數,可以看到是:232
root@liu:~# mount -t debugfs none /sys/kernel/debug
root@liu:~# cat /sys/kernel/debug/pinctrl/1000b000.pinctrl/gpio-r
GPIO ranges handled:
0: 1000b000.pinctrl GPIOS [232 - 511] PINS [0 - 279]
以GPIO205爲例,具體的值爲,437(232+205) 操作方式如下
root@liu:~# echo 437 > /sys/class/gpio/export
root@liu:~# echo out > /sys/class/gpio/gpio437/direction
root@liu:~# echo 1 > /sys/class/gpio/gpio437/value
root@liu:~# echo 292 > /sys/class/gpio/unexport
UART
通過設備數可以瞭解到終端使用的是ttyS0,對應關係如下
- ttyS0 <–> Uart2
- ttyS1 <–> Uart0
- ttyS2 <–> Uart1
設備數信息
root@liu:~# vi linux-mt/arch/arm/boot/dts/mt7623.dtsi
uart2: serial@11004000 {
compatible = "mediatek,mt7623-uart",
"mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x400>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pericfg CLK_PERI_UART2_SEL>,
<&pericfg CLK_PERI_UART2>;
clock-names = "baud", "bus";
status = "disabled";
};
uart0: serial@11002000 {
compatible = "mediatek,mt7623-uart",
"mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x400>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pericfg CLK_PERI_UART0_SEL>,
<&pericfg CLK_PERI_UART0>;
clock-names = "baud", "bus";
status = "disabled";
};
uart1: serial@11003000 {
compatible = "mediatek,mt7623-uart",
"mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x400>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pericfg CLK_PERI_UART1_SEL>,
<&pericfg CLK_PERI_UART1>;
clock-names = "baud", "bus";
status = "disabled";
};
root@liu:~# vi linux-mt/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
uart0_pins_a: uart@0 {
pins_dat {
pinmux = <MT7623_PIN_79_URXD0_FUNC_URXD0>,
<MT7623_PIN_80_UTXD0_FUNC_UTXD0>;
};
};
uart1_pins_a: uart@1 {
pins_dat {
pinmux = <MT7623_PIN_81_URXD1_FUNC_URXD1>,
<MT7623_PIN_82_UTXD1_FUNC_UTXD1>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_a>;
status = "okay";
};
&uart2 {
status = "okay";
};
參考
http://www.fw-web.de/dokuwiki/doku.php?id=en:bpi-r2:start
http://forum.banana-pi.org/t/how-to-build-an-ubuntu-debian-sd-image-from-scratch/6805
http://forum.banana-pi.org/t/gpio-uart-not-the-debug-port/3748/6