当前位置: 首页 > 工具软件 > Banana PI > 使用案例 >

Bananapi R2 定制系统

於意蕴
2023-12-01

背景

由于项目需要使用了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、以及打包。

配置内核选项

配置pty
在内核中选择Unix98 PTY,这样会在/dev/下生成pts目录,及pty节点。如果不配置,会出现下面的现象:ssh连接上了,但是不显示shell终端。

Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.14.34-BPI-R2-Kernel armv7l)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

配置串口扩展芯片支持

USB FTDI Single Port Serial Driver 

配置overlay文件系统

 <*> Overlay filesystem support
 [*]   Overlayfs: turn on redirect dir feature by default
 [*]   Overlayfs: turn on inodes index feature by default

这个docker依赖的底层文件系统。

创建文件系统

安装依赖工具包

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 ntpdate kmod
  • ntpdate,如果系统时间不准,可以通过ntpdate cn.pool.ntp.org,进行更新
  • kmod,这个安装包是包含modprobe等命令的,如果没有它,后续运行docker会有问题。

设置DNS

# vi /etc/resolv.conf
nameserver 127.0.1.1
nameserver 8.8.8.8

如果不设置,能上网,但ping不通百度。

# ping www.baidu.com
ping: unknown host www.baidu.com

设置主机名

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

无网络开机慢
现象: Ubuntu 16.04开机

A start job is running for Raise network interface(5min 4s)

解决方式:

vim /etc/systemd/system/network-online.target.wants/networking.service

将里面的TimeoutStartSec=5min 修改为TimeoutStartSec=5sec
重启系统

安装docker
参考:https://docs.docker.com/engine/install/ubuntu/
安装完之后,默认是没有/etc/docker/daemon.json这个文件的。新建该文件:

# vi /etc/docker/daemon.json
{
  "registry-mirrors": ["http://hub-mirror.c.163.com"]
}

清理不必要的包

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

root@liu:~# dd 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

 类似资料: