uboot移植

目录

1.编译 NXP 官方开发板对应的 uboot

2. 烧写验证与驱动测试

1、SD 卡和 EMMC 驱动检查

2、LCD 驱动检查

3、网络驱动

3.在 U-Boot 中添加自己的开发板

1.添加开发板默认配置文件

2. 添加开发板对应的头文件 

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

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

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

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

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

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

 5.LCD 驱动修改

6. 网络驱动修改

网络 PHY 地址修改

删除 uboot 中 74LV595 的驱动代码

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

其他需要修改的地方

bootcmd 和 bootargs 环境变量

环境变量 bootcmd

环境变量 bootargs  


 

1.编译 NXP 官方开发板对应的 uboot

找到 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 赋值,修改如图 33.1.2.2 所示:
这样我们就可 以使用如下简短的命令来编译 uboot 了:
make mx6ull_14x14_evk_emmc_defconfig
make V=1 -j16

2. 烧写验证与驱动测试

imxdownload 软件拷贝到 uboot 源码根目录下,然后使用 imxdownload 软件将 u-boot.bin
烧写到 SD 卡中,烧写命令如下:
chmod 777 imxdownload //给予 imxdownload 可执行权限
./imxdownload u-boot.bin /dev/sdd //烧写到 SD 卡中,不能烧写到 /dev/sda sda1 里面

1SD 卡和 EMMC 驱动检查

使用命令 mmc list 列出当前的 MMC 设备,
检查每个 MMC 设备信息,先检查 MMC 设 备 0 ,输入如下命令:
mmc dev 0
mmc info

 

可以看出, mmc 设备 0 SD 卡, SD 卡容量为 14.8GB ,这个和我所使用的
SD 卡信息相符,说明 SD 卡驱动正常。再来检查 MMC 设备 1 ,输入如下命令:
mmc dev 1
mmc info

 

从图 33.1.3.4 可以看出, mmc 设备 1 EMMC ,容量为 7.3GB ,说明 EMMC 驱动也成功,
SD 卡和 EMMC 的驱动都没问题。

2LCD 驱动检查

如果 uboot 中的 LCD 驱动正确的话,启动 uboot 以后 LCD 上应该会显示出 NXP logo
如下图 33.1.3.5 所示:

 

如果你用的不是正点原子的 4.3 480x272 分辨率的屏幕的话,那么 LCD 就不会显示
33.1.3.5 所示 logo 界面。因为 NXP 官方 I.MX6ULL 开发板的屏幕就是 4.3 480x272 分辨率
的,所以 uboot 默认 LCD 驱动是 4.3 480x272 分辨率的。如果使用其他分辨率的 LCD 就需
要修改 LCD 驱动,这里我们先不修改 LCD 驱动了,稍后我们在讲解如何修改 uboot 中的 LCD
驱动,我们只需要记得, uboot LCD 需要修改就行了。

3、网络驱动

uboot 启动的时候提示“ Board Net Initialization Failed ”和“ No ethernet found. ”这两行,说
明网络驱动也有问题,

3.U-Boot 中添加自己的开发板

1.添加开发板默认配置文件

先在 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 行和第 4 行做了修改。

2. 添加开发板对应的头文件 

在目录 include/configs 下添加 I.MX6ULL-ALPHA 开 发 板 对 应 的 头 文 件 , 复 制
include/configs/mx6ullevk.h ,并重命名为 mx6ull_alientek_emmc.h ,命令如下:
cp include/configs/mx6ullevk.h 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 的某些功能,那就在 mx6ull_alientek_emmc.h 里面做修改即可。 mx6ull_alientek_emmc.h 里面的内容比较多,去掉一 些用不到的配置,精简后的内容如下:
10
11
12 #include < asm / arch / imx - regs . h >
13 #include < linux / sizes . h >
14 #include "mx6_common.h"
15 #include < asm / imx - common / gpio . h >
16
......
28
29 #define is_mx6ull_9x9_evk () CONFIG_IS_ENABLED ( TARGET_MX6ULL_9X9_EVK )
30
31 #ifdef CONFIG_TARGET_MX6ULL_9X9_EVK
32 #define PHYS_SDRAM_SIZE SZ_256M
33 #define CONFIG_BOOTARGS_CMA_SIZE "cma=96M "
34 # else
35 #define PHYS_SDRAM_SIZE SZ_512M
36 #define CONFIG_BOOTARGS_CMA_SIZE ""
37 /* DCDC used on 14x14 EVK, no PMIC */
38 #undef CONFIG_LDO_BYPASS_CHECK
39 #endif
40
41 /* SPL options */
42 /* We default not support SPL
43 * #define CONFIG_SPL_LIBCOMMON_SUPPORT
44 * #define CONFIG_SPL_MMC_SUPPORT
45 * #include "imx6_spl.h"
46 */
47
48 #define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
49
50 #define CONFIG_DISPLAY_CPUINFO
51 #define CONFIG_DISPLAY_BOARDINFO
52
53 /* Size of malloc() pool */
54 #define CONFIG_SYS_MALLOC_LEN ( 16 * SZ_1M )
55
56 #define CONFIG_BOARD_EARLY_INIT_F
57 #define CONFIG_BOARD_LATE_INIT
58
59 #define CONFIG_MXC_UART
60 #define CONFIG_MXC_UART_BASE UART1_BASE
61
62 /* MMC Configs */
63 #ifdef CONFIG_FSL_USDHC
64 #define CONFIG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR
65
66 /* NAND pin conflicts with usdhc2 */
67 #ifdef CONFIG_SYS_USE_NAND
68 #define CONFIG_SYS_FSL_USDHC_NUM 1
69 # else
70 #define CONFIG_SYS_FSL_USDHC_NUM 2
71 #endif
72 #endif
73
74 /* I2C configs */
75 #define CONFIG_CMD_I2C
76 #ifdef CONFIG_CMD_I2C
77 #define CONFIG_SYS_I2C
78 #define CONFIG_SYS_I2C_MXC
79 #define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */
80 #define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */
81 #define CONFIG_SYS_I2C_SPEED 100000
82
......
89
90 #define CONFIG_SYS_MMC_IMG_LOAD_PART 1
91
92 #ifdef CONFIG_SYS_BOOT_NAND
93 #define CONFIG_MFG_NAND_PARTITION "mtdparts=gpmi
nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "
94 # else
95 #define CONFIG_MFG_NAND_PARTITION ""
96 #endif
97
98 #define CONFIG_MFG_ENV_SETTINGS \
99 "mfgtool_args=setenv bootargs console=${console},${baudrate} " \
......
111 "bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr}
${fdt_addr};\0" \
112
113 # if defined ( CONFIG_SYS_BOOT_NAND )
114 #define CONFIG_EXTRA_ENV_SETTINGS \
115 CONFIG_MFG_ENV_SETTINGS \
116 "panel=TFT43AB\0" \
......
126 "bootz ${loadaddr} - ${fdt_addr}\0"
127
128 # else
129 #define CONFIG_EXTRA_ENV_SETTINGS \
130 CONFIG_MFG_ENV_SETTINGS \
131 "script=boot.scr\0" \
......
202 "fi;\0" \
203
204 #define CONFIG_BOOTCOMMAND \
205 "run findfdt;" \
......
216 "else run netboot; fi"
217 #endif
218
219 /* Miscellaneous configurable options */
220 #define CONFIG_CMD_MEMTEST
221 #define CONFIG_SYS_MEMTEST_START 0x80000000
222 #define CONFIG_SYS_MEMTEST_END ( CONFIG_SYS_MEMTEST_START +
0x8000000 )
223
224 #define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
225 #define CONFIG_SYS_HZ 1000
226
227 #define CONFIG_STACKSIZE SZ_128K
228
229 /* Physical Memory Map */
230 #define CONFIG_NR_DRAM_BANKS 1
231 #define PHYS_SDRAM MMDC0_ARB_BASE_ADDR
232
233 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM
234 #define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR
235 #define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE
236
237 #define CONFIG_SYS_INIT_SP_OFFSET \
238 ( CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE )
239 #define CONFIG_SYS_INIT_SP_ADDR \
240 ( CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET )
241
242 /* FLASH and environment organization */
243 #define CONFIG_SYS_NO_FLASH
244
......
255
256 #define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */
257 #define CONFIG_SYS_MMC_ENV_PART 0 /* user area */
258 #define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */
259
260 #define CONFIG_CMD_BMODE
261
......
275
276 /* NAND stuff */
277 #ifdef CONFIG_SYS_USE_NAND
278 #define CONFIG_CMD_NAND
279 #define CONFIG_CMD_NAND_TRIMFFS
280
281 #define CONFIG_NAND_MXS
282 #define CONFIG_SYS_MAX_NAND_DEVICE 1
283 #define CONFIG_SYS_NAND_BASE
0x40000000
284 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
285 #define CONFIG_SYS_NAND_ONFI_DETECTION
286
287 /* DMA stuff, needed for GPMI/MXS NAND support */
288 #define CONFIG_APBH_DMA
289 #define CONFIG_APBH_DMA_BURST
290 #define CONFIG_APBH_DMA_BURST8
291 #endif
292
293 #define CONFIG_ENV_SIZE
SZ_8K
294 # if defined ( CONFIG_ENV_IS_IN_MMC )
295 #define CONFIG_ENV_OFFSET
( 12 * SZ_64K )
296 #elif defined ( CONFIG_ENV_IS_IN_SPI_FLASH )
297 #define CONFIG_ENV_OFFSET
( 768 * 1024 )
298 #define CONFIG_ENV_SECT_SIZE ( 64 * 1024 )
299 #define CONFIG_ENV_SPI_BUS
CONFIG_SF_DEFAULT_BUS
300 #define CONFIG_ENV_SPI_CS
CONFIG_SF_DEFAULT_CS
301 #define CONFIG_ENV_SPI_MODE
CONFIG_SF_DEFAULT_MODE
302 #define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
303 #elif defined ( CONFIG_ENV_IS_IN_NAND )
304 #undef CONFIG_ENV_SIZE
305 #define CONFIG_ENV_OFFSET
( 60 << 20 )
306 #define CONFIG_ENV_SECT_SIZE ( 128 << 10 )
307 #define CONFIG_ENV_SIZE
CONFIG_ENV_SECT_SIZE
308 #endif
309
310
311 /* USB Configs */
312 #define CONFIG_CMD_USB
313 #ifdef CONFIG_CMD_USB
314 #define CONFIG_USB_EHCI
315 #define CONFIG_USB_EHCI_MX6
316 #define CONFIG_USB_STORAGE
317 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET
318 #define CONFIG_USB_HOST_ETHER
319 #define CONFIG_USB_ETHER_ASIX
320 #define CONFIG_MXC_USB_PORTSC
( PORT_PTS_UTMI | PORT_PTS_PTW )
321 #define CONFIG_MXC_USB_FLAGS
0
322 #define CONFIG_USB_MAX_CONTROLLER_COUNT 2
323 #endif
324
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
347
348 #define CONFIG_IMX_THERMAL
349
350 #ifndef CONFIG_SPL_BUILD
351 #define CONFIG_VIDEO
352 #ifdef CONFIG_VIDEO
353 #define CONFIG_CFB_CONSOLE
354 #define CONFIG_VIDEO_MXS
355 #define CONFIG_VIDEO_LOGO
356 #define CONFIG_VIDEO_SW_CURSOR
357 #define CONFIG_VGA_AS_SINGLE_DEVICE
358 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
359 #define CONFIG_SPLASH_SCREEN
360 #define CONFIG_SPLASH_SCREEN_ALIGN
361 #define CONFIG_CMD_BMP
362 #define CONFIG_BMP_16BPP
363 #define CONFIG_VIDEO_BMP_RLE8
364 #define CONFIG_VIDEO_BMP_LOGO
365 #define CONFIG_IMX_VIDEO_SKIP
366 #endif
367 #endif
368
369 #define CONFIG_IOMUX_LPSR
370
......
375 #endif

 

可以看出, mx6ull_alientek_emmc.h 文件中基本都是“ CONFIG_ ”开头 的宏定义,这也说明 mx6ull_alientek_emmc.h 文件的主要功能就是配置或者裁剪 uboot 。如果需 要某个功能的话就在里面添加这个功能对应的 CONFIG_XXX 宏即可,如果不需要某个功能的 话就删除掉对应的宏即可。
14 行,添加了头文件 mx6_common.h ,如果在 mx6ull_alientek_emmc.h 中没有发现配置
某个功能或命令,但是实际却存在的话,可以到 mx6_common.h 文件里面去找一下。
29~39 行,设置 DRAM 的大小,宏 PHYS_SDRAM_SIZE 就是板子上 DRAM 的大小,
如果用的 NXP 官方的 9X9 EVK 开发板的话 DRAM 大小就为 256MB 。否则的话默认为 512MB
正点原子的 I.MX6U-ALPHA 开发板用的是 512MB DDR3
50 行,定义宏 CONFIG_DISPLAY_CPUINFO uboot 启动的时候可以输出 CPU 信息。
51 行,定义宏 CONFIG_DISPLAY_BOARDINFO uboot 启动的时候可以输出板子信息。
54 行, CONFIG_SYS_MALLOC_LEN malloc 内存池大小,这里设置为 16MB
56 行,定义宏 CONFIG_BOARD_EARLY_INIT_F ,这样 board_init_f 函数就会调用
board_early_init_f 函数。
57 行,定义宏 CONFIG_BOARD_LATE_INIT ,这样 board_init_r 函数就会调用
board_late_init 函数。
59 60 行,使能 I.MX6ULL 的串口功能,宏 CONFIG_MXC_UART_BASE 表示串口寄
存器基地址,这里使用的串口 1 ,基地址为 UART1_BASE UART1_BASE 定义在文件
arch/arm/include/asm/arch-mx6/imx-regs.h 中, imx-regs.h I.MX6ULL 寄存器描述文件,根据
imx-regs.h 可得到 UART1_BASE 的值如下:
UART1_BASE= (ATZ1_BASE_ADDR + 0x20000)
=AIPS1_ARB_BASE_ADDR + 0x20000
=0x02000000 + 0x20000
=0X02020000
63
64 行,
EMMC 接在 I.MX6ULL USDHC2 上,宏 CONFIG_SYS_FSL_ESDHC_ADDR
EMMC 所使用接口的寄存器基地址,也就是 USDHC2 的基地址。
67~72 行,跟 NAND 相关的宏,因为 NAND USDHC2 的引脚冲突,因此如果使用
NAND 的只能使用一个 USDHC 设备 (SD ) 。如果没有使用 NAND ,那么就有两个 USDHC
(EMMC SD ) ,宏 CONFIG_SYS_FSL_USDHC_NUM 表示 USDHC 数量。 EMMC 版本的
核心版没有用到 NAND ,所以 CONFIG_SYS_FSL_USDHC_NUM=2
75~81 ,和 I2C 有关的宏定义,用于控制使能哪个 I2C I2C 的速度为多少。
92~96 行, NAND 的分区设置,如果使用 NAND 的话,默认的 NAND 分区为:
"mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "
98~111 行,宏 CONFIG_MFG_ENV_SETTINGS 定义了一些环境变量,使用 MfgTool
写系统时候会用到这里面的环境变量。
113~202 行 , 通 过 条 件 编 译 来 设 置 宏 CONFIG_EXTRA_ENV_SETTINGS , 宏
CONFIG_EXTRA_ENV_SETTINGS 也是设置一些环境变量,此宏会设置 bootargs 这个环境变
量,后面我们会详细分析这个宏定义。
204~217 行,设置宏 CONFIG_BOOTCOMMAND ,此宏就是设置环境变量 bootcmd
值。后面会详细的分析这个宏定义。
220~222 行,设置命令 memtest 相关宏定义,比如使能命令 memtest ,设置 memtest 测试
的内存起始地址和内存大小。
224 行,宏 CONFIG_SYS_LOAD_ADDR 表示 linux kernel DRAM 中的加载地址,也
就是 linux kernel DRAM 中的存储首地址, CONFIG_LOADADDR=0X80800000
225 行,宏 CONFIG_SYS_HZ 为系统时钟频率,这里为 1000Hz
227 行,宏 CONFIG_STACKSIZE 为栈大小,这里为 128KB
230 行,宏 CONFIG_NR_DRAM_BANKS DRAM BANK 的数量, I.MX6ULL 只有一
DRAM BANK ,我们也只用到了一个 BANK ,所以为 1
231 行,宏 PHYS_SDRAM I.MX6ULL DRAM 控制器 MMDC0 所管辖的 DRAM
围起始地址,也就是 0X80000000
233 行,宏 CONFIG_SYS_SDRAM_BASE DRAM 的起始地址。
234 行,宏 CONFIG_SYS_INIT_RAM_ADDR I.MX6ULL 内部 IRAM 的起始地址 (
就是 OCRAM 的起始地址 ) ,为 0X00900000
235 行,宏 CONFIG_SYS_INIT_RAM_SIZE I.MX6ULL 内部 IRAM 的大小 (OCRAM
的大小 ) ,为 0X00040000=128KB
237~240 行,宏 CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_INIT_SP_ADDR
初始 SP 有关,第一个为初始 SP 偏移,第二个为初始 SP 地址。
256 行,宏 CONFIG_SYS_MMC_ENV_DEV 为默认的 MMC 设备,这里默认为 USDHC2
也就是 EMMC
257 行,宏 CONFIG_SYS_MMC_ENV_PART 为模式分区,默认为第 0 个分区。
258 行,宏 CONFIG_MMCROOT 设置进入 linux 系统的根文件系统所在的分区,这里设
置为 "/dev/mmcblk1p2" ,也就是 EMMC 设备的第 2 个分区。第 0 个分区保存 uboot ,第 1 个分
区保存 linux 镜像和设备树,第 2 个分区为 Linux 系统的根文件系统。
277~291 行,与 NAND 有关的宏定义,如果使用 NAND 的话。
293 行,宏 CONFIG_ENV_SIZE 为环境变量大小,默认为 8KB
294~308 行,宏 CONFIG_ENV_OFFSET 为环境变量偏移地址,这里的偏移地址是相对
于存储器的首地址。如果环境变量保存在 EMMC 中的话,环境变量偏移地址为 12*64KB 。如
果环境变量保存在 SPI FLASH 中的话,偏移地址为 768*1024 。如果环境变量保存在 NAND
的话,偏移地址为 60<<20(60MB) ,并且重新设置环境变量的大小为 128KB
312~323 行,与 USB 相关的宏定义。
325~342 行,与网络相关的宏定义,比如使能 dhcp ping 等命令。第 331 行的宏
CONFIG_FEC_ENET_DEV 指定 uboot 所使用的网口, I.MX6ULL 有两个网口,为 0 的时候使
ENET1 ,为 1 的时候使用 ENET2 。宏 IMX_FEC_BASE ENET 接口的寄存器首地址,宏
CONFIG_FEC_MXC_PHYADDR 为网口 PHY 芯片的地址。宏 CONFIG_FEC_XCV_TYPE
PHY 芯片所使用的接口类型, I.MX6U-ALPHA 开发板的两个 PHY 都使用的 RMII 接口。
344~END ,剩下的都是一些配置宏,比如 CONFIG_VIDEO 宏用于开启 LCD
CONFIG_VIDEO_LOGO 使能 LOGO 显示, CONFIG_CMD_BMP 使能 BMP 图片显示指令。这
样就可以在 uboot 中显示图片了,一般用于显示 logo

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 文件

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 文件

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

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

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

修改文件 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 的前一行添加如下内容:

1 source "board/freescale/mx6ull_alientek_emmc/Kconfig"

添加完成以后的 Kconfig 文件如图 33.2.4.1 所示:

 

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

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

 5.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 ,找到如下所示内容:
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 } } };

修改如下:

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.c uboot 默认的屏幕 参数。
打开 mx6ull_alientek_emmc.h ,找到所有如下语句:
panel=TFT43AB

将其改为:

panel=TFT7016  

也就是设置 panel TFT7016 panel 的值要与示例代码 33.2.6.4 中的 .name 成员变量的值
一致。
如果 EMMC 中的环境变量 panel 不等于 TFT7016 ,那么 LCD 显示肯定不正常,我们只需要在
uboot 中修改 panel 的值为 TFT7016 即可,在 uboot 的命令模式下输入如下命令:
setenv panel TFT7016
saveenv

6. 网络驱动修改

①、 ENET1 复位引脚初始化。
②、 LAN8720A 的器件 ID
③、 LAN8720 驱动
①、 ENET2 的复位引脚,从图 33.2.7.2 可以看出, ENET2 的复位引脚 ENET2_RST 接到了
I.MX6ULL SNVS_TAMPER8 上。
②、 ENET2 所使用的 PHY 芯片器件地址,从图 33.2.7.2 可以看出, PHY 器件地址为 0X1
③、 LAN8720 驱动, ENET1 ENET2 都使用的 LAN8720 ,所以驱动肯定是一样的。

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

删除 uboot 74LV595 的驱动代码

uboot 中网络 PHY 芯片地址修改完成以后就是网络复位引脚的驱动修改了,打开
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)
示例代码 33.2.7.3 中以 IOX 开头的宏定义是 74LV595 的相关 GPIO ,因为 NXP 官方
I.MX6ULL EVK 开发板使用 74LV595 来扩展 IO ,两个网络的复位引脚就是由 74LV595 来控制
的。正点原子的 I.MX6U-ALPHA 开发板并没有使用 74LV595 ,因此我们将示例代码 33.2.7.3
的代码删除掉,替换为如下所示代码:
#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 中找到如下代码:
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),
};
同理,示例代码 33.2.7.5 74LV595 IO 配置参数结构体,将其删除掉。继续在
mx6ull_alientek_emmc.c 中找到函数 iox74lv_init ,如下所示:
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);
};
iox74lv_init 函数是 74LV595 的初始化函数, iox74lv_set 函数用于控制 74LV595 IO 输出
电平,将这两个函数全部删除掉!
mx6ull_alientek_emmc.c 中找到 board_init 函数,此函数是板子初始化函数,会被
board_init_r 调用, board_init 函数内容如下:
int board_init(void)
{
......
imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
 iox74lv_init();
 ......
return 0;
}
board_init 会调用 imx_iomux_v3_setup_multiple_pads iox74lv_init 这两个函数来初始化
74lv595 GPIO ,将这两行删除掉。至此, mx6ull_alientek_emmc.c 中关于 74LV595 芯片的驱
动代码都删除掉了,接下来就是添加 I.MX6U-ALPHA 开发板两个网络复位引脚了。

添加 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 };
结构体数组 fec1_pads fec2_pads ENET1 ENET2 这两个网口的 IO 配置参数,在这
两个数组中添加两个网口的复位 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 };
示例代码 33.2.7.9 中,第 651 行和 667 行分别是 ENET1 ENET2 的复位 IO 配置参数。继
续在文件 mx6ull_alientek_emmc.c 中找到函数 setup_iomux_fec ,此函数默认代码如下:
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 }
函数 setup_iomux_fec 就是根据 fec1_pads fec2_pads 这两个网络 IO 配置数组来初始化
I.MX6ULL 的网络 IO 。我们需要在其中添加网络复位 IO 的初始化代码,并且复位一下 PHY
片,修改后的 setup_iomux_fec 函数如下:
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 }
示例代码 33.2.7.11 中第 676 ~679 行和第 685 ~688 行分别对应 ENET1 ENET2 的复
IO 初始化,将这两个 IO 设置为输出并且硬件复位一下 LAN8720A ,这个硬件复位很重要!
否则可能导致 uboot 无法识别 LAN8720A
大功基本上告成,还差最后一步, uboot 中的 LAN8720A 驱动有点问题,打开文件
drivers/net/phy/phy.c ,找到函数 genphy_update_link ,这是个通用 PHY 驱动函数,此函数用于更
PHY 的连接状态和速度。使用 LAN8720A 的时候需要在此函数中添加一些代码,修改后的
函数 genphy_update_link 如下所示:
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
239 /*
240 * Wait if the link is up, and autonegotiation is in progress
241 * (ie - we're capable and it's not done)
242 */
243 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
......
291
292 return 0;
293 }
225 ~237 行就是新添加的代码,为条件编译代码段,只有使用 SMSC 公司的 PHY 这段
代码才会执行 ( 目前只测试了 LAN8720A SMSC 公司其他的芯片还未测试 ) 。第 229 行读取
LAN8720A BMCR 寄存器 ( 寄存器地址为 0) ,此寄存器为 LAN8720A 的配置寄存器,这里先
读取此寄存器的默认值并保存起来。 230 行向寄存器 BMCR 寄存器写入 BMCR_RESET( 值为
0X8000) ,因为 BMCR bit15 是软件复位控制位,因此 230 行就是软件复位 LAN8720A ,复位
完成以后此位会自动清零。第 231~233 行等待 LAN8720A 软件复位完成,也就是判断 BMCR
bit15 位是否为 1 ,为 1 的话表示还没有复位完成。第 234 行重新向 BMCR 寄存器写入以前
的值,也就是 229 行读出的那个值。
至此网络的复位引脚驱动修改完成,重新编译 uboot ,然后将 u-boot.bin 烧写到 SD 卡中并
启动,
可以看到“ Net FEC1 ”这一行,提示当前使用的 FEC1 这个网口,也就 是 ENET2 。在 uboot 中使用网络之前要先设置几个环境变量,命令如下:
etenv 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 //保存环境变量
再来测试一下 ENET1 的网络是否正常工作,打开 mx6ull_alientek_emmc.h , 将CONFIG_FEC_ENET_DEV 改为 0 ,然后重新编译一下 uboot 并烧写到 SD 卡中重启。重启开
发板,建议大家将 ENET2 设置为 uboot 的默认网卡!也就是将宏 CONFIG_FEC_ENET_DEV 设置为 1。

其他需要修改的地方

uboot 启动信息中会有“ Board: MX6ULL 14x14 EVK ”这一句,也就是说板子名字为
MX6ULL 14x14 EVK ”,要将其改为我们所使用的板子名字,比如“ MX6ULL ALIENTEK
EMMC ”或者“ 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;
}

bootcmd bootargs 环境变量

uboot 中有两个非常重要的环境变量 bootcmd bootargs ,接下来看一下这两个环境变量。
bootcmd bootagrs 是采用类似 shell 脚本语言编写的,里面有很多的变量引用,这些变量其实
都 是 环 境 变 量 , 有 很 多 是 NXP 自 己 定 义 的 。 文 件 mx6ull_alientek_emmc.h 中的宏
CONFIG_EXTRA_ENV_SETTINGS 保存着这些环境变量的默认值,内容如下:
113 #if defined(CONFIG_SYS_BOOT_NAND)
114 #define CONFIG_EXTRA_ENV_SETTINGS \
115 CONFIG_MFG_ENV_SETTINGS \
116 "panel=TFT43AB\0" \
117 "fdt_addr=0x83000000\0" \
118 "fdt_high=0xffffffff\0" \
......
126 "bootz ${loadaddr} - ${fdt_addr}\0"
127
128 #else
129 #define CONFIG_EXTRA_ENV_SETTINGS \
130 CONFIG_MFG_ENV_SETTINGS \
131 "script=boot.scr\0" \
132 "image=zImage\0" \
133 "console=ttymxc0\0" \
134 "fdt_high=0xffffffff\0" \
135 "initrd_high=0xffffffff\0" \
136 "fdt_file=undefined\0" \
......
194 "findfdt="\
195 "if test $fdt_file = undefined; then " \
196 "if test $board_name = EVK && test $board_rev = 9X9; then " \
197 "setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
198 "if test $board_name = EVK && test $board_rev = 14X14; then " \
199 "setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \
200 "if test $fdt_file = undefined; then " \
201 "echo WARNING: Could not determine dtb to use; fi; " \
202 "fi;\0" \
CONFIG_EXTRA_ENV_SETTINGS 是个条件编译语句,使用 NAND EMMC 的时候
CONFIG_EXTRA_ENV_SETTINGS 的值是不同的。

环境变量 bootcmd

bootcmd 保存着 uboot 默认命令, uboot 倒计时结束以
后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC
NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。可
以在 uboot 启动以后进入命令行设置 bootcmd 环境变量的值。如果 EMMC 或者 NAND 中没有
保存 bootcmd 的值,那么 uboot 就会使用默认的值,板子第一次运行 uboot 的时候都会使用默
认值来设置 bootcmd 环境变量。打开文件 include/env_default.h ,在此文件中有如下所示内容:
13 #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
14 env_t environment __PPCENV__ = {
15 ENV_CRC, /* CRC Sum */
16 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
17 1, /* Flags: valid */
18 #endif
19 {
20 #elif defined(DEFAULT_ENV_INSTANCE_STATIC)
21 static char default_environment[] = {
22 #else
23 const uchar default_environment[] = {
24 #endif
25 #ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
26 ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
27 #endif
28 #ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
29 ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
30 #endif
31 #ifdef CONFIG_BOOTARGS
32 "bootargs=" CONFIG_BOOTARGS "\0"
33 #endif
34 #ifdef CONFIG_BOOTCOMMAND
35 "bootcmd=" CONFIG_BOOTCOMMAND "\0"
36 #endif
37 #ifdef CONFIG_RAMBOOTCOMMAND
38 "ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
39 #endif
40 #ifdef CONFIG_NFSBOOTCOMMAND
41 "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
42 #endif
43 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
44 "bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
45 #endif
46 #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
47 "baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
48 #endif
49 #ifdef CONFIG_LOADS_ECHO
50 "loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0"
51 #endif
52 #ifdef CONFIG_ETHPRIME
53 "ethprime=" CONFIG_ETHPRIME "\0"
54 #endif
55 #ifdef CONFIG_IPADDR
56 "ipaddr=" __stringify(CONFIG_IPADDR) "\0"
57 #endif
58 #ifdef CONFIG_SERVERIP
59 "serverip=" __stringify(CONFIG_SERVERIP) "\0"
60 #endif
61 #ifdef CONFIG_SYS_AUTOLOAD
62 "autoload=" CONFIG_SYS_AUTOLOAD "\0"
63 #endif
64 #ifdef CONFIG_PREBOOT
65 "preboot=" CONFIG_PREBOOT "\0"
66 #endif
67 #ifdef CONFIG_ROOTPATH
68 "rootpath=" CONFIG_ROOTPATH "\0"
69 #endif
70 #ifdef CONFIG_GATEWAYIP
71 "gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0"
72 #endif
73 #ifdef CONFIG_NETMASK
74 "netmask=" __stringify(CONFIG_NETMASK) "\0"
75 #endif
76 #ifdef CONFIG_HOSTNAME
77 "hostname=" __stringify(CONFIG_HOSTNAME) "\0"
78 #endif
79 #ifdef CONFIG_BOOTFILE
80 "bootfile=" CONFIG_BOOTFILE "\0"
81 #endif
82 #ifdef CONFIG_LOADADDR
83 "loadaddr=" __stringify(CONFIG_LOADADDR) "\0"
84 #endif
85 #ifdef CONFIG_CLOCKS_IN_MHZ
86 "clocks_in_mhz=1\0"
87 #endif
88 #if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
89 "pcidelay=" __stringify(CONFIG_PCI_BOOTDELAY)"\0"
90 #endif
91 #ifdef CONFIG_ENV_VARS_UBOOT_CONFIG
92 "arch=" CONFIG_SYS_ARCH "\0"
93 "cpu=" CONFIG_SYS_CPU "\0"
94 "board=" CONFIG_SYS_BOARD "\0"
95 "board_name=" CONFIG_SYS_BOARD "\0"
96 #ifdef CONFIG_SYS_VENDOR
97 "vendor=" CONFIG_SYS_VENDOR "\0"
98 #endif
99 #ifdef CONFIG_SYS_SOC
100 "soc=" CONFIG_SYS_SOC "\0"
101 #endif
102 #endif
103 #ifdef CONFIG_EXTRA_ENV_SETTINGS
104 CONFIG_EXTRA_ENV_SETTINGS
105 #endif
106 "\0"
107 #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
108 }
109 #endif
110 };
第 13~23 行 , 这 段 代 码 是 个 条 件 编 译 , 由 于 没 有 定 义DEFAULT_ENV_INSTANCE_EMBEDDED 和 CONFIG_SYS_REDUNDAND_ENVIRONMENT
因此 uchar default_environment[] 数组保存环境变量。
在示例代码 33.3.1.1 中指定了很多环境变量的默认值,比如 bootcmd 的默认值就是
CONFIG_BOOTCOMMAND bootargs 的默认值就是 CONFIG_BOOTARGS 。我们可以在
mx6ull_alientek_emmc.h 文件中通过设置宏 CONFIG_BOOTCOMMAND 来设置 bootcmd 的默认
值, NXP 官方设置的 CONFIG_BOOTCOMMAND 值如下:
204 #define CONFIG_BOOTCOMMAND \
205 "run findfdt;" \
206 "mmc dev ${mmcdev};" \
207 "mmc dev ${mmcdev}; if mmc rescan; then " \
208 "if run loadbootscript; then " \
209 "run bootscript; " \
210 "else " \
211 "if run loadimage; then " \
212 "run mmcboot; " \
213 "else run netboot; " \
214 "fi; " \
215 "fi; " \
216 "else run netboot; fi"
205 行, run findfdt ;使用的是 uboot run 命令来运行 findfdt findfdt NXP 自行添加
的环境变量。 findfdt 是用来查找开发板对应的设备树文件 (.dtb) IMX6ULL EVK 的设备树文件
imx6ull-14x14-evk.dtb findfdt 内容如下:
"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" \
findfdt 里面用到的变量有 fdt_file board_name board_rev ,这三个变量内容如下:
fdt_file=undefined board_name=EVK board_rev=14X14
findfdt 做的事情就是判断, fdt_file 是否为 undefined ,如果 fdt_file undefined 的话那就要
根据板子信息得出所需的 .dtb 文件名。此时 fdt_file undefined ,所以根据 board_name
board_rev 来判断实际所需的 .dtb 文件,如果 board_name EVK 并且 board_rev=9x9 的话 fdt_file
就为 imx6ull-9x9-evk.dtb 。如果 board_name EVK 并且 board_rev=14x14 的话 fdt_file 就设置
imx6ull-14x14-evk.dtb 。因此 IMX6ULL EVK 板子的设备树文件就是 imx6ull-14x14-evk.dtb
因此 run findfdt 的结果就是设置 fdt_file imx6ull-14x14-evk.dtb
206 行, mmc dev ${mmcdev} 用于切换 mmc 设备, mmcdev 1 ,因此这行代码就是: mmc
dev 1 ,也就是切换到 EMMC 上。
207 行,先执行 mmc dev ${mmcdev} 切换到 EMMC 上,然后使用命令 mmc rescan 扫描
看有没有 SD 卡或者 EMMC 存在,如果没有的话就直接跳到 216 行,执行 run netboot netboot
也是一个自定义的环境变量,这个变量是从网络启动 Linux 的。如果 mmc 设备存在的话就从
mmc 设备启动。
208 行,运行 loadbootscript 环境变量,此环境变量内容如下:
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};

其中 mmcdev=1mmcpart=1loadaddr=0x80800000script= boot.scr,因此展开以后就是:

loadbootscript=fatload mmc 1:1 0x80800000 boot.scr; 

loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src DRAM 0X80800000 处。但
mmc1 的分区 1 中没有 boot.src 这个文件,可以使用命令“ ls mmc 1:1 ”查看一下 mmc1 分区
1 中的所有文件,看看有没有 boot.src 这个文件。
209 行,如果加载 boot.src 文件成功的话就运行 bootscript 环境变量, bootscript 的内容如
下:
bootscript=echo Running bootscript from mmc ...;
source

 

因为 boot.src 文件不存在,所以 bootscript 也就不会运行。
211 行,如果 loadbootscript 没有找到 boot.src 的话就运行环境变量 loadimage ,环境变量
loadimage 内容如下:
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}

loadimage=fatload mmc 1:1 0x80800000 zImage 

可以看出 loadimage 就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,而 mmc1
的分区 1 中存在 zImage
212 行,加载 linux 镜像文件 zImage 成功以后就运行环境变量 mmcboot ,否则的话运行
netboot 环境变量。 mmcboot 环境变量如下:
154 "mmcboot=echo Booting from mmc ...; " \
155 "run mmcargs; " \
156 "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
157 "if run loadfdt; then " \
158 "bootz ${loadaddr} - ${fdt_addr}; " \
159 "else " \
160 "if test ${boot_fdt} = try; then " \
161 "bootz; " \
162 "else " \
163 "echo WARN: Cannot load the DT; " \
164 "fi; " \
165 "fi; " \
166 "else " \
167 "bootz; " \
168 "fi;\0" \
154 行,输出信息“ Booting from mmc ... ”。
155 行,运行环境变量 mmcargs mmcargs 用来设置 bootargs ,后面分析 bootargs 的时候
在学习。
156 行,判断 boot_fdt 是否为 yes 或者 try ,根据 uboot 输出的环境变量信息可知 boot_fdt=try
因此会执行 157 行的语句。
157 行,运行环境变量 loadfdt ,环境变量 loadfdt 定义如下:
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}

 展开以后就是:

loadfdt=fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb
因此 loadfdt 的作用就是从 mmc1 的分区 1 中读取 imx6ull-14x14-evk.dtb 文件并放到 0x83000000
处。
158 行,如果读取 .dtb 文件成功的话那就调用命令 bootz 启动 linux ,调用方法如下:
bootz ${loadaddr} - ${fdt_addr};

 展开就是:

bootz 0x80800000 - 0x83000000 ( 注意‘ - ’前后要有空格 )
至此 Linux 内核启动,如此复杂的设置就是为了从 EMMC 中读取 zImage 镜像文件和设备
树文件。经过分析,浓缩出来的仅仅是 4 行精华:
mmc dev 1 //切换到 EMMC
fatload mmc 1:1 0x80800000 zImage //读取 zImage 0x80800000
fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb // 读取设备树到 0x83000000
bootz 0x80800000 - 0x83000000 //启动 Linux

 

当我们明确知道我们所使用的板子的时候就可以大幅简化宏
CONFIG_BOOTCOMMAND 的 设 置 , 比 如 我 们 要 从 EMMC 启动,那么宏
CONFIG_BOOTCOMMAND 就可简化为:
#define CONFIG_BOOTCOMMAND \
"mmc dev 1;" \
"fatload mmc 1:1 0x80800000 zImage;" \
"fatload mmc 1:1 0x83000000 imx6ull-alientek-emmc.dtb;" \
"bootz 0x80800000 - 0x83000000;"

或者可以直接在 uboot 中设置 bootcmd 的值,这个值就是保存到 EMMC 中的,命令如下:

setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;'

 

环境变量 bootargs  

bootargs 保存着 uboot 传递给 Linux 内核的参数,在上一小节讲解 bootcmd 的时候说过,
bootargs 环境变量是由 mmcargs 设置的, mmcargs 环境变量如下:
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中 console=ttymxc0 baudrate=115200 mmcroot=/dev/mmcblk1p2 rootwait rw ,因此将
mmcargs 展开以后就是:
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw

 

其中 /dev/mmcblkx(x=0~n) 表示 mmc 设备,而 /dev/mmcblkxpy(x=0~n,y=1~n) 表示 mmc 设备
x 的分区 y 。在 I.MX6U-ALPHA 开发板中 /dev/mmcblk1 表示 EMMC ,而 /dev/mmcblk1p2 表示
EMMC 的分区 2
  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hqb_newfarmer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值