一、查看荔枝派Nano的分区内容
1. 分区查看
共有两个分区,第一个分区作为uboot、dtb、内核等文件;第二个分区是跟文件系统。
2. 第一个分区
通过mount进行挂载,查看到内容包括:主要是dtb设备树和zImage压缩的内核。由于u-boot不是是通过dd指令传输到指定的位置,因此这里不显示。还有一个scr,这是一个uboot启动时加载命令的提示,也需要放在第一个分区。
3. 第二个分区
挂载,查看内容:主要是linux的根文件。
二、构建需要的文件并且烧录到SD卡
1. 教程:主要参考荔枝派Nano
uboot教程:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/get_started/first_eat.html
boot.scr教程:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/build_sys/bootargs.html
dtb和zImage教程:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/build_sys/kernel.html
Linux根文件教程:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/build_sys/rootfs.html
2. 格式化SD卡
参考:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/build_sys/build_index.html
通过fldisk /dev/sdb进行操作,第一个分区32M,并且进行格式化。
3. 烧录uboot
uboot通过dd指令进行烧录,uboot烧录教程:https://github.com/peng-zhihui/Planck-Pi。
需要通过dd烧录到8k位置。
sudo dd if=./u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8 &&
sync
4. 写入其他文件
通过mount进行挂载,然后cp。
sudo mount /dev/sdb1 /mnt/sdcard/
cd /mnt/sdcard/
sudo cp ~/f1c200s/u-boot/tools/boot.scr /mnt/sdcard/
cd /home/tju/f1c200s/Linux/arch/arm/boot
sudo cp ./zImage /mnt/sdcard/
sudo cp ./dts/suniv-f1c100s-licheepi-nano.dtb /mnt/sdcard/
ls /mnt/sdcard/
三、问题
1. 可以进入uboot,但是进入不了linux内核?
**方法1:**手动加载内核和设备树
在U-Boot命令行中,您可以手动加载内核和设备树文件,确保它们位于正确的内存地址。例如:
load mmc 0:1 0x80008000 zImage
load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb
bootz 0x80008000 - 0x80C00000
执行这些命令后,系统应该进入Linux内核。但是报错了.
2. 继续解决
发现是没有配置串口登录,参考:https://wiki.sipeed.com/soft/Lichee/zh/Nano-Doc-Backup/build_sys/rootfs.html
在烧录了之后,需要检查 rootfs文件下的 /etc/inittab 是否已有以下声明,一般来说没有,因此需要修改。之后按照上述手动加载就可以登录了。
ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 # GENERIC_SERIAL // 串口登录使能
3. 为什么要手动加载,不能够自动加载进入linux内核吗?GPT的回答如下,通过在uboot中输入如下指令确实可以解决。
可能的原因:
-
U-Boot 的
bootcmd
没有正确配置或保存:
在 U-Boot 中,bootcmd
环境变量指定了启动时自动执行的命令序列。如果这个变量没有正确设置或保存,U-Boot 就不会自动加载内核、设备树和根文件系统,而是等待手动输入命令。 -
U-Boot 环境变量未保存:
如果您在 U-Boot 中设置了bootcmd
环境变量,但没有保存(使用saveenv
),那么在重启 U-Boot 后这些设置会丢失,导致启动时不能自动执行。 -
启动命令配置不正确:
即使bootcmd
被正确配置,可能在命令中存在错误,导致内核、设备树文件未能正确加载。
4. 解决方法:
1. 检查并设置 bootcmd
环境变量
确保您在 U-Boot 中正确设置了 bootcmd
环境变量。这个变量应该包含加载内核和设备树、以及启动内核的命令。例如,假设您的内核镜像 zImage
和设备树文件 suniv-f1c100s-licheepi-nano.dtb
存在于第一个分区,并且根文件系统在第二个分区(mmcblk0p2
)上,您可以将以下命令设置为 bootcmd
:
setenv bootcmd 'load mmc 0:1 0x80008000 zImage; load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb; bootz 0x80008000 - 0x80C00000'
这里的命令做了以下几件事:
- 从 SD 卡的第一个分区(
mmc 0:1
)加载内核镜像zImage
到内存地址0x80008000
。 - 从同一分区加载设备树文件
suniv-f1c100s-licheepi-nano.dtb
到内存地址0x80C00000
。 - 使用
bootz
命令启动内核。
2. 保存环境变量
设置完 bootcmd
后,您需要使用 saveenv
命令保存环境变量,这样它们在重启后才能生效:
saveenv
3. 重启 U-Boot
保存环境变量后,您可以使用以下命令重启系统:
reset
此时,U-Boot 应该会根据设置的 bootcmd
自动加载内核和设备树,启动 Linux 系统,而不需要手动执行命令。
- 重写boot.cmd,并替换原来的,看能否解决,相比于之前的去除了显示屏输出。
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw
load mmc 0:1 0x80008000 zImage
load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb
bootz 0x80008000 - 0x80C00000
但还是不行!
看来目前的boot.cmd有点儿问题,需要后续处理,但是在boot中写入了上述环境变量后就没问题了,先暂时不处理。
四、串口登录
1. 使用mobaxterm进行串口登录
很方便,需要简单设置一下
2. 在bootroot中修改账密
通过make menuconfig设置,修改账号和密码为自己需要的,简单一点。参考
3. 后续优化
删除内核中不必要的设备树,比如目前没有用到SPI0的flash,也没有屏幕和触摸屏,进行注释。也可以加上自己的LED灯,但加上之哦胡会在后续的使用中出现busy。目前如下。
// tju@tju-XW-2:~/f1c200s/Linux/arch/arm/boot/dts$ cat suniv-f1c100s-licheepi-nano.dts
// SPDX-License-Identifier: (GPL-2.0+ OR X11)
/*
* Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
*/
/dts-v1/;
#include "suniv-f1c100s.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "Lichee Pi Nano";
compatible = "licheepi,licheepi-nano", "allwinner,suniv-f1c100s",
"allwinner,suniv";
aliases {
serial0 = &uart0;
spi0 = &spi0;
};
chosen {
stdout-path = "serial0:115200n8";
};
/*
panel: panel {
compatible = "qiaodian,qd43003c0-40", "simple-panel";
#address-cells = <1>;
#size-cells = <0>;
enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
panel_input: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_out_lcd>;
};
};
};
*/
/*
panel: panel {
compatible = "lg,lb070wv8", "simple-panel";
#address-cells = <1>;
#size-cells = <0>;
enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
panel_input: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_out_lcd>;
};
};
};
*/
reg_vcc3v3: vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
leds {
compatible = "gpio-leds";
blue_led {
label = "licheepi:blue:usr";
gpios = <&pio 4 3 GPIO_ACTIVE_LOW>; /* PE3 */
};
green_led {
label = "licheepi:green:usr";
gpios = <&pio 4 4 GPIO_ACTIVE_LOW>; /* PE4 */
default-state = "on";
};
};
};
&de {
status = "okay";
};
&mmc0 {
vmmc-supply = <®_vcc3v3>;
bus-width = <4>;
broken-cd;
status = "okay";
};
&otg_sram {
status = "okay";
};
/*
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
status = "okay";
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "winbond,w25q128", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
};
};
*/
/*
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
status = "okay";
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "winbond,xt25f128b", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
};
};
*/
/*
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
status = "okay";
spi-max-frequency = <50000000>;
flash: xt25f128b@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "winbond,xt25f128b", "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 0x100000>;
read-only;
};
partition@100000 {
label = "dtb";
reg = <0x100000 0x10000>;
read-only;
};
partition@110000 {
label = "kernel";
reg = <0x110000 0x400000>;
read-only;
};
partition@510000 {
label = "rootfs";
reg = <0x510000 0xAF0000>;
};
};
};
};
*/
/*
&tcon0 {
pinctrl-names = "default";
pinctrl-0 = <&lcd_rgb666_pins>;
status = "okay";
};
&tcon0_out {
tcon0_out_lcd: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_input>;
};
};
*/
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
&usb_otg {
dr_mode = "otg";
status = "okay";
};
&usbphy {
usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */
status = "okay";
};
4. 命令行点灯
通过如下指令进行电灯,注意对于PE4这类的,应该是432+4计算得到。对于PD0则是332+0=96得到编号,由于上述添加了PE3和PE4为LED,通过如下指令会显示busy,因此这里使用PD0,并且用万用表测试。
1. 导出GPIO引脚
首先,你需要导出控制LED的GPIO引脚,使其可以通过sysfs
访问。例如,如果你选择GPIO引脚96,你可以通过以下命令将其导出:
echo 96 > /sys/class/gpio/export
2. 设置GPIO为输出模式
然后,设置该GPIO引脚为输出模式:
echo "out" > /sys/class/gpio/gpio96/direction
3. 控制LED的开关
控制LED的开和关就是通过写入GPIO的值文件来实现的:
-
点亮LED(假设LED是接地的,输出高电平):
echo 1 > /sys/class/gpio/gpio96/value
-
熄灭LED(假设LED是接地的,输出低电平):
echo 0 > /sys/class/gpio/gpio96/value
4. 释放GPIO引脚
当不再需要使用该GPIO引脚时,你可以通过以下命令释放它:
echo 96 > /sys/class/gpio/unexport
示例脚本
你可以将上述命令放在一个脚本中,来实现LED的开关控制:
#!/bin/bash
# 导出GPIO96
echo 96 > /sys/class/gpio/export
# 设置为输出模式
echo "out" > /sys/class/gpio/gpio96/direction
# 点亮LED
echo 1 > /sys/class/gpio/gpio96/value
# 等待5秒
sleep 5
# 熄灭LED
echo 0 > /sys/class/gpio/gpio96/value
# 释放GPIO96
echo 96 > /sys/class/gpio/unexport
将这个脚本保存为led_control.sh
,然后通过以下命令运行:
chmod +x led_control.sh
./led_control.sh
5. 重大问题:无法运行脚本或编译后的文件
对于上述sh脚本,或者交叉编译后的文件,均无法在开发板中运行,显示not found。
解决方法: