前言

之前买了一个luckfox pico plus,有一说一,当时不知道为什么脑子抽了买个这玩意,60多💴,拿来不知道有啥用,就跟着教程随便摸索了一下,记录一下摸索过程。

开始摸索

先看了几遍幸狐科技给的wiki文档,有一说一,还挺通俗易懂,luckfox pico plus使用RV1103处理器,基于单核 ARM Cortex-A7 32 位架构,计算性能可达 0.5 TOPS,板载内存64MB DDR2与板载存储128MB spi nand flash,跟着教程也装了ubuntu(卡的要死)、Buildroot,不过用起来感觉不怎么样,看见教程有Alpine Linux 移植,就跟着进行了移植(幸狐这wiki搬运教程也太不上心了,我看到好多错的地方)。

移植开始

docker运行Alpine Linux容器

我用的windows桌面端docker,所以运行前执行

docker run --rm --privileged multiarch/qemu-user-static --reset --persistent yes

在wsl的ubuntu22.04换行中,执行以下代码,将临时文件挂载到系统,用来存储新的rootfs

dd if=/dev/zero of=rootfs.ext4 bs=1M count=100
mkfs.ext4 rootfs.ext4
mkdir -p /home/luckfox/my-rootfs
sudo mount rootfs.ext4 /home/luckfox/my-rootfs

然后执行启动armv7alpine容器

docker run -it --name armv7alpine --net=host -v /tmp/my-rootfs:/my-rootfs arm32v7/alpine

容器内操作

在容器里,将Alpine Linux的官方源替换成阿里源

sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
apk update

安装openrc用来管理进程

apk add openrc
rc-update add devfs boot
rc-update add procfs boot
rc-update add sysfs boot

添加安全终端 :允许 root 用户从 ttyFIQ0 登录。
删除tty1到tty6开始的行,这一步一定要做,否则串口启动会卡死在找ttyX上。
执行完最好vi /etc/inittab看看ttyFIQ0::respawn:/sbin/agetty --autologin root ttyFIQ0 vt100前面有没有#

echo ttyFIQ0 > /etc/securetty
# 删除 tty1-tty6 的配置
sed -i '/tty[1-6]/d' /etc/inittab
# 添加 ttyFIQ0 自动登录配置
sed -i '/# Put a agetty on the serial port/a ttyFIQ0::respawn:/sbin/agetty --autologin root ttyFIQ0 vt100' /etc/inittab

配置静态ip

cat <<EOF > /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 192.168.1.100
        netmask 255.255.255.0
        gateway 192.168.1.1
EOF

添加开机启动

rc-update add networking default

修改dns

cat <<EOF > /etc/resolv.conf
nameserver 114.114.114.114
nameserver 8.8.8.8
EOF

设置板子名字,方便ssh连接

echo luckfox > /etc/hostname

安装配置ssh,设置登录密码

apk add openssh
vi /etc/ssh/sshd_config
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
rc-update add sshd default
passwd

创建本地启动服务脚本

cat <<EOF > /etc/local.d/crond.start
#!/bin/bash

# 网络校时并启动 crond 定时任务
ntpd -d -q && crond

# 关闭板载 LED 灯 (如果你不想关灯,可以把这行去掉)
echo 0 > /sys/class/leds/work/brightness
EOF
chmod +x /etc/local.d/crond.start
rc-update add local default

配置开机启动ntpd实现网络校时

cat <<EOF > /etc/ntp.conf
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
EOF
rc-update add local default
apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && apk del tzdata

安装需要用到的软件包,最好手动vi /etc/passwd看看第一行改成 /bin/bash了吗

apk add util-linux sqlite btop bash bash-completion
sed -i 's/\/bin\/ash/\/bin\/bash/g' /etc/passwd

将 rootfs 打包,在宿主机的 /home/luckfox/my-rootfs/ 目录下看到一个 alpine.tar.gz 文件。

cd /
for d in bin etc lib root sbin usr; do tar c "$d" | tar x -C /my-rootfs; done
for dir in dev proc run sys var tmp media mnt opt srv; do mkdir -p /my-rootfs/${dir}; done
cd /my-rootfs/ && tar czf alpine.tar.gz *

修改官方SDK根目录下的build.sh文件

function build_sysdrv() {
    echo "============Start building sysdrv============"

    mkdir -p ${RK_PROJECT_OUTPUT_IMAGE}
    build_uboot
    build_kernel
    build_rootfs
    build_recovery

    if [ -z $RK_CUSTOM_ROOTFS ]; then
        rootfs_tarball="$RK_PROJECT_PATH_SYSDRV/rootfs_${RK_LIBC_TPYE}_${RK_CHIP}.tar"
    else
        rootfs_tarball="$RK_CUSTOM_ROOTFS"
    fi

    rootfs_out_dir="$RK_PROJECT_OUTPUT/rootfs_${RK_LIBC_TPYE}_${RK_CHIP}"

    if ! [ -d $RK_PROJECT_OUTPUT ]; then
        mkdir -p $RK_PROJECT_OUTPUT
    fi

    if [ -f $rootfs_tarball ]; then
        if [ -d $rootfs_out_dir ]; then
            rm -rf $rootfs_out_dir
        fi
        if [ -z $RK_CUSTOM_ROOTFS ]; then
            tar xf $rootfs_tarball -C $RK_PROJECT_OUTPUT
        else
            mkdir -p $rootfs_out_dir
            tar xf $rootfs_tarball -C $rootfs_out_dir
        fi
    else
        msg_error "Not found rootfs tarball: $rootfs_tarball"
        exit 1
    fi

    msg_info "If you need to add custom files, please upload them to <Luckfox Sdk>/output/out/rootfs_${RK_LIBC_TPYE}_${RK_CHIP}."
    finish_build
}
function __PACKAGE_ROOTFS() {
    local rootfs_tarball _target_dir _install_dir

    if [ -z $RK_CUSTOM_ROOTFS ]; then
        rootfs_tarball="$RK_PROJECT_PATH_SYSDRV/rootfs_${RK_LIBC_TPYE}_${RK_CHIP}.tar"
    else
        rootfs_tarball="$RK_CUSTOM_ROOTFS"
    fi

    if [ -f $rootfs_tarball ]; then
        if [ -z $RK_CUSTOM_ROOTFS ]; then
            tar xf $rootfs_tarball -C $RK_PROJECT_OUTPUT
        else
            if [ ! -d $RK_PROJECT_PACKAGE_ROOTFS_DIR ]; then
                mkdir $RK_PROJECT_PACKAGE_ROOTFS_DIR
            fi
            tar xf $rootfs_tarball -C $RK_PROJECT_PACKAGE_ROOTFS_DIR
        fi
    else
        msg_error "Not found rootfs tarball: $rootfs_tarball"
        exit 1
    fi

    if [ "$LF_TARGET_ROOTFS" == "buildroot" ] || [ "$LF_TARGET_ROOTFS" == "busybox" ]; then
        build_get_sdk_version
        cat >$RK_PROJECT_PACKAGE_ROOTFS_DIR/bin/sdkinfo <<EOF
#!/bin/sh
echo Build Time:  $(date "+%Y-%m-%d-%T")
echo SDK Version: ${GLOBAL_SDK_VERSION}
EOF
        chmod a+x $RK_PROJECT_PACKAGE_ROOTFS_DIR/bin/sdkinfo
        __COPY_FILES $RK_PROJECT_PATH_APP/root $RK_PROJECT_PACKAGE_ROOTFS_DIR
    fi
    __COPY_FILES $RK_PROJECT_PATH_MEDIA/root $RK_PROJECT_PACKAGE_ROOTFS_DIR
    __COPY_FILES $SDK_ROOT_DIR/external $RK_PROJECT_PACKAGE_ROOTFS_DIR

    if [ -d "$RK_PROJECT_PACKAGE_ROOTFS_DIR/usr/share/iqfiles" ]; then
        (
            cd $RK_PROJECT_PACKAGE_ROOTFS_DIR/etc
            ln -sf ../usr/share/iqfiles ./
        )
    fi

    if [ -f $RK_PROJECT_FILE_ROOTFS_SCRIPT ]; then
        chmod a+x $RK_PROJECT_FILE_ROOTFS_SCRIPT
        cp -f $RK_PROJECT_FILE_ROOTFS_SCRIPT $RK_PROJECT_PACKAGE_ROOTFS_DIR/etc/init.d
    fi
}

修改SDK根目录下的.BoardConfig.mk文件,在文件末尾添加以下内容

export RK_CUSTOM_ROOTFS=../sysdrv/custom_rootfs/alpine.tar.gz

删除output/out/rootfs_uclibc_rv1106目录,确保我们的rootfs生效

rm -rf output/out/rootfs_uclibc_rv1106

编译镜像,然后烧录

cd project
./build.sh lunch
./build.sh

手动挂载tf卡

ls /dev/mmcblk*
mkdir -p /mnt/sdcard
mount -t vfat /dev/mmcblk1p1 /mnt/sdcard
mount -a
df -h

添加开机自启vi /etc/fstab

/dev/mmcblk1p1  /mnt/sdcard  vfat  defaults,noatime  0  0

配置ssh

rc-service sshd status
ssh-keygen -A
mkdir -p /var/empty
chown root:root /var/empty
chmod 755 /var/empty
rc-service sshd start

后续单独编译Rootfs,编译后 :
在 output/image/ 目录下会生成一个新的 rootfs.img 。
烧录时 :使用瑞芯微的烧录工具,只勾选 rootfs 分区,选择这个新的 rootfs.img 进行下载。

./build.sh rootfs

添加内外穿透

借助樱花FRP,下载安装配置

cd /usr/local/bin
# 替换 <下载地址> 为实际链接
wget -O frpc https://nya.globalslb.net/natfrp/client/frpc/0.51.0-sakura-12.3/frpc_linux_armv7
chmod +x frpc
./frpc -v
vi /etc/init.d/frpc
#!/sbin/openrc-run

name="frpc"
description="SakuraFrp Client"

# 你的 frpc 路径
command="/usr/local/bin/frpc"

# 你的启动参数 (把你的 Token 填在这里)
# 例如: command_args="-f wdnmdtoken666666:12345"
command_args="YOUR_TOKEN_HERE"

# 让 frpc 在后台运行
command_background="yes"

# PID 文件路径 (用于管理进程)
pidfile="/run/frpc.pid"

depend() {
    # 依赖网络服务,要在网络启动后再启动
    need net
    after firewall
}
chmod +x /etc/init.d/frpc
rc-service frpc start
rc-update add frpc default

添加虚拟内存SWAP

dd if=/dev/zero of=/mnt/sdcard/swapfile bs=1M count=256
chmod 600 /mnt/sdcard/swapfile
mkswap /mnt/sdcard/swapfile
swapon /mnt/sdcard/swapfile
free -h
vi /etc/fstab
/mnt/sdcard/swapfile  none  swap  sw  0  0

设置crond定时任务(6小时校正一次)

mkdir -p /var/spool/cron/crontabs
ln -s /usr/bin/vi /bin/vi
crontab -e
# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
0       */6     *       *       *       ntpd -d -q