nxp出厂uboot
https://download.csdn.net/download/weixin_52849254/87663485
移植成功后的uboot
https://download.csdn.net/download/weixin_52849254/87663490
tar -vxjf uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2
找到 NXP 官方 I.MX6ULL EVK 开发板对应的默认配置文件以后就可以编译一下,使用如下命令编译 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
编译完成以后结果如图
编译成功。我们在编译的时候需要输入 ARCH 和 CORSS_COMPILE这两个变量的值,这样太麻烦了。我们可以直接在顶层 Makefile 中直接给 ARCH 和CORSS_COMPILE 赋值,修改如图 所示:
249 ARCH = arm
250 CROSS_COMPILE = arm-linux-gnueabihf-
249、 250 行就是直接给 ARCH 和 CROSS_COMPILE 赋值,这样我们就可以使用如下简短的命令来编译 uboot 了
make mx6ull_14x14_evk_emmc_defconfig
make V=1 -j16
如果既不想修改 uboot 的顶层 Makefile,又想编译的时候不用输入那么多,那么就直接创建个 shell 脚本就行了, shell 脚本名为 nxp_uboot_make.sh,然后在 shell 脚本里面输入如下内容:
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
记得给 nxp_uboot_make.sh 这个文件可执行权限,使用 nxp_uboot_make.sh 脚本编译 uboot 的时候每次都会清理一下工程,然后全部重新编译,编译的时候直接执行这个脚本就行了,命令如下:
./nxp_uboot_make.sh
编译完成以后会生成 u-boot.bin、 u-boot.imx 等文件,但是这些文件是 NXP 官方 I.MX6ULLEVK 开发板。能不能用到正点原子的 I.MX6ULL 开发板上呢?试一下不就知道了!
将 imxdownload 软件拷贝到 uboot 源码根目录下,然后使用 imxdownload 软件将 u-boot.bin烧写到 SD 卡中,烧写命令如下:
chmod 777 imxdownload //给予 imxdownload 可执行权限
./imxdownload u-boot.bin /dev/sdc //烧写到 SD 卡中,不能烧写到/dev/sda 或 sda1 里面
烧写完成以后将 SD 卡插入 I.MX6U-ALPHA 开发板的 TF 卡槽中,最后设置开发板从 SD卡启动。打开 SecureCRT,设置好开发板所使用的串口并打开,复位开发板, SecureCRT 接收到如下图 所示信息:
uboot 启动正常,虽然我们用的是 NXP 官方 I.MX6ULL 开发板的uboot,但是在正点原子的 I.MX6ULL 开发板上是可以正常启动的。而且 DRAM 识别正确,为512MB,如果用的 NAND 版本的核心版的话 uboot 启动会失败!因为 NAND 核心版用的 256MB的 DRAM。
检查一下 SD 卡和EMMC 驱动是否正常,使用命令 mmc list 列出当前的 MMC 设备,结果
可以看出当前有两个 MMC 设备,检查每个 MMC 设备信息,先检查 MMC 设
备 0,输入如下命令:
mmc dev 0
mmc info
mmc 设备 0 是 SD 卡, SD 卡容量为 7.4GB,这个和我所使用的SD 卡信息相符,说明 SD 卡驱动正常。再来检查 MMC 设备 1,输入如下命令:
mmc 设备 1 为 EMMC,容量为 7.3GB,说明 EMMC 驱动也成功,SD 卡和 EMMC 的驱动都没问题。
如果 uboot 中的 LCD 驱动正确的话,启动 uboot 以后 LCD 上应该会显示出 NXP 的 logo,
lcd显示内容重叠,有问题,因为 NXP 官方 I.MX6ULL 开发板的屏幕就是 4.3 寸 480x272 分辨率的,所以 uboot 默认 LCD 驱动是 4.3 寸 480x272 分辨率的。如果使用其他分辨率的 LCD 就需要修改 LCD 驱动,这里我使用的是800x480
uboot 启动的时候提示“Board Net Initialization Failed”和“No ethernet found.”这两行,说明网络驱动也有问题,正常情况下应该是
现在没有图中的信息,那更别说 ping 一下 ubuntu 主机了,说明当前 uboot 的网络部驱动也是有问题的,这是因为正点原子开发板的网络芯片复位引脚和 NXP 官方开发板不一样,因此需要修改驱动。
总结一下 NXP 官方 I.MX6ULL EVK 开发板的 uboot 在正点原子 EMMC 版本 I.MX6ULL
开发板上的运行情况:
①、uboot 启动正常,DRAM 识别正确,SD 卡和EMMC 驱动正常。
②、uboot 里面的 LCD 驱动默认是给 4.3 寸 480x272 分辨率的,如果使用的其他分辨率的屏幕需要修改驱动。
③、网络不能工作,识别不出来网络信息,需要修改驱动。
接下来我们要做的工作如下:
①、前面我们一直使用着NXP 官方开发板的 uboot 配置,接下来需要在 uboot 中添加我们自己的开发板,也就是正点原子的 I.MX6ULL 开发板。
②、解决LCD 驱动和网络驱动的问题。
NXP 官方 uboot 中默认都是 NXP 自己的开发板,虽说我们可以直接在官方的开发板上直接修改,使 uboot 可以完整的运行在我们的板子上。
接下来我们就参考 NXP 官方的 I.MX6ULL EVK 开发板,学习如何在 uboot 中添加我们的开发板或者开发平台。
先在 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 中的内容改成下面的:
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y
CONFIG_CMD_GPIO=y
mx6ull_alientek_emmc_defconfig 基本和 mx6ull_14x14_evk_emmc_defconfig 中的内容一样,只是第 1 行和第 4 行做了修改。
在 目 录 include/configs 下 添 加 I.MX6ULL-ALPHA 开 发 板 对 应 的 头 文 件 , 复 制include/configs/mx6ullevk.h,并重命名为 alientek_mx6ull_emmc.h,命令如下:
cd include/configs/
cp mx6ullevk.h mx6ull_alientek_emmc.h
拷贝完成以后将:
#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H
改为:
#ifndef __ALIENTEK_MX6ULL_EMMC_CONFIG_H
#define __ALIENTEK_MX6ULL_EMMC_CONFIG_H
alientek_mx6ull_emmc.h 里面有很多宏定义,这些宏定义基本用于配置 uboot,也有一些I.MX6ULL 的配置项目。如果我们自己要想使能或者禁止 uboot 的某些功能,那就在alientek_mx6ull_emmc.h 里面做修改即可。 alientek_mx6ull_emmc.h 里面的内容比较多,去掉一些用不到的配置,精简后的内容如下:
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* Configuration settings for the Freescale i.MX6UL 14x14 EVK board.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ALIENTEK_MX6ULL_EMMC_CONFIG_H
#define __ALIENTEK_MX6ULL_EMMC_CONFIG_H
#include <asm/arch/imx-regs.h>
#include <linux/sizes.h>
#include "mx6_common.h"
#include <asm/imx-common/gpio.h>
/* uncomment for PLUGIN mode support */
/* #define CONFIG_USE_PLUGIN */
/* uncomment for SECURE mode support */
/* #define CONFIG_SECURE_BOOT */
#ifdef CONFIG_SECURE_BOOT
#ifndef CONFIG_CSF_SIZE
#define CONFIG_CSF_SIZE 0x4000
#endif
#endif
#define is_mx6ull_9x9_evk() CONFIG_IS_ENABLED(TARGET_MX6ULL_9X9_EVK)
#ifdef CONFIG_TARGET_MX6ULL_9X9_EVK
#define PHYS_SDRAM_SIZE SZ_256M
#define CONFIG_BOOTARGS_CMA_SIZE "cma=96M "
#else
#define PHYS_SDRAM_SIZE SZ_512M
#define CONFIG_BOOTARGS_CMA_SIZE ""
/* DCDC used on 14x14 EVK, no PMIC */
#undef CONFIG_LDO_BYPASS_CHECK
#endif
/* SPL options */
/* We default not support SPL
* #define CONFIG_SPL_LIBCOMMON_SUPPORT
* #define CONFIG_SPL_MMC_SUPPORT
* #include "imx6_spl.h"
*/
#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DISPLAY_BOARDINFO
/* Size of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN (16 * SZ_1M)
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_BOARD_LATE_INIT
#define CONFIG_MXC_UART
#define CONFIG_MXC_UART_BASE UART1_BASE
/* MMC Configs */
#ifdef CONFIG_FSL_USDHC
#define CONFIG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR
/* NAND pin conflicts with usdhc2 */
#ifdef CONFIG_SYS_USE_NAND
#define CONFIG_SYS_FSL_USDHC_NUM 1
#else
#define CONFIG_SYS_FSL_USDHC_NUM 2
#endif
#endif
/* I2C configs */
#define CONFIG_CMD_I2C
#ifdef CONFIG_CMD_I2C
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MXC
#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */
#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */
#define CONFIG_SYS_I2C_SPEED 100000
/* PMIC only for 9X9 EVK */
#define CONFIG_POWER
#define CONFIG_POWER_I2C
#define CONFIG_POWER_PFUZE3000
#define CONFIG_POWER_PFUZE3000_I2C_ADDR 0x08
#endif
#define CONFIG_SYS_MMC_IMG_LOAD_PART 1
#ifdef CONFIG_SYS_BOOT_NAND
#define CONFIG_MFG_NAND_PARTITION "mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "
#else
#define CONFIG_MFG_NAND_PARTITION ""
#endif
#define CONFIG_MFG_ENV_SETTINGS \
"mfgtool_args=setenv bootargs console=${console},${baudrate} " \
CONFIG_BOOTARGS_CMA_SIZE \
"rdinit=/linuxrc " \
"g_mass_storage.stall=0 g_mass_storage.removable=1 " \
"g_mass_storage.file=/fat g_mass_storage.ro=1 " \
"g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF "\
"g_mass_storage.iSerialNumber=\"\" "\
CONFIG_MFG_NAND_PARTITION \
"clk_ignore_unused "\
"\0" \
"initrd_addr=0x83800000\0" \
"initrd_high=0xffffffff\0" \
"bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};\0" \
#if defined(CONFIG_SYS_BOOT_NAND)
#define CONFIG_EXTRA_ENV_SETTINGS \
CONFIG_MFG_ENV_SETTINGS \
"panel=TFT43AB\0" \
"fdt_addr=0x83000000\0" \
"fdt_high=0xffffffff\0" \
"console=ttymxc0\0" \
"bootargs=console=ttymxc0,115200 ubi.mtd=4 " \
"root=ubi0:rootfs rootfstype=ubifs " \
CONFIG_BOOTARGS_CMA_SIZE \
"mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs)\0"\
"bootcmd=nand read ${loadaddr} 0x4000000 0x800000;"\
"nand read ${fdt_addr} 0x5000000 0x100000;"\
"bootz ${loadaddr} - ${fdt_addr}\0"
#else
#define CONFIG_EXTRA_ENV_SETTINGS \
CONFIG_MFG_ENV_SETTINGS \
"script=boot.scr\0" \
"image=zImage\0" \
"console=ttymxc0\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
"fdt_file=undefined\0" \
"fdt_addr=0x83000000\0" \
"boot_fdt=try\0" \
"ip_dyn=yes\0" \
"panel=TFT43AB\0" \
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
"mmcautodetect=yes\0" \
"mmcargs=setenv bootargs console=${console},${baudrate} " \
CONFIG_BOOTARGS_CMA_SIZE \
"root=${mmcroot}\0" \
"loadbootscript=" \
"fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
"bootscript=echo Running bootscript from mmc ...; " \
"source\0" \
"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
"mmcboot=echo Booting from mmc ...; " \
"run mmcargs; " \
"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
"if run loadfdt; then " \
"bootz ${loadaddr} - ${fdt_addr}; " \
"else " \
"if test ${boot_fdt} = try; then " \
"bootz; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"fi; " \
"else " \
"bootz; " \
"fi;\0" \
"netargs=setenv bootargs console=${console},${baudrate} " \
CONFIG_BOOTARGS_CMA_SIZE \
"root=/dev/nfs " \
"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
"netboot=echo Booting from net ...; " \
"run netargs; " \
"if test ${ip_dyn} = yes; then " \
"setenv get_cmd dhcp; " \
"else " \
"setenv get_cmd tftp; " \
"fi; " \
"${get_cmd} ${image}; " \
"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
"bootz ${loadaddr} - ${fdt_addr}; " \
"else " \
"if test ${boot_fdt} = try; then " \
"bootz; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"fi; " \
"else " \
"bootz; " \
"fi;\0" \
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
"if test $board_name = EVK && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \
"if test $fdt_file = undefined; then " \
"echo WARNING: Could not determine dtb to use; fi; " \
"fi;\0" \
#define CONFIG_BOOTCOMMAND \
"run findfdt;" \
"mmc dev ${mmcdev};" \
"mmc dev ${mmcdev}; if mmc rescan; then " \
"if run loadbootscript; then " \
"run bootscript; " \
"else " \
"if run loadimage; then " \
"run mmcboot; " \
"else run netboot; " \
"fi; " \
"fi; " \
"else run netboot; fi"
#endif
/* Miscellaneous configurable options */
#define CONFIG_CMD_MEMTEST
#define CONFIG_SYS_MEMTEST_START 0x80000000
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x8000000)
#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
#define CONFIG_SYS_HZ 1000
#define CONFIG_STACKSIZE SZ_128K
/* Physical Memory Map */
#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM
#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR
#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE
#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
/* FLASH and environment organization */
#define CONFIG_SYS_NO_FLASH
#ifdef CONFIG_SYS_BOOT_QSPI
#define CONFIG_FSL_QSPI
#define CONFIG_ENV_IS_IN_SPI_FLASH
#elif defined CONFIG_SYS_BOOT_NAND
#define CONFIG_SYS_USE_NAND
#define CONFIG_ENV_IS_IN_NAND
#else
#define CONFIG_FSL_QSPI
#define CONFIG_ENV_IS_IN_MMC
#endif
#define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */
#define CONFIG_SYS_MMC_ENV_PART 0 /* user area */
#define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */
#define CONFIG_CMD_BMODE
#ifdef CONFIG_FSL_QSPI
#define CONFIG_QSPI_BASE QSPI0_BASE_ADDR
#define CONFIG_QSPI_MEMMAP_BASE QSPI0_AMBA_BASE
#define CONFIG_CMD_SF
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_BAR
#define CONFIG_SF_DEFAULT_BUS 0
#define CONFIG_SF_DEFAULT_CS 0
#define CONFIG_SF_DEFAULT_SPEED 40000000
#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
#define CONFIG_SPI_FLASH_STMICRO
#endif
/* NAND stuff */
#ifdef CONFIG_SYS_USE_NAND
#define CONFIG_CMD_NAND
#define CONFIG_CMD_NAND_TRIMFFS
#define CONFIG_NAND_MXS
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x40000000
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_ONFI_DETECTION
/* DMA stuff, needed for GPMI/MXS NAND support */
#define CONFIG_APBH_DMA
#define CONFIG_APBH_DMA_BURST
#define CONFIG_APBH_DMA_BURST8
#endif
#define CONFIG_ENV_SIZE SZ_8K
#if defined(CONFIG_ENV_IS_IN_MMC)
#define CONFIG_ENV_OFFSET (12 * SZ_64K)
#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
#define CONFIG_ENV_OFFSET (768 * 1024)
#define CONFIG_ENV_SECT_SIZE (64 * 1024)
#define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS
#define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS
#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE
#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
#elif defined(CONFIG_ENV_IS_IN_NAND)
#undef CONFIG_ENV_SIZE
#define CONFIG_ENV_OFFSET (60 << 20)
#define CONFIG_ENV_SECT_SIZE (128 << 10)
#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
#endif
/* USB Configs */
#define CONFIG_CMD_USB
#ifdef CONFIG_CMD_USB
#define CONFIG_USB_EHCI
#define CONFIG_USB_EHCI_MX6
#define CONFIG_USB_STORAGE
#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
#define CONFIG_USB_HOST_ETHER
#define CONFIG_USB_ETHER_ASIX
#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW)
#define CONFIG_MXC_USB_FLAGS 0
#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
#endif
#ifdef CONFIG_CMD_NET
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_MII
#define CONFIG_FEC_MXC
#define CONFIG_MII
#define CONFIG_FEC_ENET_DEV 1
#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR 0x2
#define CONFIG_FEC_XCV_TYPE RMII
#elif (CONFIG_FEC_ENET_DEV == 1)
#define IMX_FEC_BASE ENET2_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR 0x1
#define CONFIG_FEC_XCV_TYPE RMII
#endif
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_PHYLIB
#define CONFIG_PHY_MICREL
#endif
#define CONFIG_IMX_THERMAL
#ifndef CONFIG_SPL_BUILD
#define CONFIG_VIDEO
#ifdef CONFIG_VIDEO
#define CONFIG_CFB_CONSOLE
#define CONFIG_VIDEO_MXS
#define CONFIG_VIDEO_LOGO
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#define CONFIG_SPLASH_SCREEN
#define CONFIG_SPLASH_SCREEN_ALIGN
#define CONFIG_CMD_BMP
#define CONFIG_BMP_16BPP
#define CONFIG_VIDEO_BMP_RLE8
#define CONFIG_VIDEO_BMP_LOGO
#define CONFIG_IMX_VIDEO_SKIP
#endif
#endif
#define CONFIG_IOMUX_LPSR
#if defined(CONFIG_ANDROID_SUPPORT)
#include "mx6ullevk_android.h"
#endif
#endif
可以看出, alientek_mx6ull_emmc.h 文件中基本都是“CONFIG_”开头的宏定义,这也说明 alientek_mx6ull_emmc.h 文件的主要功能就是配置或者裁剪 uboot。如果需要某个功能的话就在里面添加这个功能对应的 CONFIG_XXX 宏即可,如果不需要某个功能的话就删除掉对应的宏即可。我们以示例代码 为例,详细的看一下 alientek_mx6ull_emmc.h中这些宏都是什么功能。
UART1_BASE= (ATZ1_BASE_ADDR + 0x20000)
=AIPS1_ARB_BASE_ADDR + 0x20000
=0x02000000 + 0x20000
=0X02020000
查阅 I.MX6ULL 参考手册, UART1 的寄存器基地址正是 0X02020000
NAND 的分区是可以调整的,比如 boot 分区我们用不了 64M 这么大,因此可以将其改小,其他的分区一样的。
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 目录下的文件做一些修改:
将 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这个文件。
将 imximage.cfg 中的下面一句:
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000
改为:
PLUGIN board/freescale/mx6ull_alientek_emmc/plugin.bin 0x00907000
修改 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
修改 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
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 中了,接下来就是编译这个新添加的开发板。
在 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 开发板上是有问题的,需要修改。
一般 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 还是没有正常工作的,那就要检查自己哪里有没有改错,或者还有哪里没有修改。
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,所以驱动肯定是一样的。
首先修改 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。
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 开发板两个网络复位引脚了。
在 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.不需要!!!!!!!!!!!!!!
在 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 启动信息如图 所示:
设置开发板为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