写在前边
H3有很多开发板可以参考,主要有nanopi、orangepi等,这些开发板上大部分支持debian的系统,本着学习的目的,想运行一把openwrt。Openwrt18.06已经对全志的很多板子做了支持,这里主要参考了nanopi-m1-plus.
openwrt开发环境配置及原理
- 下载openwrt,可以通过github拉取最新代码,网速比较慢也可以下载压缩包后再解压,最新已经有19.07,不过我这里用的是18.06。
git clone https://github.com/openwrt/openwrt.git (github直接下载)
https://github.com/openwrt/openwrt (或者从网站下载压缩包)
- Linux系统,我用的是虚拟机安装ubuntu18.04LTS,4G内存+100GB硬盘,小了不够用。
- 参考openwrt readme应该更新一下源和软件包
/scripts/feeds update -a
./scripts/feeds install -a
有时候会出错,我这里一般是网络问题,速度太不给力,可以直接点击链接,用迅雷一类的工具下载会快一些。还有一种情况不是网络问题,类似依赖一类的问题,Openwrt邮箱列表有人提到再执行一遍这两条命令可解决,中间遇到过一次,果然如此。
4. 如果使用的是openwrt支持的板子,剩下就非常简单,直接配置板子,编译,等待。。。就行
make menuconfig
make
- Openwrt初看起来,源码都没有,由一堆脚本和配置文件组成,网上讲解较多,主要关注目录结构,主Makefile流程
https://www.jianshu.com/p/1fe3d27509da
<target>目录包含了openwrt支持的平台相关的代码,重点关注内核补丁,如果需要移植新的平台或者在支持的平台添加新的板子,都需要修改这里,添加补丁。
<package>目录包含了很多openwrt基础包,内部boot文件夹包含了uboot对一些平台的支持,本次移植也要在这里打上uboot的补丁用来支持我们自己的板子。
<dl>目录包含了下载的压缩包
除了这些原有和自带的目录外,我们可以新建一个 <files>目录,这个目录下的内容会在构建RootFS时覆盖原有的文件,一般可放一些配置文件,比如etc/config/network,放一下统一的配置,减少我们手动修改配置的过程。
移植前的准备
所谓移植,也不是从0开始,我们可以选择一个类似的平台,比如本次我们主要参考的有nanopi-m1-plus 和orangepi-plus. 列个表格对比一下重点关注硬件的不同。
配置 | icore5 | nanopi-m1-plus | orangepi-plus |
---|---|---|---|
ddr3 | 1GB | 1GB | 1GB |
sdio0 | sd卡 | sd卡 | sd卡 |
sdio0-cd | PF6 | PF6 | PF6 |
sdio1 | fpga | bcm4329 | rtl8189 |
sdio2 | emmc | emmc | emmc |
gmac | rgmii phyaddr01 | rgmii phyaddr 07 | rgmii |
USB3 | rtl8188 | - | - |
pmic | AXP152 | - | SY8106A |
由上可以看到主要的差别时在pmic和wifi上边,pmic负责启动板上外设电源,如ddr、io、core电源等,电源启动必须在系统外设使能前,如必须在ddr使用前给ddr3供电,uboot第二阶段代码已经在ddr上执行,所以必须在spl中使能pmic(i2c接口),并正确配置电源电压。另外就是sdio1, 参考的板卡都是接到了wifi卡上,我们这个接到了fpga上,用来交互信息,暂时忽略;usb wifi也暂时忽略,不影响移植,后续在加。
openwrt 增加新支持设备的方法。
网上说法很多,先看看官方的说法
https://openwrt.org/docs/guide-developer/adding_new_device
嗯~,说的很详细,一步一步添加什么文件,但是看不懂,还是不知道怎么做,怎么添加没告诉我们。再看看网友的说法
https://blog.csdn.net/chenyefei/article/details/77905919
这位网友很不错,附上了3个示例提交,大约知道怎么添加了。 总结一下:
- 在 <./target/linux/$(platform)/image/Makefile>内添加新设备影像的配置,针对icore5,就是在cortexa7.mk内添加内容,模仿nanopi添加以下内容,就可以在make menuconfig中看到新板子了
define Device/sun8i-h3-icore5
DEVICE_TITLE:=icore5
DEVICE_PACKAGES:=kmod-rtc-sunxi \
kmod-leds-gpio kmod-ledtrig-heartbeat \
kmod-brcmfmac brcmfmac-firmware-43430-sdio wpad-mini
SUPPORTED_DEVICES:=xinda,icore5
SUNXI_DTS:=sun8i-h3-icore5
endef
TARGET_DEVICES += sun8i-h3-icore5
里边的内容,SUNXI_DTS指定了新的设备树文件。这个内核中还没有,需要添加,添加的方法有直接添加和打补丁两种,都介绍一下。
a. 直接添加
在<./build_dir/target-$(chip)/linux-$(chip)/linux-$(version)> 找到linux源码树,针对本例也就是 ./openwrt-openwrt-18.06/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-sunxi_cortexa7/linux-4.14.160。如果找不到这个路径,就是之前还没编译过,运行 make target/linux/prepare 准备一下源码树,这个操作会将<dl>目录下的linux内核源码压缩包解压到上述路径,并且将<./target/linux/$(platform)/patches-$(version)/>目录内的补丁按照补丁的编号依次打上,如果出错则退出。准备好源码树后,就可以针对icore5,在dts目录下添加自己板子的设备树。直接添加的代码,在运行 make target/linux/clean时会被删除,只建议在测试时使用,测试通过后一定要制作补丁,否则代码丢了就得不偿失。
b. 打补丁添加
由上述步骤可知,编译时,会自动打补丁,也就是我们可以将补丁放到指定目录中,让系统自动打,这样也不会污染源码,更方便后续维护。制作补丁的方法,简单点就是准备好源码树后,进入源码目录,执行quilt new num-new.patch; 然后通过quilt edit 修改代码或者添加代码,最后执行quilt refresh生成补丁,将补丁拷贝至<./target/linux/$(platform)/patches-$(version)/>目录内即可。
- 重新make menuconfig 选择icore5板子,编译;失败,看提示,应该时uboot缺失,因为更改了目标,uboot中还没有添加相应的规则。类似的,uboot 在<./package/boot/uboot-sunxi/>目录,发现该目录下也有个patch目录,是的,这个目录跟linux源码patch目录的作用时一样的。首先修改Makefile,添加icore5的配置
define U-Boot/icore5
BUILD_SUBTARGET:=cortexa7
NAME:=Icore5
BUILD_DEVICES:=sun8i-h3-icore5
endef
并在下边的UBOOT_TARGETS中添加icore5, 注意定义的名字应该与 **_defconfig 一致,如上述定义,我们应该在uboot源码树中添加icore5_defconfig; 这样在编译uboot时就会自动执行 make icore5_defconfig.
同样的,我们建议在uboot下打补丁修改代码。
最终验证
在<files>目录添加配置 <etc/config/network> ,当前只有rgmii phy这一路通了,就先配一路, 内容如下:
config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd71:468e:86c5::/48'
config interface 'lan'
option type 'bridge'
option ifname 'eth0'
option proto 'static'
option netmask '255.255.255.0'
option ip6assign '60'
option ipaddr '192.168.10.2'
config device 'lan_eth0_dev'
option name 'eth0'
option macaddr '0c:ef:af:c3:14:9e'
最终在bin目录下生成了 ext4和squashfs两种类型的镜像,我选择ext4镜像,解压到当前目录,使用dd命令下载到sd卡中,插上sd卡,使用dd命令将镜像烧录在sd卡起始位置。系统跑起来了:
U-Boot SPL 2017.11 (Dec 26 2019 - 13:02:32)
DRAM: 0 MiB
### ERROR ### Please RESET the board ###
U-Boot SPL 2017.11 (Dec 26 2019 - 13:02:32)
DRAM: 1024 MiB
Trying to boot from MMC1
U-Boot 2017.11 (Dec 26 2019 - 13:02:32 +0000) Allwinner Technology
CPU: Allwinner H3 (SUN8I 1680)
Model: icore5
DRAM: 1 GiB
MMC: SUNXI SD/MMC: 0, SUNXI SD/MMC: 1
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: No ethernet found.
starting USB...
No controllers found
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
reading /boot.scr
377 bytes read in 14 ms (25.4 KiB/s)
## Executing script at 43100000
reading uImage
2518520 bytes read in 134 ms (17.9 MiB/s)
reading dtb
14332 bytes read in 22 ms (635.7 KiB/s)
## Booting kernel from Legacy Image at 42000000 ...
Image Name: ARM OpenWrt Linux-4.14.160
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2518456 Bytes = 2.4 MiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
## Flattened Device Tree blob at 43000000
Booting using the fdt blob at 0x43000000
Loading Kernel Image ... OK
Using Device Tree in place at 43000000, end 430067fb
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.14.160 (yhangzzz@yhangzzz-virtual-machine) (gcc version 7.3.0 (OpenWrt GCC 7.3.0 unknown)) #0 SMP PREEMPT Thu Dec 26 13:02:32 2019
[ 0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=30c5387d
[ 0.000000] CPU: div instructions available: patching division code
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
...
root@OpenWrt:/# ifconfig
br-lan Link encap:Ethernet HWaddr 0C:EF:AF:C3:14:9E
inet addr:192.168.10.2 Bcast:192.168.10.255 Mask:255.255.255.0
inet6 addr: fe80::eef:afff:fec3:149e/64 Scope:Link
inet6 addr: fd71:468e:86c5::1/60 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:692 errors:0 dropped:0 overruns:0 frame:0
TX packets:218 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:97464 (95.1 KiB) TX bytes:22147 (21.6 KiB)
eth0 Link encap:Ethernet HWaddr 0C:EF:AF:C3:14:9E
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1130 errors:0 dropped:7 overruns:0 frame:0
TX packets:403 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:154722 (151.0 KiB) TX bytes:78851 (77.0 KiB)
Interrupt:28
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:192 errors:0 dropped:0 overruns:0 frame:0
TX packets:192 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:13056 (12.7 KiB) TX bytes:13056 (12.7 KiB)
最后附上,uboot和linux的补丁文件。
uboot补丁文件:
--- /dev/null
+++ b/configs/icore5_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=408
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_TEXT_BASE=0x60
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-icore5"
+CONFIG_SUN8I_EMAC=y
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-icore5.dts
@@ -0,0 +1,44 @@
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "icore5";
+ compatible = "icore5", "allwinner,sun8i-h3";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+};
+
+&mmc0 {
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -331,7 +331,8 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
sun8i-h3-nanopi-m1.dtb \
sun8i-h3-nanopi-m1-plus.dtb \
sun8i-h3-nanopi-neo.dtb \
- sun8i-h3-nanopi-neo-air.dtb
+ sun8i-h3-nanopi-neo-air.dtb \
+ sun8i-h3-icore5.dtb
dtb-$(CONFIG_MACH_SUN8I_R40) += \
sun8i-r40-bananapi-m2-ultra.dtb
dtb-$(CONFIG_MACH_SUN8I_V3S) += \
linux 补丁文件:
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-icore5.dts
@@ -0,0 +1,63 @@
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+
+/ {
+ model = "icore5";
+ compatible = "xinda,icore5", "allwinner,sun8i-h3";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &emac;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&mmc0 {
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ status = "okay";
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <®_vcc3v3>;
+ vqmmc-supply = <®_vcc3v3>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-handle = <&rgmii_phy>;
+ phy-mode = "rgmii";
+ snps,reset-gpio = <&pio 3 14 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 30000>;
+ status = "okay";
+};
+
+&external_mdio {
+ rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
注意: linux补丁文件不全,没有在 dts/Makefile中添加 sun8i-h3-icore5.dtb ,测试时直接再源码树修改了Makefile,有兴趣的同学可以再做一个补丁。
来源:oschina
链接:https://my.oschina.net/u/4232364/blog/3159558