记录_第三十三章uboot移植

1、如何通将NXP官方的uboot移植移植到正点原子的开发板上

注: NXP:恩智浦半导体公司, 2006年创立 前身为荷兰飞利浦公司于1953年成立的半导体事业部 2015年收购飞思卡尔半导体(由摩托罗拉创立) 成为全球前十大非存储类半导体公司 及全球最大的汽车半导体供应商 2019年 福布斯全球数字经济100强榜位列78位 2020年 福布斯全球企业2000强榜第1025位 全球汽车零部件企业百强榜。

uboot 移植不是从零将 uboot 移植到所使用的开发板上,这个工作是半导体厂商做的,半导体商将 uboot 移植到他们芯片上,做一个开发板,这个开发板叫原厂开发板(原厂 BSP 包)。
做产品的会参考原厂的开发板做硬件,然后在原厂提供的 BSP 包上修改,将 uboot 或者 linux kernel 移植到自己的硬件上。
uboot 移植一般流程:
①、uboot 中找到参考开发平台,一般是原厂的开发板。
②、参考原厂开发板移植 uboot 到使用的开发板上。

正点原子 I.MX6ULL 开发板参考 NXP 官方的 I.MX6ULL EVK 开发板做的硬件,移植 uboot 的时候以 NXP 官方的 I.MX6ULL EVK 开发板为蓝本。

移植前,先编译 NXP 官方 I.MX6ULL EVK 开发板对应的 uboot,
配置uboot,configs 目录下有很多跟 I.MX6UL/6ULL 有关的配置如图 以 mx6ul 开头的是 I.MX6UL 芯片的
以 mx6ul 开头的是 I.MX6UL 芯片,mx6ull 开头的是 I.MX6ULL 开发板,I.MX6UL/6ULL 有 9x9mm 和 14x14mm 两种尺寸的,使用的是14x14mm的芯片,所以关注 mx6ull_14x14 开头的默认配置文件,正点原子的 I.MX6ULL 有 EMMC 和NAND 两个版本,因此我们最终只需要关注mx6ull_14x14_evk_emmc_defconfig 和mx6ull_14x14_evk_nand_defconfig 这两个配置文件。
实验使用EMMC 版本的移植,所以使用 mx6ull_14x14_evk_emmc_defconfig。
编译 uboot

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
-j指定的是并行作业的数量,告诉 make 同时应该运行多少个任务,设置 -j 参数时,尝试使用比可用核心数多一些的作业通常是为了充分利用潜在的并行性能,但是系统会根据可用资源来调度任务的执行。如果同时运行太多任务,可能会导致系统资源竞争,反而影响性能。在双核处理器上,通常使用 -j4 或 -j8 作为参数值更为合适,以充分利用核心,但又不会过度竞争系统资源。 太麻烦 在顶层 Makefile 中直接给 ARCH(目标平台) 和CORSS_COMPILE(交叉编译选项) 赋值 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/549defb465274856b967c6beed72cc7b.png) 可使用简短的命令来编译 uboot
make mx6ull_14x14_evk_emmc_defconfig
make V=1 -j16

第二种方法创建 shell 脚本,shell 脚本名为 mx6ull_14x14_emmc.sh,然后在 shell 脚本里面输入如下
内容:

 #!/bin/bash
 1 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
 2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-mx6ull_14x14_evk_emmc_defconfig
 3 make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

#!/bin/bash 是特殊指令。在类Unix系统中,告诉操作系统要使用哪个解释器来执行这个脚本。此处使用 Bash 解释器。
第一行命令使用 make 工具清理当前目录下的项目。ARCH=arm 和 CROSS_COMPILE=arm-linux-gnueabihf- 是用于指定目标平台及编译配置的交叉编译的配置选项,distclean 是一个清理操作的目标。
mx6ull_14x14_emmc.sh 这个文件可执行权限,distclean编译 uboot每次都会清理一下工程,然后重新编译

./mx6ull_14x14_evk_emmc.sh

编译完成以后会生成 u-boot.bin、u-boot.imx 等文件,烧写验证

chmod 777 imxdownload //给予 imxdownload 可执行权限
./imxdownload u-boot.bin /dev/sdd //烧写到 SD 卡中,不能烧写到/dev/sda 或 sda1 里面

NXP 官方 I.MX6ULL EVK 开发板的 uboot 在正点原子 EMMC 版本 I.MX6ULL
开发板上的运行情况:
①、uboot 启动正常,DRAM 识别正确,SD 卡和 EMMC 驱动正常。
②、uboot 里面的 LCD 驱动默认是给 4.3 寸 480x272 分辨率的,如果使用的其他分辨率的
屏幕需要修改驱动。
③、网络不能工作,识别不出来网络信息,需要修改驱动。
接下来我们要做的工作如下:
①、前面我们一直使用着 NXP 官方开发板的 uboot 配置,接下来需要在 uboot 中添加我们
自己的开发板,也就是正点原子的 I.MX6ULL 开发板。
②、解决 LCD 驱动和网络驱动的问题。

1.1、在 U-Boot 中添加自己的开发板

NXP 官方 uboot 中默认是 NXP 的开发板,可以直接在官方的开发板上直接修改 uboot 运行在我们的板子上,但不能了解 uboot 是如何添加新平台的,接下来参考 NXP 官方的 I.MX6ULL EVK 开发板,学习如何在 uboot 中添加新的开发板或者开发平台。

1.1.1、添加开发板默认配置文件mx6ull_alientek_emmc_defconfig

configs 目录下创建默认配置文件,复制 mx6ull_14x14_evk_emmc_defconfig,重
命名为 mx6ull_alientek_emmc_defconfig

cd configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig

修改 mx6ull_alientek_emmc_defconfig 文件中第一行和第四行的内容

1 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_
emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"
2 CONFIG_ARM=y
3 CONFIG_ARCH_MX6=y
4 CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y
5 CONFIG_CMD_GPIO=y

1.1.2、添加开发板对应的头文件mx6ull_alientek_emmc.h

在 目 录 include/configs 下 添 加 开 发 板 对 应 的 头 文 件,复 制
include/configs/mx6ullevk.h,并重命名为 mx6ull_alientek_emmc.h

cp include/configs/mx6ullevk.h include/configs/mx6ull_alientek_emmc.h

拷贝完成后,修改

#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

这些宏定义基本用于配置 uboot。

1.1.3、添加开发板对应的板级文件夹mx6ull_alientek_emmc

uboot 中每个板子都有一个对应的文件夹来存放板级文件,如开发板上外设驱动文件等,NXP 的 I.MX 系列芯片都存放在 board/freescale 目录下的mx6ullevk 的文件夹。
复制 mx6ullevk,将其重命名为 mx6ull_alientek_emmc

cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc

进 入 mx6ull_alientek_emmc 目 录 , 将 其 中 的 mx6ullevk.c 文 件 重 命 名 为mx6ull_alientek_emmc.c

1.1.3.1、修改 mx6ull_alientek_emmc 目录下的 Makefile 文件

第 6 行的 obj-y,改为 mx6ull_alientek_emmc.o,这样才会编译 mx6ull_alientek_emmc.c文件

1 # (C) Copyright 2015 Freescale Semiconductor, Inc.
2 #
3 # SPDX-License-Identifier: GPL-2.0+
4 #
5 
6 obj-y := mx6ull_alientek_emmc.o
7 
8 extra-$(CONFIG_USE_PLUGIN) := plugin.bin
9 $(obj)/plugin.bin: $(obj)/plugin.o
10 $(OBJCOPY) -O binary --gap-fill 0xff $< $@

1.1.3.2、修改 mx6ull_alientek_emmc 目录下的 imximage.cfg 文件

imximage.cfg 中的下面一句

PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

改为

PLUGIN board/freescale/mx6ull_alientek_emmc /plugin.bin 0x00907000

1.1.3.3、修改 mx6ull_alientek_emmc 目录下的 Kconfig 文件

1 if TARGET_MX6ULL_ALIENTEK_EMMC
2 
3 config SYS_BOARD
4 default "mx6ull_alientek_emmc"
5 
6 config SYS_VENDOR
7 default "freescale"
8 
9 config SYS_SOC
10 default "mx6"
11
12 config SYS_CONFIG_NAME
13 default "mx6ull_alientek_emmc"
14
15 endif

1.1.3.4、修改 mx6ull_alientek_emmc 目录下的 MAINTAINERS 文件

1 MX6ULL_ALIENTEK_EMMC BOARD
2 M: Peng Fan <peng.fan@nxp.com>
3 S: Maintained
4 F: board/freescale/mx6ull_alientek_emmc/
5 F: include/configs/mx6ull_alientek_emmc.h

1.1.4、修改 U-Boot 图形界面配置文件

uboot 支持图形界面配置,修改文件arch/arm/cpu/armv7/mx6/Kconfig(如果是 I.MX6UL 板子,修改 arch/arm/Kconfig 这个文件),在 207 行加入如下内容:

1 config TARGET_MX6ULL_ALIENTEK_EMMC
2 bool "Support mx6ull_alientek_emmc"
3 select MX6ULL
4 select DM
5 select DM_THERMAL

最后一行的 endif 的前一行添加如下内容

source "board/freescale/mx6ull_alientek_emmc/Kconfig"

到此,I.MX6U-ALPHA 开发板就已经添加到 uboot 中了。
接下来就是编译这个新添加的开发板

1.2、使用新添加的板子配置编译 uboot

uboot 根目录下新建一个名为 mx6ull_alientek_emmc.sh 的 shell 脚本,输入

1 #!/bin/bash
2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
3 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格)
mx6ull_alientek_emmc_defconfig
4 make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

第 3 行我们使用的默认配置文件就是 1.1.1 节中新建的mx6ull_alientek_emmc_defconfig 配置文件,给予可执行权限,运行脚本完成编译

chmod 777 mx6ull_alientek_emmc.sh //给予可执行权限,一次即可
./mx6ull_alientek_emmc.sh //运行脚本编译 uboot

编译 完成 以 后 输 入 如 下命 令,查 看 一 下 1.1.2 小 节 中 添加 的
mx6ull_alientek_emmc.h 这个头文件有没有被引用

grep -nR "mx6ull_alientek_emmc.h"

如果有很多文件都引用了该头文件,说明新板子添加成功,如图
在这里插入图片描述

1.3、LCD 驱动修改

一般 uboot 中修改驱动是在 xxx.h 和 xxx.c 这两个文件中进行的,xxx 为板子名称,如 mx6ull_alientek_emmc.h 和 mx6ull_alientek_emmc.c 这两个文件。
一般修改 LCD 驱动重点注意以下几点:
①、LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确。
②、LCD 背光引脚 GPIO 的配置。
③、LCD 配置参数是否正确。
正点原子的 I.MX6U-ALPHA 开发板 LCD 原理图和 NXP 官方 I.MX6ULL 开发板一致,即 LCD 的 GPIO和背光引脚 GPIO 都一样,所以 IO 部分就不用修改,需要修改 LCD 配置参数。
打开文件 mx6ull_alientek_emmc.c,找到如下

1 struct display_info_t const displays[] = {{
2 .bus = MX6UL_LCDIF1_BASE_ADDR,
3 .addr = 0,
4 .pixfmt = 24,
5 .detect = NULL,
6 .enable = do_enable_parallel_lcd,
7 .mode = {
8 .name = "TFT43AB",
9 .xres = 480,
10 .yres = 272,
11 .pixclock = 108695,
12 .left_margin = 8,
13 .right_margin = 4,
14 .upper_margin = 2,
15 .lower_margin = 4,
16 .hsync_len = 41,
17 .vsync_len = 10,
18 .sync = 0,
19 .vmode = FB_VMODE_NONINTERLACED
20 } } };

图中定义了一个变量 displays,类型为 display_info_t,这是 LCD信息结构体,其中包括 LCD 的分辨率,像素格式,LCD 的各个参数等。display_info_t 定义在文件 arch/arm/include/asm/imx-common/video.h 中;其中还有个 mode 成员变量,此成员变量也是个结构体,为 fb_videomode,定义在文件 include/linux/fb.h 中。
这些参数与第二十四章讲解 RGB LCD 的时候参数基本一样,唯一不同的是像素时钟 pixclock ,以正点原子的 7 寸 1024*600 分辨率的屏幕(ATK7016)为例,屏幕要求的像素时钟为 51.2MHz,因此:

pixclock=(1/51200000)*10^12=19531

根据其他的屏幕参数,可以得出 ATK7016 屏幕的配置参数如下,替换掉 mx6ull_alientek_emmc.c 中 uboot 默认的屏幕参数

1 struct display_info_t const displays[] = {{
2 .bus = MX6UL_LCDIF1_BASE_ADDR,
3 .addr = 0,
4 .pixfmt = 24,
5 .detect = NULL,
6 .enable = do_enable_parallel_lcd,
7 .mode = {
8 .name = "TFT7016",
9 .xres = 1024,
10 .yres = 600,
11 .pixclock = 19531,
12 .left_margin = 140, //HBPD
13 .right_margin = 160, //HFPD
14 .upper_margin = 20, //VBPD
15 .lower_margin = 12, //VFBD
16 .hsync_len = 20, //HSPW
17 .vsync_len = 3, //VSPW
18 .sync = 0,
19 .vmode = FB_VMODE_NONINTERLACED
20 } } };

打开 mx6ull_alientek_emmc.h,将所有

panel=TFT43AB

改为

panel=TFT7016

修改完成后重新编译 uboot 并烧写到 SD 中启动
重启 LCD 驱动一般会工作正常,LCD 上回显示 NXP 的 logo。但是有可能会遇到LCD 并没有工作,还是黑屏,在 uboot 命令模式输入“print”来查看环境变量 panel 的值,会发现 panel 的值要是 TFT43AB(或其他不是 TFT7016)
因为之前有将环境变量保存到 EMMC 中,uboot 启动会先从 EMMC 中读取环境变量,如果 EMMC 中没有环境变量的话才会使用 mx6ull_alientek_emmc.h 中的默认环境变量。
如果 EMMC 中的环境变量 panel 不等于 TFT7016,那么 LCD 显示不正常,需要在uboot 中修改 panel 的值为 TFT7016 ,在 uboot 的命令模式下输入如下命令:

setenv panel TFT7016
saveenv

修改环境变量 panel 为 TFT7016,保存,重启 uboot

1.4、网络驱动修改

正点原子I.MX6U-ALPHA开发板V2.4版本以前的底板使用的网络PHY为LAN8720,V2.4 及其以后的版本使用的网络 PHY 为 SR8201F,而且网络 PHY 地址有改变,需要看准自己所使用的底板版本号
忘记了自己板子的型号,目前先认定为V2.4以前的

1.4.1、网络简介

开发板内部有以太网 MAC 外设,也就是 ENET(Ethernet 以太网,),需要外接一个 PHY 芯片来实现网络通信功能,即内部 MAC+外部 PHY 芯片的方案。

注:在嵌入式系统或芯片的描述中,ENET指与以太网相关的功能模块或接口,通常,ENET包含了处理以太网通信的硬件模块,比如处理帧、CRC校验、帧同步等任务的模块,但它不涉及物理层的细节,例如具体的电信号传输和PHY层通信。PHY(物理层接口)则负责处理这些物理层的细节。
MAC(Media Access Control):内部的MAC部分负责管理帧的发送和接收,执行MAC层协议,如组帧、帧同步、CRC校验等。它通常是集成在处理器或芯片中的硬件模块。
MAC是计算机网络中的一个重要概念,它是OSI模型(开放系统互联模型)中数据链路层(第二层)的一个子层,负责管理数据链路的访问控制。
MAC层负责实现以下功能:
帧的创建和传输: 将数据封装成帧,并将帧发送到网络介质上。
帧的接收和解析: 接收并解析从网络介质上接收到的帧,将数据传递给更高层次的协议处理。
介质访问控制: 确定何时发送数据,如何识别冲突,并处理这些冲突,以避免多个设备同时访问网络介质而导致的碰撞。
在以太网中,MAC地址是用于唯一标识网络设备的硬件地址。MAC层的主要责任是控制对共享传输介质(例如以太网电缆)的访问,以确保不同设备之间的通信能够按照一定的规则进行,避免冲突和混乱。
MAC地址是一个48位的地址,通常以十六进制表示,是一个网络适配器的唯一标识符,全球唯一,不同的网络设备具有不同的MAC地址。
PHY(Physical Layer Interface):PHY部分通常是一个外部的芯片,用于处理物理层的信号转换,包括转换成电信号的模拟信号处理,以及与外部网络设备的通信。PHY负责处理物理层的细节,例如在以太网中进行信号编码、解码、调制和解调等
PHY是计算机网络中的一个术语,它是OSI模型中数据链路层的一部分,负责处理物理层的信号传输和接口功能。
PHY通常是指物理层接口芯片,它负责管理和处理物理层的细节,包括但不限于以下内容:
信号传输: 将数字信号转换成模拟信号以在网络媒介上传输,并将接收到的模拟信号转换成数字信号。
信号编解码: 对数字信号进行编码和解码,以确保在传输过程中的正确性和稳定性。
物理层规范和标准支持: 实现和支持与物理层相关的协议、标准和规范,如以太网、Wi-Fi、蓝牙等。
电气特性管理: 处理电气特性,如信号幅度、时序、电压等,以确保数据在物理层传输时的可靠性和稳定性。
在以太网通信中,PHY是连接MAC层和物理介质(例如电缆、光纤等)之间的接口,它确保了MAC层与实际物理介质之间的互联,并负责在不同的物理介质之间进行信号的转换和交互。
不同的网络标准可能会有不同类型的PHY芯片,以支持不同的物理层介质和通信协议。PHY提供了一个标准接口,使得网络设备可以与不同类型的物理介质进行通信。

DM9000 是个网络芯片,在一些没有内部 MAC 的 CPU 中,会采用 DM9000 来实现联网功能,如三星的 2440,4412 等,DM9000 提供了一个类似 SRAM 的访问接口,主控 CPU 通过这个接口即可与DM9000 进行通信,DM9000 就是一个 MAC+PHY 芯片,内部 MAC+PHY 芯片比DM9000 方案比优势,通信效率和速度,一般 SOC 内部的 MAC 是带有专用 DMA ,专门用于处理网络数据包,采用 SRAM 来读写 DM9000 的速度是压根就没法和内部 MAC+外部 PHY 芯片的速度比。
从这里也可以看出,三星的 2440、4412 这些芯片设计之初就不是给工业产品用的,他们是给消费类电子使用的,比如手机、平板等,手机或平板要上网,可以通过 WIFI 或者 4G,没有见过哪个手机或者平板上网是要接网线的。
注:DMA 代表的是“Direct Memory Access”,即“直接内存访问”,它是计算机系统中用于高速数据传输的一种技术。
在传统的CPU访问内存数据的过程中,通常是通过程序控制和CPU参与的方式完成的,这种方式可能会占用较多的CPU时间和系统总线带宽。
DMA 技术通过在不需要 CPU 参与的情况下,允许外设直接和系统内存进行数据传输。它的基本原理是,在设备和内存之间建立一个专门的 DMA 控制器,这个控制器能够独立地管理数据的传输,而无需 CPU 不断地介入。
DMA 的主要优势包括:
提高数据传输效率: DMA 可以在数据传输过程中减少 CPU 的介入,因此可以更快地将数据从外设传输到内存,或者在内存之间进行高速数据传输。
释放 CPU 资源: CPU 不需要持续地管理数据传输过程,它可以在数据传输过程中处理其他任务,从而提高系统的并发性和效率。
DMA 通常用于需要大量数据传输的情况,比如磁盘操作、网络数据传输、音频/视频处理等。它在提高系统性能和效率方面起到了重要的作用。

I.MX6UL/ULL 有两个网络接口 ENET1 和 ENET2,NXP 官方的I.MX6ULL EVK 开发板使用 KSZ8081 这颗 PHY 芯片,正点原子其中 ENET1 和 ENET2 都使用 LAN8720A 作为 PHY 芯片,换了PHY 芯片以后网络驱动怎么办?更换 PHY 芯片以后如何调整网络驱动?如下

1.4.2、更换 PHY 芯片调整网络驱动

在这里插入图片描述
注:SoC 代表的是“System on a Chip”,即“芯片上系统”。它是一种集成了多个硬件组件和功能模块的单一集成电路芯片,一个 SoC 通常包含了处理器核心(比如CPU、GPU等)、内存控制器、外设控制器(比如UART、SPI、I2C等)、通信接口(如以太网、Wi-Fi、蓝牙)、各种传感器接口、时钟控制器等等。这些功能模块被整合在同一个芯片上,以实现更高的集成度和性能
我们要修改 ENET1 网络驱动的话重点就三点:
①、ENET1 复位引脚初始化。
②、LAN8720A 的器件 ID。
③、LAN8720 驱动
关于 ENET2 网络驱动的修改也注意一下三点:
①、ENET2 的复位引脚,从图 33.2.7.2 可以看出,ENET2 的复位引脚 ENET2_RST 接到了
I.MX6ULL 的 SNVS_TAMPER8 上。
②、ENET2 所使用的 PHY 芯片器件地址,从图 33.2.7.2 可以看出,PHY 器件地址为 0X1。
③、LAN8720 驱动,ENET1 和 ENET2 都使用的 LAN8720,所以驱动肯定是一样的。

1.4.2.1、修改网络 PHY 地址

修改 uboot 中的 ENET1 和 ENET2 的 PHY 地址和驱动,打开 mx6ull_alientek_emmc.h文件

325 #ifdef CONFIG_CMD_NET
326 #define CONFIG_CMD_PING
327 #define CONFIG_CMD_DHCP
328 #define CONFIG_CMD_MII
329 #define CONFIG_FEC_MXC
330 #define CONFIG_MII
331 #define CONFIG_FEC_ENET_DEV 1
332
333 #if (CONFIG_FEC_ENET_DEV == 0)
334 #define IMX_FEC_BASE ENET_BASE_ADDR
335 #define CONFIG_FEC_MXC_PHYADDR 0x2
336 #define CONFIG_FEC_XCV_TYPE RMII
337 #elif (CONFIG_FEC_ENET_DEV == 1)
338 #define IMX_FEC_BASE ENET2_BASE_ADDR
339 #define CONFIG_FEC_MXC_PHYADDR 0x1
340 #define CONFIG_FEC_XCV_TYPE RMII
341 #endif
342 #define CONFIG_ETHPRIME "FEC"
343
344 #define CONFIG_PHYLIB
345 #define CONFIG_PHY_MICREL
346 #endif

第 331 行的宏 CONFIG_FEC_ENET_DEV 用于选择使用哪个网口,默认为 1,也就是选择ENET2,第 335 行为 ENET1 的 PHY 地址,默认是 0X2,第 339 行为 ENET2 的 PHY 地址,默认为 0x1。
正点原子的 I.MX6U-ALPHA 开发板 ENET1 的 PHY 地址为0X0,ENET2 的 PHY 地址为 0X1,所以需要将第 335 行的宏 CONFIG_FEC_MXC_PHYADDR改为 0x0
第 345 行定了一个宏 CONFIG_PHY_MICREL,用于使能 uboot 中 Micrel 公司的 PHY驱动,将 CONFIG_PHY_MICREL 改为 CONFIG_PHY_SMSC,使能 uboot 中的 SMSC 公司中的 PHY 驱动,因为 LAN8720A 是 SMSC 公司生产的。
即三处要修改:
①、修改 ENET1 网络 PHY 的地址。
②、修改 ENET2 网络 PHY 的地址。
③、使能 SMSC 公司的 PHY 驱动。

325 #ifdef CONFIG_CMD_NET
326 #define CONFIG_CMD_PING
327 #define CONFIG_CMD_DHCP
328 #define CONFIG_CMD_MII
329 #define CONFIG_FEC_MXC
330 #define CONFIG_MII
331 #define CONFIG_FEC_ENET_DEV 1
332
333 #if (CONFIG_FEC_ENET_DEV == 0)
334 #define IMX_FEC_BASE ENET_BASE_ADDR
335 #define CONFIG_FEC_MXC_PHYADDR 0x0
336 #define CONFIG_FEC_XCV_TYPE RMII
337 #elif (CONFIG_FEC_ENET_DEV == 1)
338 #define IMX_FEC_BASE ENET2_BASE_ADDR
339 #define CONFIG_FEC_MXC_PHYADDR 0x1
340 #define CONFIG_FEC_XCV_TYPE RMII
341 #endif
342 #define CONFIG_ETHPRIME "FEC"
343
344 #define CONFIG_PHYLIB
345 #define CONFIG_PHY_SMSC
346 #endif

1.4.2.2、删除 uboot 中 74LV595 的驱动代码

修改网络复位引脚的驱动,打开mx6ull_alientek_emmc.c

#define IOX_SDI IMX_GPIO_NR(5, 10)
#define IOX_STCP IMX_GPIO_NR(5, 7)
#define IOX_SHCP IMX_GPIO_NR(5, 11)
#define IOX_OE IMX_GPIO_NR(5, 8)

替换为

#define ENET1_RESET IMX_GPIO_NR(5, 7)
#define ENET2_RESET IMX_GPIO_NR(5, 8)

再找

static iomux_v3_cfg_t const iox_pads[] = {
 /* IOX_SDI */
 MX6_PAD_BOOT_MODE0__GPIO5_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
 /* IOX_SHCP */
 MX6_PAD_BOOT_MODE1__GPIO5_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
 /* IOX_STCP */
 MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
 /* IOX_nOE */
 MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
};

将其删除掉,再找

static void iox74lv_init(void)
{
 int i;
 gpio_direction_output(IOX_OE, 0);
 for (i = 7; i >= 0; i--) {
 gpio_direction_output(IOX_SHCP, 0);
 gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
 udelay(500);
  gpio_direction_output(IOX_SHCP, 1);
 udelay(500);
 }
 ......
 /*
 * shift register will be output to pins
 */
 gpio_direction_output(IOX_STCP, 1);
};
void iox74lv_set(int index)
{
 int i;
 for (i = 7; i >= 0; i--) {
 gpio_direction_output(IOX_SHCP, 0);
 if (i == index)
 gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
 else
 gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
 udelay(500);
 gpio_direction_output(IOX_SHCP, 1);
 udelay(500);
 }
 ......
 /*
 * shift register will be output to pins
 */
 gpio_direction_output(IOX_STCP, 1);
};

将这两个函数全部删除掉。在 mx6ull_alientek_emmc.c 中找到 board_init 函数(板子初始化函数)

int board_init(void)
{
......
imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
iox74lv_init();
 ......
 return 0;
}

将这两行删除掉

1.4.2.3、添加 I.MX6U-ALPHA 开发板网络复位引脚驱动

在 mx6ull_alientek_emmc.c 中找

640 static iomux_v3_cfg_t const fec1_pads[] = {
641 MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
642 MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
......
649 MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
650 MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
651 };
652
653 static iomux_v3_cfg_t const fec2_pads[] = {
654 MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
655 MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
......
664 MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
665 MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
666 };

添加两个网口的复位 IO 配置参数,即添加第 651 行和 667 行分别是 ENET1 和 ENET2 的复位 IO 配置参数

640 static iomux_v3_cfg_t const fec1_pads[] = {
641 MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
642 MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
......
649 MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
650 MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
651 MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
652 };
653
654 static iomux_v3_cfg_t const fec2_pads[] = {
655 MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
656 MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
......
665 MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
666 MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
667 MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
668 };

文件 mx6ull_alientek_emmc.c 中找

668 static void setup_iomux_fec(int fec_id)
669 {
670 if (fec_id == 0)
671 imx_iomux_v3_setup_multiple_pads(fec1_pads,
672 ARRAY_SIZE(fec1_pads));
673 else
674 imx_iomux_v3_setup_multiple_pads(fec2_pads,
675 ARRAY_SIZE(fec2_pads));
676 }

修改为如下

668 static void setup_iomux_fec(int fec_id)
669 {
670 if (fec_id == 0)
671 {
672
673 imx_iomux_v3_setup_multiple_pads(fec1_pads,
674 ARRAY_SIZE(fec1_pads));
675
676 gpio_direction_output(ENET1_RESET, 1);
677 gpio_set_value(ENET1_RESET, 0);
678 mdelay(20);
679 gpio_set_value(ENET1_RESET, 1);
680 }
681 else
682 {
683 imx_iomux_v3_setup_multiple_pads(fec2_pads,
684 ARRAY_SIZE(fec2_pads));
685 gpio_direction_output(ENET2_RESET, 1);
686 gpio_set_value(ENET2_RESET, 0);
687 mdelay(20);
688 gpio_set_value(ENET2_RESET, 1);
689 }
690 }

##1.4.2.4、 修改 drivers/net/phy/phy.c 文件中的函数 genphy_update_link

最后一步,打开文件drivers/net/phy/phy.c,找到函数 genphy_update_link,这是个通用 PHY 驱动函数,添加一些代码,225 行~237 行就是新添加的代码。

221 int genphy_update_link(struct phy_device *phydev)
222 {
223 unsigned int mii_reg;
224
225 #ifdef CONFIG_PHY_SMSC
226 static int lan8720_flag = 0;
227 int bmcr_reg = 0;
228 if (lan8720_flag == 0) {
229 bmcr_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 
230 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 
231 while(phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR) & 0X8000) {
232 udelay(100); 
233 }
234 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr_reg); 
235 lan8720_flag = 1;
236 }
237 #endif
238

至此网络的复位引脚驱动修改完成,重新编译 uboot,然后将 u-boot.bin 烧写到 SD 卡中并启动。
如图成功
在这里插入图片描述
“Net: FEC1”这一行,提示当前使用的 FEC1 这个网口,也就
是 ENET2,uboot 中使用网络之前要先设置几个环境变量

setenv ipaddr 192.168.1.55 //开发板 IP 地址
setenv ethaddr b8:ae:1d:01:00:00 //开发板网卡 MAC 地址
setenv gatewayip 192.168.1.1 //开发板默认网关
setenv netmask 255.255.255.0 //开发板子网掩码
setenv serverip 192.168.1.250 //服务器地址,也就是 Ubuntu 地址
saveenv           //保存环境变量

设置好环境变量以后就可以在 uboot 中使用网络,用网线将 I.MX6U-ALPHA 上的 ENET2与电脑或者路由器连接起来,保证开发板和电脑在同一个网段内,通过 ping 命令来测试一下网络连接

ping 192.168.1.250

在这里插入图片描述
有“host 192.168.1.250 is alive”这句,说明 ping 主机成功,ENET2网络工作正常。
再来测试一下 ENET1 的网络是否正常工作
打开 mx6ull_alientek_emmc.h,将 CONFIG_FEC_ENET_DEV 改为 0,然后重新编译一下 uboot 并烧写到 SD 卡中重启
在这里插入图片描述
Net:FEC0”这一行,说明当前使用的 FEC0 这个网卡,也就是ENET1,建议将 ENET2 设置为 uboot 的默认网卡!也就是将宏 CONFIG_FEC_ENET_DEV 设置为 1。

1.5、其他需要修改的地方

在 uboot 启动信息中会有“Board: MX6ULL 14x14 EVK”这一句,也就是说板子名字为
“MX6ULL 14x14 EVK”,要将其改为我们所使用的板子名字,打开文件 mx6ull_alientek_emmc.c
修改后

int checkboard(void)
{
 if (is_mx6ull_9x9_evk())
 puts("Board: MX6ULL 9x9 EVK\n");
 else
 puts("Board: MX6ULL ALIENTEK EMMC\n");
 return 0;
}

至此 uboot 的驱动部分就修改完成,uboot 移植也完成,uboot 的最终目的就是启动 Linux 内核,所以需要通过启动 Linux 内核来判断 uboot 移植是否成功启动 Linux 内核之前,学习两个重要的环境变量 bootcmd 和 bootargs

1.6、学习bootcmd 和 bootargs 环境变量

1.6.1环境变量 bootcmd

bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令,一般用来启动 Linux 内核,如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。
可在uboot 启动以后进入命令行设置 bootcmd 环境变量的值,如果 EMMC 或者 NAND 中没有保存 bootcmd 的值,那么 uboot 就会使用默认的值设置 bootcmd 环境变量

1.6.2、环境变量 bootargs

bootargs 保存着 uboot 传递给 Linux 内核的参数

2、uboot 启动 Linux 测试

一种是直接从 EMMC 启动,一种是从网络启动。

2.1、从 EMMC 启动 Linux 系统

将编译出来的 Linux 镜像文件 zImage 和设备树文件保存在 EMMC中,uboot 从 EMMC 中读取这两个文件并启动,这个是产品最终的启动方式。
拿到手的 I.MX6U-ALPHA 开发板(EMMC 版本)已经将 zImage 文件和设备树文件
烧写到了 EMMC 中,可以直接读取来测试,先检查一下 EMMC 的分区 1 中有没有
zImage 文件和设备树文件
在这里插入图片描述
设置 bootargs 和 bootcmd这两个环境变量

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 
imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;'
saveenv

设置好以后直接输入 boot,或者 run bootcmd 即可启动 Linux 内核,在这里插入图片描述

2.2、从网络启动 Linux 系统

从网络启动 linux 系统的唯一目的就是为了调试,设置 linux 从网络启动,也就是将 linux 镜像文件和根文件系统都放到 Ubuntu 下某个指定的文件夹中,可以通过 nfs 或者 tftp 从 Ubuntu 中下载 zImage 和设备树文件,这里使用 tftp 从 Ubuntu 中下载 zImage 和设备树文件,前提是要将 zImage 和设备树文件放到 Ubuntu 下的 tftp 目录中,设置 bootargs 和 bootcmd 这两个环境变量

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 
80800000 - 83000000'
saveenv

开始通过tftp下载zImage和imx6ull-alientek-emmc.dtb这两个文件
在这里插入图片描述
下载完成以后启动 Linux 内核
在这里插入图片描述

uboot 移植到此结束

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是不想再当小白的黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值