uboot移植到IMX6ULL平台详细过程(下)

简介: uboot移植到IMX6ULL平台详细过程(下)

3 添加开发板对应的板级文件夹

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

cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc

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

cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc.c

我们还需要对 mx6ull_alientek_emmc 目录下的文件做一些修改:

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

将 mx6ull_alientek_emmc 下的 Makefile 文件内容改为如下所示:

vi Makefile

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 $< $@

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

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

将 imximage.cfg 中的下面一句:

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

改为:

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

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

修改 Kconfig 文件,修改后的内容如下:

if TARGET_MX6ULL_ALIENTEK_EMMC
config SYS_BOARD
default "mx6ull_alientek_emmc"
config SYS_VENDOR
default "freescale"
config SYS_SOC
`   default "mx6"
config SYS_CONFIG_NAME
default "mx6ull_alientek_emmc"
endif

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

修改 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/alientek_mx6ull_emmc.h

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

uboot 是支持图形界面配置,关于 uboot 的图形界面配置下一章会详细的讲解。修改文件arch/arm/cpu/armv7/mx6/Kconfig(如果用的 I.MX6UL 的话,应该修改 arch/arm/Kconfig 这个文件),在 207 行加入如下内容:

vim arch/arm/cpu/armv7/mx6/Kconfig
config TARGET_MX6ULL_ALIENTEK_EMMC
 bool "Support mx6ull_alientek_emmc"
  select MX6ULL
   select DM
select DM_THERMAL

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

source "board/freescale/mx6ull_alientek_emmc/Kconfig"

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

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

在 uboot 根目录下新建一个名为 nxp_uboot_make.sh 的 shell 脚本,在这个 shell 脚本里面输入如下内容:

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

第 3 行我们使用的默认配置文件就是前面新建的 mx6ull_alientek_emmc_defconfig 这个配置文件。给予 mx6ll_alientek_emmc.sh 可执行权限,然后运行脚本来完成编译,命令如下:

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

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

grep -nR "mx6ull_alientek_emmc.h"

如果有很多文件都引用了mx6ull_alientek_emmc.h 这个头文件,那就说明新板子添加成功

编译完成以后就使用 imxdownload 将新编译出来的 u-boot.bin 烧写到 SD 卡中测试,SecureCRT 输出结果如图 所示:

此时的 Board 还是“MX6ULL 14x14 EVK”,因为我们参考的 NXP官方的 I.MX6ULL 开发板来添加自己的开发板。如果接了 LCD 屏幕的话会发现 LCD 屏幕并没有显示 NXP 的 logo(或显示重叠的logo),而且从图 可以看出此时的网络同样也没识别出来。前面已经说了,默认 uboot 中的 LCD 驱动和网络驱动在正点原子的 I.MX6U-ALPHA 开发板上是有问题的,需要修改。

6 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 的 IO 和背光 IO 都一样的,所以 IO 部分就不用修改了。需要修改的之后 LCD 参数,打开文件 mx6ull_alientek_emmc.c,找到如下所示内容:

board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c

780 struct display_info_t const displays[] = {{
 781     .bus = MX6UL_LCDIF1_BASE_ADDR,
 782     .addr = 0,
 783     .pixfmt = 24,
 784     .detect = NULL,
 785     .enable = do_enable_parallel_lcd,
 786     .mode   = {
 787         .name           = "TFT43AB",
 788         .xres           = 480,
 789         .yres           = 272,
 790         .pixclock       = 108695,
 791         .left_margin    = 8,
 792         .right_margin   = 4,
 793         .upper_margin   = 2,
 794         .lower_margin   = 4,
 795         .hsync_len      = 41,
 796         .vsync_len      = 10,
 797         .sync           = 0,
 798         .vmode          = FB_VMODE_NONINTERLAC

ED

799 } } };

定义了一个变量 displays,类型为 display_info_t,这个结构体是 LCD信息结构体,其中包括了 LCD 的分辨率,像素格式, LCD 的各个参数等。 display_info_t 定义在文件 arch/arm/include/asm/imx-common/video.h 中,定义如下:

struct display_info_t {
 int bus;
  int addr;
  int pixfmt;
  int (*detect)(struct display_info_t const *dev);
  void (*enable)(struct display_info_t const *dev);
  struct fb_videomode mode;
};

ixfmt 是像素格式,也就是一个像素点是多少位,如果是 RGB565 的话就是 16 位,如果是 888 的话就是 24 位,一般使用 RGB888。结构体 display_info_t 还有个 mode 成员变量,此成员变量也是个结构体,为 fb_videomode,定义在文件 include/linux/fb.h 中,定义如下:

struct fb_videomode {
   const char *name; /* optional */
   u32 refresh; /* optional */
   u32 xres;5 u32 yres;
   u32 pixclock;
   u32 left_margin;
   u32 right_margin;
   u32 upper_margin;
   u32 lower_margin;
   u32 hsync_len;
   u32 vsync_len;
   u32 sync;
   u32 vmode;
   u32 flag;
};

结构体 fb_videomode 里面的成员变量为LCD 的参数,这些成员变量函数如下:

name:LCD 名字,要和环境变量中的 panel 相等。

xres、yres:LCD X 轴和 Y 轴像素数量。

pixclock:像素时钟,每个像素时钟周期的长度,单位为皮秒。

left_margin:HBP,水平同步后肩。

right_margin:HFP,水平同步前肩。

upper_margin:VBP,垂直同步后肩。

lower_margin:VFP,垂直同步前肩。

hsync_len:HSPW,行同步脉宽。

vsync_len:VSPW,垂直同步脉宽。

vmode:大多数使用FB_VMODE_NONINTERLACED,也就是不使用隔行扫描。

可以看出,这些参数和我们第二十四章讲解RGB LCD 的时候参数基本一样,唯一不同的像素时钟 pixclock 的含义不同,

pixclock 像素时钟需要根据自己的LCD屏幕时间参数进行计算,计算公式如下:

pxclk = {[(VSPW+VBP+LINE+VFP) * (HSPW+HBP+HOZVAL+HFP)] * 60} **** (1)

以上参数都在LCD数据手册能找到。

pixclock = (1 / pxclk) * 10^12 (2)

由1,2式即可计算出pixclock的值32285。

780 struct display_info_t const displays[] = {{
781     .bus = MX6UL_LCDIF1_BASE_ADDR,
782     .addr = 0,
783     .pixfmt = 24,
784     .detect = NULL,
785     .enable = do_enable_parallel_lcd,
786     .mode   = {
787         .name           = "ATK4384",
788         .xres           = 800,
789         .yres           = 480,
790         .pixclock       = 32285,
791         .left_margin    = 88,
792         .right_margin   = 40,
793         .upper_margin   = 32,
794         .lower_margin   = 13,
795         .hsync_len      = 48,
796         .vsync_len      = 3,
797         .sync           = 0,
798         .vmode          = FB_VMODE_NONINTERLACED
799 } } };

打开 mx6ull_alientek_emmc.h,找到所有如下语句:

include/configs/mx6ull_alientek_emmc.h

panel=TFT43AB

将其改为

panel=ATK4384

也就是设置 panel 为 ATK4384, panel 的值要与示例代码中的.name 成员变量的值一致。修改完成以后重新编译一遍 uboot 并烧写到 SD 中启动。

重启以后 LCD 驱动一般就会工作正常了, LCD 上回显示 NXP 的 logo。但是有可能会遇到LCD 并没有工作,还是黑屏,这是什么原因呢?在 uboot 命令模式输入“print”来查看环境变量 panel 的值,会发现 panel 的值要是 TFT43AB(或其他的,反正不是 ATK4384),如图 33.2.6.1所示:

print

这是因为之前有将环境变量保存到 EMMC 中, uboot 启动以后会先从 EMMC 中读取环境变量,如果 EMMC 中没有环境变量的话才会使用 mx6ull_alientek_emmc.h 中的默认环境变量。如果 EMMC 中的环境变量 panel 不等于 ATK4384,那么 LCD 显示肯定不正常,我们只需要在uboot 中修改 panel 的值为 ATK4384 即可,在 uboot 的命令模式下输入如下命令:

setenv panel ATK4384
saveenv

上述命令修改环境变量 panel 为 ATK4384,然后保存,重启 uboot,此时 LCD 驱动就工作正常了。如果 LCD 还是没有正常工作的,那就要检查自己哪里有没有改错,或者还有哪里没有修改。

7.网络驱动修改

1、 I.MX6U-ALPHA 开发板网络简介

I.MX6UL/ULL 内部有个以太网 MAC 外设,也就是 ENET,需要外接一个 PHY 芯片来实现网络通信功能,也就是内部 MAC+外部 PHY 芯片的方案。大家可能听过 DM9000 这个网络芯片,在一些没有内部 MAC 的 CPU 中,比如三星的 2440, 4412 等,就会采用 DM9000 来实现联网功能。 DM9000 提供了一个类似 SRAM 的访问接口,主控 CPU 通过这个接口即可与DM9000 进行通信, DM9000 就是一个 MAC+PHY 芯片。这个方案就相当于外部 MAC+外部PHY,那么 I.MX6U 这样的内部 MAC+PHY 芯片与 DM9000 方案比有什么优势吗?那优势大了去了!首先就是通信效率和速度,一般 SOC 内部的 MAC 是带有一个专用 DMA 的,专门用于处理网络数据包,采用 SRAM 来读写 DM9000 的速度是压根就没法和内部 MAC+外部 PHY 芯片的速度比。采用外部 DM9000 完全是无奈之举,谁让 2440, 4412 这些芯片内部没有以太网外设呢,现在又想用有线网络,没有办法只能找个 DM9000 的方案。从这里也可以看出,三星的 2440、 4412 这些芯片设计之初就不是给工业产品用的,他们是给消费类电子使用的,比如手机、平板等,手机或平板要上网,可以通过 WIFI 或者 4G,我是没有见过哪个手机或者平板上网是要接根网线的。正点原子的 I.MX6U-ALPHA 开发板也可以通过 WIFI 或者 4G 上网,这个是后话了。

I.MX6UL/ULL 有两个网络接口 ENET1 和 ENET2,正点原子的 I.MX6U-ALPHA 开发板提供了这两个网络接口,其中 ENET1 和 ENET2 都使用 LAN8720A 作为 PHY 芯片。 NXP 官方的I.MX6ULL EVK 开发板使用 KSZ8081 这颗 PHY 芯片, LAN8720A 相比 KSZ8081 具有体积小、外围器件少、价格便宜等优点。直接使用 KSZ8081 固然可以,但是我们在实际的产品中不一定会使用 KSZ8081,有时候为了降低成本会选择其他的 PHY 芯片,这个时候就有个问题:换了PHY 芯片以后网络驱动怎么办?为此,正点原子的 I.MX6U-ALPHA 开发板将 ENET1 和 ENET2的 PHY 换成了 LAN8720A,这样就可以给大家讲解更换 PHY 芯片以后如何调整网络驱动,使网络工作正常。

I.MX6U-ALPHA 开发板 ENET1 的网络原理图如图

所示:

ENET1 的网络 PHY 芯片为 LAN8720A,通过 RMII 接口与 I.MX6ULL 相连,正点原子I.MX6U-ALPHA 开发板的 ENET1 引脚与 NXP 官方的 I.MX6ULL EVK 开发板基本一样,唯独复位引脚不同。从图 33.2.7.1 可以看出,正点原子 I.MX6U-ALPHA 开发板的 ENET1 复位引脚ENET1_RST 接到了 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。

LAN8720A 内部是有寄存器的,I.MX6ULL 会读取 LAN8720 内部寄存器来判断当前的物理链接状态、连接速度(10M 还是 100M)和双工状态(半双工还是全双工)。I.MX6ULL 通过 MDIO接口来读取 PHY 芯片的内部寄存器,MDIO 接口有两个引脚,ENET_MDC 和 ENET_MDIO,ENET_MDC 提供时钟,ENET_MDIO 进行数据传输。一个 MDIO 接口可以管理 32 个 PHY 芯片,同一个 MDIO 接口下的这些 PHY 使用不同的器件地址来做区分,MIDO 接口通过不同的器件地址即可访问到相应的 PHY 芯片。I.MX6U-ALPHA 开发板 ENET1 上连接的 LAN8720A器件地址为 0X0,所示我们要修改ENET1 网络驱动的话重点就三点:

①、ENET1 复位引脚初始化。

②、LAN8720A 的器件 ID。

③、LAN8720 驱动

再来看一下 ENET2 的原理图,如图 所示:

关于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,所以驱动肯定是一样的。

2、网络 PHY 地址修改

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

这个文件,找到如下代码:

vi include/configs/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     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

第 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驱动,KSZ8081 这颗 PHY 芯片就是 Micrel 公司生产的,不过 Micrel 已经被 Microchip 收购了。如果要使用 LAN8720A,那么就得将 CONFIG_PHY_MICREL 改为 CONFIG_PHY_SMSC,也就是使能 uboot 中的 SMSC 公司中的 PHY 驱动,因为 LAN8720A 就是 SMSC 公司生产的。所以示例代码有三处要修改:

①、修改ENET1 网络 PHY 的地址。

②、修改ENET2 网络 PHY 的地址。

③、使能 SMSC 公司的PHY 驱动。

修改后的网络 PHY 地址参数如下所示:

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

建议大家将 ENET2 设置为 uboot 的默认网卡!也就是将宏 CONFIG_FEC_ENET_DEV 设置为 1。

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

uboot 中网络 PHY 芯片地址修改完成以后就是网络复位引脚的驱动修改了,打开mx6ull_alientek_emmc.c,找到如下代码:

vi board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c
91 #define IOX_SDI IMX_GPIO_NR(5, 10)
  92 #define IOX_STCP IMX_GPIO_NR(5, 7)
  93 #define IOX_SHCP IMX_GPIO_NR(5, 11)
  94 #define IOX_OE IMX_GPIO_NR(5, 8)

示例代码 中以 IOX 开头的宏定义是 74LV595 的相关 GPIO,因为 NXP 官方I.MX6ULL EVK 开发板使用 74LV595 来扩展 IO,两个网络的复位引脚就是由 74LV595 来控制的。正点原子的 I.MX6U-ALPHA 开发板并没有使用 74LV595,因此我们将示例代码 中的代码删除掉,替换为如下所示代码:

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

ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07, ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08。

继续在 mx6ull_alientek_emmc.c 中找到如下代码:

94 static iomux_v3_cfg_t const iox_pads[] = {
  95     /* IOX_SDI */
  96     MX6_PAD_BOOT_MODE0__GPIO5_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
  97     /* IOX_SHCP */
  98     MX6_PAD_BOOT_MODE1__GPIO5_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
  99     /* IOX_STCP */
 100     MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
 101     /* IOX_nOE */
 102     MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
 103 };

同理,示例代码是 74LV595 的 IO 配置参数结构体,将其删除掉。继续在mx6ull_alientek_emmc.c 中找到函数 iox74lv_init,如下所示:

153 static void iox74lv_init(void)
 154 {
 155     int i;
 156 
 157     gpio_direction_output(IOX_OE, 0);
 158 
 159     for (i = 7; i >= 0; i--) {
 160         gpio_direction_output(IOX_SHCP, 0);
 161         gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
 162         udelay(500);
 163         gpio_direction_output(IOX_SHCP, 1);
 164         udelay(500);
 165     }
 166 
 167     gpio_direction_output(IOX_STCP, 0);
 168     udelay(500);
 169     /*
 170      * shift register will be output to pins
 171      */
 172     gpio_direction_output(IOX_STCP, 1);
 173 
 174     for (i = 7; i >= 0; i--) {
 175         gpio_direction_output(IOX_SHCP, 0);
 176         gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
 177         udelay(500);
 178         gpio_direction_output(IOX_SHCP, 1);
 179         udelay(500);
 180     }
 181     gpio_direction_output(IOX_STCP, 0);
 182     udelay(500);
 183     /*
 184      * shift register will be output to pins
 185      */
 186     gpio_direction_output(IOX_STCP, 1);
 187 };
189 void iox74lv_set(int index)
 190 {
 191     int i;
 192 
 193     for (i = 7; i >= 0; i--) {
 194         gpio_direction_output(IOX_SHCP, 0);
 195 
 196         if (i == index)
 197             gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);
 198         else
 199             gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
 200         udelay(500);
 201         gpio_direction_output(IOX_SHCP, 1);
 202         udelay(500);
 203     }
 204 
 205     gpio_direction_output(IOX_STCP, 0);
 206     udelay(500);
 207     /*
 208       * shift register will be output to pins
 209       */
 210     gpio_direction_output(IOX_STCP, 1);
 211 
 212     for (i = 7; i >= 0; i--) {
 213         gpio_direction_output(IOX_SHCP, 0);
 214         gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
 215         udelay(500);
 216         gpio_direction_output(IOX_SHCP, 1);
 217         udelay(500);
 218     }
 219 
 220     gpio_direction_output(IOX_STCP, 0);
 221     udelay(500);
 222     /*
 223       * shift register will be output to pins
 224       */
 225     gpio_direction_output(IOX_STCP, 1);
 226 };

iox74lv_init 函数是 74LV595 的初始化函数, iox74lv_set 函数用于控制 74LV595 的 IO 输出电平,将这两个函数全部删除掉!

在 mx6ull_alientek_emmc.c 中找到 board_init 函数,此函数是板子初始化函数,会被board_init_r 调用, board_init 函数内容如下:

815 int board_init(void)
 816 {   
 817     /* Address of boot parameters */
 818     gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 819     
 820     imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
 821     
 822     iox74lv_init();
 823 
 824 #ifdef CONFIG_SYS_I2C_MXC
 825     setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
 826 #endif
 827 
 828 #ifdef  CONFIG_FEC_MXC
 829     setup_fec(CONFIG_FEC_ENET_DEV);
 830 #endif
 831 
 832 #ifdef CONFIG_USB_EHCI_MX6
 833     setup_usb();
 834 #endif
 835 
 836 #ifdef CONFIG_FSL_QSPI
 837     board_qspi_init();
 838 #endif
 839 
 840 #ifdef CONFIG_NAND_MXS
 841     setup_gpmi_nand();
 842 #endif
 843     
 844     return 0;
 845 }

board_init 会调用 imx_iomux_v3_setup_multiple_pads 和 iox74lv_init 这两个函数来初始化74lv595 的 GPIO,将这两行删除掉。至此, mx6ull_alientek_emmc.c 中关于 74LV595 芯片的驱动代码都删除掉了,接下来就是添加 I.MX6U-ALPHA 开发板两个网络复位引脚了。

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

在 mx6ull_alientek_emmc.c 中找到如下所示代码:

645 static iomux_v3_cfg_t const fec1_pads[] = {
 646     MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
 647     MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
 648     MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 649     MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 650     MX6_PAD_ENET1_TX_EN__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 651     MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
 652     MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 653     MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 654     MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
 655     MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 656 };
 657 
 658 static iomux_v3_cfg_t const fec2_pads[] = {
 659     MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
 660     MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
 661 
 662     MX6_PAD_ENET2_TX_DATA0__ENET2_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 663     MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 664     MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
 665     MX6_PAD_ENET2_TX_EN__ENET2_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 666 
 667     MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 668     MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 669     MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 670     MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
 671 };
结构体数组 fec1_pads 和 fec2_pads 是 ENET1 和 ENET2 这两个网口的 IO 配置参数,在这两个数组中添加两个网口的复位 IO 配置参数,完成以后如下所示:
 645 static iomux_v3_cfg_t const fec1_pads[] = {
 646     MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
 647     MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
 648     MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 649     MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 650     MX6_PAD_ENET1_TX_EN__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 651     MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
 652     MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 653     MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 654     MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
 655     MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 656     MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
 657 };
 658 
 659 static iomux_v3_cfg_t const fec2_pads[] = {
 660     MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
 661     MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
 662     
 663     MX6_PAD_ENET2_TX_DATA0__ENET2_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 664     MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 665     MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
 666     MX6_PAD_ENET2_TX_EN__ENET2_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 667     
 668     MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 669     MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 670     MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 671     MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
 672     MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
 673 };

示例代码中,第 651 行和 667 行分别是 ENET1 和 ENET2 的复位 IO 配置参数。继续在文件 mx6ull_alientek_emmc.c 中找到函数 setup_iomux_fec,此函数默认代码如下:

675 static void setup_iomux_fec(int fec_id)
 676 {
 677     if (fec_id == 0)
 678         imx_iomux_v3_setup_multiple_pads(fec1_pads,
 679                          ARRAY_SIZE(fec1_pads));
 680     else
 681         imx_iomux_v3_setup_multiple_pads(fec2_pads,
 682                          ARRAY_SIZE(fec2_pads));
 683 }

函数 setup_iomux_fec 就是根据 fec1_pads 和 fec2_pads 这两个网络 IO 配置数组来初始化I.MX6ULL 的网络 IO。我们需要在其中添加网络复位 IO 的初始化代码,并且复位一下 PHY 芯片,修改后的 setup_iomux_fec 函数如下:

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

示例代码中第 676 行~679 行和第 685 行~688 行分别对应 ENET1 和 ENET2 的复位 IO 初始化,将这两个 IO 设置为输出并且硬件复位一下 LAN8720A,这个硬件复位很重要!否则可能导致 uboot 无法识别 LAN8720A。


教程中5.不需要!!!!!!!!!!!!!!

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


8 其他需要修改的地方

在 uboot 启动信息中会有“Board: MX6ULL 14x14 EVK”这一句,也就是说板子名字为“ MX6ULL 14x14 EVK”,要将其改为我们所使用的板子名字,比如“ MX6ULL ALIENTEKEMMC”或者“MX6ULL ALIENTEK NAND”。打开文件 mx6ull_alientek_emmc.c,找到函数checkboard,将其改为如下所示内容:

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

修改完成以后重新编译 uboot 并烧写到 SD 卡中验证

结果

至此网络的复位引脚驱动修改完成,重新编译 uboot,然后将 u-boot.bin 烧写到 SD 卡中并启动, uboot 启动信息如图 所示:

5.启动内核

设置开发板为sd卡启动,上电启动uboot,进入uboot命令模式

配置uboot网络信息

setenv ipaddr 192.168.10.101
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.10.1
setenv netmask 255.255.255.0
setenv serverip 192.168.10.100
saveenv

配置后使用开发板ping serverip,ping通即配置成功

配置环境变量和根文件系统目录

setenv bootargs 'console=tty1 console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.10.100:/home/alientek/linux/nfs/rootfs,proto=tcp rw ip=192.168.10.101:192.168.10.100:192.168.10.1:255.255.255.0::eth0:off'
saveenv

格式参考:

setenv bootargs ‘console=开发板串口,波特率 root=挂载方式 \nfsroot=虚拟机 IP 地址:文件系统路径,proto=传输协议 读写权限 \ip=开发板 IP 地址:虚拟机 IP 地址:网关地址:子网掩码::开发板网口:off’

注意:

文件系统路径不要错

IP地址等信息不要错

设置环境变量 bootcmd 来挂载 tftp 目录下的内核、设备树文件到开发板内存中。

setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
saveenv

重启开发板即可启动内核:

目录
相关文章
|
9月前
|
Linux 开发工具
瑞芯微RV1109配置GPIO设备树修改笔记(熟悉新平台从点灯大法开始)
瑞芯微RV1109配置GPIO设备树修改笔记(熟悉新平台从点灯大法开始)
188 0
|
9月前
|
供应链 Linux 开发工具
Buildroot系统构建学习笔记(以百问网imx6ull开发板为例)
Buildroot系统构建学习笔记(以百问网imx6ull开发板为例)
167 0
|
11月前
|
存储 编解码 Ubuntu
uboot移植到IMX6ULL平台详细过程(上)
uboot移植到IMX6ULL平台详细过程(上)
292 0
|
芯片
最简单的LED驱动程序编写流程--基于IMX6ULL
最简单的LED驱动程序编写流程--基于IMX6ULL
163 0
|
Windows
nxp官方uboot移植到野火开发板PRO(无任何代码逻辑的修改)
nxp官方uboot移植到野火开发板PRO(无任何代码逻辑的修改)
113 0
|
芯片
具体单板的按键驱动程序(查询方式)-以IMX6ull单板为例子
具体单板的按键驱动程序(查询方式)-以IMX6ull单板为例子
78 0
|
Linux 开发工具 git
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)具体单板的按键驱动程序(查询方式)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)具体单板的按键驱动程序(查询方式)
208 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)具体单板的按键驱动程序(查询方式)
|
Ubuntu 编译器 Linux
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(九)第一个程序背后的C语言知识
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(九)第一个程序背后的C语言知识
143 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(九)第一个程序背后的C语言知识
|
Linux 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十四)具体单板的GPIO操作方法
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十四)具体单板的GPIO操作方法
122 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十四)具体单板的GPIO操作方法
|
Linux 开发工具 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十四)查询方式的按键驱动程序_编写框架
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十四)查询方式的按键驱动程序_编写框架
153 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十四)查询方式的按键驱动程序_编写框架

热门文章

最新文章