前言

荔枝派nano是一个基于全智F1C100S的类派开发板。在开始之前,请先通读官方教程的即食部分(U-Boot)、Linux编译SPI-Flash系统的创建部分的教程,并搭建好编译工具链。以下我假设你已经按照上面的教程下载好了U-Boot和Linux内核,并且到Buildroot的官网下载好了Buildroot(但没按教程创建config文件)。

本文的目标是创建一个支持USB和Wifi的运行在SPI-Flash上的精简系统。此系统使用SquashFS压缩根文件系统以获得更大的存储空间,同时使用JFFS2作为额外的配置文件存储的位置。本人技术不行,故没有实现使用OverlayFS做到根文件系统可修改,还请各位大神能提供响应的思路。

SPI-Flash的分区结构

以下是我这里的分区结构。你可以自由的分配后面两个分区的大小。

ID  SIZE    USAGE   ADDR
0   448kb   U-boot  0x0000 0000 - 0x0007 0000
1   64kb    dtb     0x0007 0000 - 0x0008 0000
2   4mb     kernel  0x0008 0000 - 0x0048 0000
3   7.5mb   rootfs  0x0048 0000 - 0x00c0 0000
4   4mb     overlay 0x00c0 0000 - 0x0100 0000   

U-Boot的编译和填坑

按照上面的U-Boot的编译教程来编译基本上是没有什么太大问题。我这里就说一下上面教程里面没有说的配置:

设置内核启动参数

勾上[*] Enable boot arguments,然后在下面填上:

panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=squashfs

其中,root=/dev/mtdblock3指定了第3分区为rootfs所在分区,rootfstype=squashfs指定了这个分区的格式是squashfs。

设置Bootcmd

勾上[*] Enable a default value for bootcmd,然后在下面填上:

sf probe 0 60000000; sf read 0x80c00000 0x70000 0x10000; sf read 0x80008000 0x80000 0x400000; bootz 0x80008000 - 0x80c00000

0x70000和0x80000分别是分区1和2的起始地址。

减小U-Boot体积

默认配置下,U-Boot的体积是接近1M的,但实际上U-Boot本体才270k左右。多余的空间实际上是被环境配置所占据了。

进入Environment菜单,找到Environment Offset。这个Offset就是配置的偏移地址,只要它比U-Boot本体大就可以了。这里我设置成0x68000,并将Environment Size设置成0x8000,这样编译出来的U-Boot大小就正好是0x70000,也就是448kb。

设置显示输出日志

勾上Console下的 Enable console multiplexing 和 Select console devices from environment,就可以在屏幕上看到启动日志了。

Linux的编译和填坑

Linux的坑就稍微有些多了。在做接下来的东西之前,你最好先载入官方的配置文件。

SPI-Flash的支持

进入 Device Drivers -> SPI support,将 Allwinner A10 SoCs SPI controller取消勾选,然后勾上下面的Allwinner A31 SPI Controller。这是为了修正配置文件中SPI驱动不正确的问题。

勾上并进入 Device Drivers -> Memory Technology Device (MTD) support,选上下面两项:

  • Command line partitioning table parsing #为了解析内核参数传过来的分区信息,如果用设备树应该可以不选
  • Caching block device access to MTD devices  #为了生成/dev/mtdblock*设备,不选会在启动的时候卡在 watiting for device /dev/mtdblock*

取消勾选 General setup -> initramfs support (存疑)。

再进入Filesystem Drivers,选上JFFS2和SquashFS的支持。

然后打开drivers/mtd/spi-nor/spi-nor.c,检查自己的flash型号的参数是否含有SECT_4K,如果有则改为0。例如对于w25q128,需要将 { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },改为{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, 0) }

最后修改设备树文件中的分区信息,可以参考前面官方教程里面的dts修改章节。

flash@0 {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "macronix,mx25l12805d", "jedec,spi-nor";
    reg = <0>;
    spi-max-frequency = <50000000>;
    partitions {
      compatible = "fixed-partitions";
      #address-cells = <1>;
      #size-cells = <1>;

      partition@0 {
        label = "u-boot";
        reg = <0x000000 0x70000>;
        read-only;
      };

      partition@70000 {
        label = "dtb";
        reg = <0x70000 0x10000>;
        read-only;
      };

      partition@80000 {
        label = "kernel";
        reg = <0x80000 0x400000>;
        read-only;
      };

      partition@480000 {
        label = "rootfs";
        reg = <0x480000 0x780000>;
      };
      
      partition@c00000 {
        label = "overlayfs";
        reg = <0xc00000 0x400000>;
      };
    };
  };

USB Gadget的支持

为了方便调试,需要启用USB Gadget。

转到 Device Driver -> USB support -> USB Gadget support,勾上 Usb gadget functions configurable through configfs,和上面的Serial gadget console support,以及下面的CDC ACM、CDC ECM、RNDIS、FunctionFS,再取消USB Gadget precomposed configurations的勾选。(具体原因和操作方法可以看我前面的文章

对文件drivers/clk/sunxi-ng/ccu-suniv.c应用下面这个补丁,修正USB驱动问题

--- ../linux/drivers/clk/sunxi-ng/ccu-suniv.c    2019-01-15 22:48:18.824587965 +0800
+++ drivers/clk/sunxi-ng/ccu-suniv.c    2019-01-23 09:05:17.959348454 +0800
@@ -238,7 +238,7 @@
/* The BSP header file has a CIR_CFG, but no mod clock uses this definition */

static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",    "osc24M",
-              0x0cc, BIT(8), 0);
+              0x0cc, BIT(1), 0);

static SUNXI_CCU_GATE(dram_ve_clk,    "dram-ve",    "pll-ddr",
              0x100, BIT(0), 0);

Wifi支持

我这里用的是rtl8723bs,所以在drivers->staging里面启用相关的驱动就可以了。

屏幕背光亮度调整

首先修改suniv.dtsi,增加pinctrl和pwm节点

diff --git a/arch/arm/boot/dts/suniv.dtsi b/arch/arm/boot/dts/suniv.dtsi
index ee600cd1b..2205e0243 100644
--- a/arch/arm/boot/dts/suniv.dtsi
+++ b/arch/arm/boot/dts/suniv.dtsi
@@ -238,6 +238,15 @@
 				pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
 				function = "mmc0";
 			};
+            
+			pwm0_pins: pwm0 {
+				pins = "PE12";
+				function = "pwm0";
+			};
+			pwm1_pins: pwm1 {
+				pins = "PE6";
+				function = "pwm1";
+			};
 		};
 
 		timer@1c20c00 {
@@ -251,6 +260,14 @@
 			compatible = "allwinner,sun6i-a31-wdt";
 			reg = <0x01c20ca0 0x20>;
 		};
+        
+		pwm: pwm@1c21000 {
+		 	compatible = "allwinner,sun7i-a20-pwm";
+		 	reg = <0x01c21000 0xC>;
+		 	clocks = <&osc24M>;
+		 	#pwm-cells = <3>;
+		 	status = "disabled";
+		 };
 
 		uart0: serial@1c25000 {
 			compatible = "snps,dw-apb-uart";

再修改suniv-f1c100s-licheepi-nano.dts

diff --git a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
index f46e1909b..2d01404ef 100644
--- a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
+++ b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
@@ -7,6 +7,7 @@
 #include "suniv-f1c100s.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "Lichee Pi Nano";
@@ -26,7 +27,6 @@
 		compatible = "qiaodian,qd43003c0-40", "simple-panel";
 		#address-cells = <1>;
 		#size-cells = <0>;
-		enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>;
 
 		port@0 {
 			reg = <0>;
@@ -46,6 +46,23 @@
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 1 500000 0>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
 };
 
 &de {
@@ -105,3 +155,9 @@
 	usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */
 	status = "okay";
 };
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm1_pins>;
+	status = "okay";
+};

Buildroot的使用和rootfs的编译

下载Buildroot后解压,不要使用官方的配置文件,应当自己从零开始编译。

基础设置

Target options
  -- Target Architecture (ARM (little endian))
  -- Target Variant arm926t
Toolchain
  -- C library (musl) # 使用musl减小最终体积
System configuration
  -- Use syslinks to /usr .... # 启用/bin, /sbin, /lib的链接
  -- Enable root login # 启用root登录
  -- Run a getty after boot # 启用登录密码输入窗口
  -- remount root filesystem # 重新挂载根文件系统到可读写
  -- Install Timezone info # 安装时区信息。我的程序需要所以就打开了这个玩意
     -- timezone list (asia)
     -- default local time (Asia/Shanghai)
Target Packages
  -- mount/umount # 如果要用overlayfs,那就要用这个挂载

网络部分软件包

这里我给出包名然后自己搜素就好了

  • ifupdown scripts
  • iw # 用做无线网络管理的,可不要
  • wpa_supplicant # 无线网络管理需要这个玩意
  • linux-firmware -> rtl87xx # 无线网卡的固件

其他可能需要的软件包

  • lrzsz # rz/sz命令,用于传输文件
  • gawk # 用于解析iw命令的输出
  • dialog # 用于wifish管理的图形界面的生成

Busybox的设置

有一些软件包在busybox内是自带的,可以到使用busybox的menuconfig进行配置。需要先运行一次make生成busybox的构建文件夹,然后再使用 make busybox-menuconfig 配置。每次clean后都需要重新配置一次,因为在clean的时候这个配置会被清除。

可能需要的软件包:

  • ntpd # 网络自动校正时间
  • udhcpc # dhcp客户端

烧写镜像的生成和其他设置

下面所说的所有操作都包含在这个打包脚本里面了:licheepi-nano-image-master

镜像的生成

这里有个脚本可以一键生成镜像。

    OUT_FILENAME="flashimg.bin"

    UBOOT_FILE=../u-boot-new/u-boot-sunxi-with-spl.bin
    KERNEL_DIR=../linux
    KERNEL_MODULES_DIR=$KERNEL_DIR/out/*
    DTB_FILE=$KERNEL_DIR/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb
    KERNEL_FILE=$KERNEL_DIR/arch/arm/boot/zImage
    ROOTFS_FILE=../buildroot-2018.11.1/output/images/rootfs.tar
    SPEC_FILE=./custom/*
    SCRIPTES=./scripts/*.sh

    dd if=/dev/zero of=$OUT_FILENAME bs=1M count=16
    dd if=$UBOOT_FILE of=$OUT_FILENAME bs=1K conv=notrunc
    dd if=$DTB_FILE of=$OUT_FILENAME bs=1K seek=448  conv=notrunc
    dd if=$KERNEL_FILE of=$OUT_FILENAME bs=1K seek=512  conv=notrunc

    mkdir rootfs
    tar xf $ROOTFS_FILE -C ./rootfs

    cp -r $KERNEL_MODULES_DIR rootfs/usr/
    cp -r $SPEC_FILE rootfs/

    # add some custom modify
    for f in $SCRIPTES; do
        ROOTFS_PATH=./rootfs bash "$f" -H
    done

    fakeroot mksquashfs rootfs/ rootfs.img -no-exports -no-xattrs -all-root
    fakeroot mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0x400000 -o jffs2.img -d overlay/

    dd if=rootfs.img of=$OUT_FILENAME  bs=1K seek=4608  conv=notrunc
    dd if=jffs2.img of=$OUT_FILENAME bs=1M seek=12 conv=notrunc

    rm -rf rootfs rootfs.img jffs2.img

启用Gadget与串口

需要增加一个开机启动脚本,指向前面文章的USB gadget的配置脚本。

需要修改/etc/inittab,增加ttyGS0的getty。

sed -i 's/\# Put a getty on the serial port/\# Put a getty on the serial port\nttyGS0::respawn:\/sbin\/getty -L ttyGS0 0 vt100 # GENERIC_SERIAL/g' $ROOTFS_PATH/etc/inittab

配置网络

修改/etc/network/interface,增加wlan0

auto wlan0
iface wlan0 inet dhcp
    pre-up wpa_supplicant -i wlan0 -c /overlay/etc/wpa_supplicant.conf -B
    wait-delay 15
    hostname \$\(hostname\)
    post-down killall -q wpa_supplicant

为了使wpa_supplicant.conf可写,故我将其放在了overlay分区上。

配置挂载点

修改/etc/fstab,增加一行/dev/mtdblock4 /overlay jffs2 defaults 0 0
这就将第四分区挂载到了/overlay上。需要注意这个文件夹需要预先创建

配置wpa_supplicant

在overlay分区创建etc/wpa_supplicant.conf,内容如下:

    ctrl_interface=/var/run/wpa_supplicant
    ctrl_interface_group=wheel
    update_config=1
    eapol_version=1
    ap_scan=1
    fast_reauth=1

增加的update_config=1是为了让wpa_cli能够修改这个文件,保存wifi的配置。

创建/etc/wpa_supplicant/wpa_cli-action.sh,内容见:
https://git.yoctoproject.org/cgit/cgit.cgi/meta-intel-edison/plain/meta-intel-edison-distro/recipes-connectivity/wpa_supplicant/wpa-supplicant/wpa_cli-actions.sh

增加一个启动脚本,命令行为:/usr/sbin/wpa_cli -a /etc/wpa_supplicant/wpa_cli-action.sh -B
上面的两个脚本的作用是让wpa_cli在Wifi连接上后调用wpa_cli-action.sh,从而自动调用udhcpc获取ip地址。

wifish

按照安装脚本将wifish的文件复制到它们应该在的地方。启动后就可以调用wifish来配置WiFi了。

中科世为串口屏幕的适配

中科世为串口屏幕与荔枝派nano用的是同一个CPU方案,但其硬件与nano有一定的差别。若要驱动此屏幕,则需要将PE5端口拉高以启用屏幕的供电。
理论上应该有使用设备树启用端口的方案,然而我太菜了没有成功实现。我的方法是修改sunxi的gpio.c,在端口初始化代码的最后配置并拉高了PE5。

分类: 未分类

1 条评论

f1c100s linux踩坑记录 – Molly's Blog · 2021 年 5 月 17 日 下午 12:30

[…] 参考大佬的文章,成功编译了u-boot+linux+buildroot,插电,开机! […]

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注