U-Boot移植

U-Boot移植

作为初学者,有必要了解U-Boot是如何添加一块新的开发板。通常需要做什么配置?本文梳理一下U-Boot一般需要添加修改的文件,帮助理解U-Boot移植过程

参考手册: I . M X 6 U 嵌入式 L i n u x 驱动开发指南 V 1.8 \color{red}{I.MX6U嵌入式Linux驱动开发指南V1.8} I.MX6U嵌入式Linux驱动开发指南V1.8
移植过程: N X P i m x 6 u l l − − − > 正点原子 i m x 6 u l l _ a l i e n t e k \color{green}{NXP imx6ull--->正点原子 imx6ull\_alientek} NXPimx6ull>正点原子imx6ull_alientek
开发板: i m x 6 u l l \color{green}{imx6ull} imx6ull

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

U-Boot通常需要添加/修改/配置以下文件

  • 添加开发板默认配置文件
  • 添加开发板对应头文件
  • 添加开发板对应板级文件夹
  • 修改U-Boot图形界面配置文件
  • 重新编译U-Boot
  • 修改LCD驱动
  • 修改网络驱动
  • 修改打印信息

1.1 添加开发板默认配置文件

  • 创建默认配置文件(Configs目录下
cd configs
cp mx6ull_14x14_evk_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

1.2 添加开发板对应头文件

  • 添加头文件(include/configs目录下)
cp include/configs/mx6ullevk.h mx6ull_alientek_emmc.h
  • 修改头文件

将下面头文件

#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H

修改为alientek相关的头文件

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

文件的主要功能就是配置或者裁剪 uboot。如果需
要某个功能的话就在里面添加这个功能对应的CONFIG_XXX 宏即可,如果不需要某个功能的话就删除掉对应的宏即可。

  1. 添加头文件 \color{green}{添加头文件} 添加头文件 mx6_common.h

在 mx6ull_alientek_emmc.h 中没有发现有配置某个功能或命令,可以到 mx6_common.h 文件里面去找一下。

14 #include "mx6_common.h"
  1. 设置 D R A M 的大小 \color{green}{设置DRAM 的大小} 设置DRAM的大小

宏 PHYS_SDRAM_SIZE 就是板子上 DRAM 的大小,如果用的 NXP 官方的 9X9 EVK 开发板的话 DRAM 大小就为 256MB。否则的话默认为 512MB,正点原子的 I.MX6U-ALPHA 开发板用的是 512MB DDR3。

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
  1. 定义宏 CONFIG_DISPLAY_CPUINFO,uboot 启动 输出 C P U 信息 \color{green}{输出 CPU 信息} 输出CPU信息
50 #define CONFIG_DISPLAY_CPUINFO
  1. 定义宏 CONFIG_DISPLAY_BOARDINFO, uboot 启动 输出板子信息 \color{green}{输出板子信息} 输出板子信息
51 #define CONFIG_DISPLAY_BOARDINFO
  1. 设置CONFIG_SYS_MALLOC_LEN m a l l o c 内存池 \color{green}{malloc 内存池} malloc内存池大小:16MB
53 /* Size of malloc() pool */
54 #define CONFIG_SYS_MALLOC_LEN (16 * SZ_1M)
  1. 定义宏 CONFIG_BOARD_EARLY_INIT_F,这样 board_init_f 函数就会 调用 b o a r d _ e a r l y _ i n i t _ f 函数 \color{green}{调用board\_early\_init\_f 函数} 调用board_early_init_f函数
56 #define CONFIG_BOARD_EARLY_INIT_F
  1. 定义宏 CONFIG_BOARD_LATE_INIT,这样 board_init_r 函数就会 调用 b o a r d _ l a t e _ i n i t 函数 \color{green}{调用board\_late\_init 函数} 调用board_late_init函数
57 #define CONFIG_BOARD_LATE_INIT
  1. 使能 I . M X 6 U L L 的串口功能 \color{green}{使能 I.MX6ULL 的串口功能} 使能I.MX6ULL的串口功能
59 #define CONFIG_MXC_UART
60 #define CONFIG_MXC_UART_BASE UART1_BASE

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 # UART1 的寄存器基地址正是 0X02020000
  1. E M M C 接在 U S D H C 2 上 \color{green}{EMMC接在USDHC2上} EMMC接在USDHC2

CONFIG_SYS_FSL_ESDHC_ADDR为 EMMC 所使用接口的寄存器基地址,也就是 USDHC2 的基地址

63 #ifdef CONFIG_FSL_USDHC
64 #define CONFIG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR
  1. N A N D 相关的宏 \color{green}{ NAND 相关的宏} NAND相关的宏

NAND 和 USDHC2 的引脚冲突,因此如果使用NAND 的只能使用一个 USDHC 设备(SD 卡)。如果没有使用 NAND,那么就有两个 USDHC 设备(EMMC 和 SD 卡),宏 CONFIG_SYS_FSL_USDHC_NUM 表示 USDHC 数量。 EMMC 版本的核心版没有用到 NAND,所以 CONFIG_SYS_FSL_USDHC_NUM=2

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
  1. I 2 C 有关的宏定义 \color{green}{ I2C 有关的宏定义} I2C有关的宏定义。用于控制使能哪个 I2C及设置I2C 速度。
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
  1. N A N D 的分区设置 \color{green}{ NAND 的分区设置} NAND的分区设置
92 #ifdef CONFIG_SYS_BOOT_NAND
93 #define CONFIG_MFG_NAND_PARTITION "mtdparts=gpminand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "
94 #else
95 #define CONFIG_MFG_NAND_PARTITION ""
96 #endif

如果使用 NAND 的话,默认的 NAND 分区为:"mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) ",分区结果如下表所示:

范围 大小 分区
0~63M 64M boot(uboot)
64~79M 16M kernel(linux 内核)
80~94M 16M dtb(设备树)
95M 1M misc(杂项)
96M – end 剩余的所有空间 rootfs(根文件系统)

注: N A N D 的分区是可以调整的,如 b o o t 分区用不了 64 M 可以将其改小,其他的分区亦如此。 \color{red}{NAND 的分区是可以调整的,如 boot 分区用不了64M 可以将其改小,其他的分区亦如此。} NAND的分区是可以调整的,如boot分区用不了64M可以将其改小,其他的分区亦如此。

  1. CONFIG_MFG_ENV_SETTINGS 定义一些环境变量 \color{green}{ 定义一些环境变量} 定义一些环境变量,使用 MfgTool 烧写系统时候会用到这里面的环境变量。
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" \
  1. 通 过 条 件 编 译 来 设置宏 C O N F I G _ E X T R A _ E N V _ S E T T I N G S \color{green}{ 设置宏CONFIG\_EXTRA\_ENV\_SETTINGS } 设置宏CONFIG_EXTRA_ENV_SETTINGS , 宏CONFIG_EXTRA_ENV_SETTINGS 也是\设置一些环境变量,此宏会设置 bootargs 环境变量
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" \
  1. 设置宏 C O N F I G _ B O O T C O M M A N D \color{green}{ 设置宏 CONFIG\_BOOTCOMMAND} 设置宏CONFIG_BOOTCOMMAND,此宏就是设置环境变量 bootcmd 的值。
204 #define CONFIG_BOOTCOMMAND \
205 "run findfdt;" \
......
216 "else run netboot; fi"
217 #endif
  1. 设置命令 m e m t e s t 相关宏定义 \color{green}{ 设置命令 memtest 相关宏定义} 设置命令memtest相关宏定义。比如使能命令 memtest,设置 memtest 测试的内存起始地址和内存大小。
220 #define CONFIG_CMD_MEMTEST
221 #define CONFIG_SYS_MEMTEST_START 0x80000000
222 #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x8000000)
  1. 定义宏 C O N F I G _ S Y S _ L O A D _ A D D R \color{green}{ 定义宏 CONFIG\_SYS\_LOAD\_ADDR} 定义宏CONFIG_SYS_LOAD_ADDR 。该宏表示 linux kernel 在 DRAM 中的加载地址,即linux kernel 在 DRAM 中的存储首地址CONFIG_LOADADDR=0X80800000
224 #define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
  1. 定义系统时钟频率 \color{green}{ 定义系统时钟频率} 定义系统时钟频率 :1000Hz。
225 #define CONFIG_SYS_HZ 1000
  1. 定义栈大小 \color{green}{定义栈大小} 定义栈大小 : 128KB。
227 #define CONFIG_STACKSIZE SZ_128K
  1. 定义物理内存映射 P h y s i c a l M e m o r y M a p \color{green}{定义物理内存映射Physical Memory Map} 定义物理内存映射PhysicalMemoryMap
230 #define CONFIG_NR_DRAM_BANKS 1 //定义DRAM BANK 的数量。 I.MX6ULL 只有一个 DRAM BANK,也只用到一个 BANK,所以为 1
231 #define PHYS_SDRAM MMDC0_ARB_BASE_ADDR //宏 PHYS_SDRAM 为 I.MX6ULL 的 DRAM 控制器 MMDC0 所管辖的 DRAM 范
围起始地址,也就是 0X80000000232
233 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM //宏 CONFIG_SYS_SDRAM_BASE 为 DRAM 的起始地址。
234 #define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR //宏 CONFIG_SYS_INIT_RAM_ADDR 为 I.MX6ULL 内部 IRAM 的起始地址(也就是 OCRAM 的起始地址),为 0X00900000。
235 #define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE // 宏 CONFIG_SYS_INIT_RAM_SIZE 为 I.MX6ULL 内部 IRAM 的大小(OCRAM的大小),为 0X00040000=128KB。
236
// 宏 CONFIG_SYS_INIT_SP_OFFSET 和 CONFIG_SYS_INIT_SP_ADDR 与初始 SP 有关,第一个为初始 SP 偏移,第二个为初始 SP 地址。
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)
  1. F L A S H 和环境配置 \color{green}{FLASH和环境配置} FLASH和环境配置
256 #define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */ //宏CONFIG_SYS_MMC_ENV_DEV为默认的MMC设备,这里默认为USDHC2,也就是 EMMC
257 #define CONFIG_SYS_MMC_ENV_PART 0 /* user area */ //宏 CONFIG_SYS_MMC_ENV_PART 为模式分区,默认为第 0 个分区
//宏 CONFIG_MMCROOT 设置进入 linux 系统的根文件系统所在的分区,这里设置为"/dev/mmcblk1p2",也就是 EMMC 设备的第 2 个分区。
//第 0 个分区保存 uboot,第 1 个分区保存 linux 镜像和设备树,第 2 个分区为 Linux 系统的根文件系统。
258 #define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */ 

  1. N A N D 配置 \color{green}{NAND配置} NAND配置。与 NAND 有关的宏定义,如果使用 NAND 的话。
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
  1. 设置环境变量大小 \color{green}{设置环境变量大小} 设置环境变量大小:默认为 8KB。
293 #define CONFIG_ENV_SIZE SZ_8K

24. 设置环境变量偏移地址 \color{green}{设置环境变量偏移地址} 设置环境变量偏移地址
这里的偏移地址是相对于存储器的首地址。如果环境变量保存在 EMMC 中的话,环境变量偏移地址为 1264KB。如
果环境变量保存在 SPI FLASH 中的话,偏移地址为 768
1024。如果环境变量保存在 NAND 中的话,偏移地址为 60<<20(60MB),并且重新设置环境变量的大小为 128KB。

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

24. U S B 相关的宏定义 \color{green}{USB 相关的宏定义} USB相关的宏定义

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

25. 网络相关的宏定义 \color{green}{网络相关的宏定义} 网络相关的宏定义,比如使能 dhcp、 ping 等命令

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 //指定 uboot 所使用的网口。 I.MX6ULL 有两个网口,为 0 的时候使用 ENET1,为 1 的时候使用 ENET2
332
333 #if (CONFIG_FEC_ENET_DEV == 0)
334 #define IMX_FEC_BASE ENET_BASE_ADDR // IMX_FEC_BASE 为 ENET 接口的寄存器首地址
335 #define CONFIG_FEC_MXC_PHYADDR 0x2 // CONFIG_FEC_MXC_PHYADDR 为网口 PHY 芯片的地址
336 #define CONFIG_FEC_XCV_TYPE RMII // CONFIG_FEC_XCV_TYPE 为PHY 芯片所使用的接口类型,I.MX6U-ALPHA 开发板的两个 PHY 都使用的 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"

26. 配置宏 \color{green}{配置宏} 配置宏

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 // 宏用于开启 LCD
352 #ifdef CONFIG_VIDEO
353 #define CONFIG_CFB_CONSOLE
354 #define CONFIG_VIDEO_MXS
355 #define CONFIG_VIDEO_LOGO // 使能 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 // 使能 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

CONFIG_CMD 开头的宏都是用于使能相应命令的,其他的以 CONFIG 开头的宏都是完成一些配置功能

1.3 添加开发板对应板级文件夹

  • 创建默认配置文件(board/freescale
cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc
cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc.c
  • 修改配置信息
  1. 修改mx6ull_alientek_emmc 目录下的 Makefile 文件
6 obj-y := mx6ull_alientek_emmc.o
  1. 修改 mx6ull_alientek_emmc 目录下的 imximage.cfg 文件
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

修改为

PLUGIN board/freescale/mx6ull_alientek_emmc /plugin.bin 0x00907000
  1. 修改 mx6ull_alientek_emmc 目录下的 Kconfig 文件
1 if TARGET_MX6ULL_ALIENTEK_EMMC
2 
3 config SYS_BOARD
4 default "mx6ull_alientek_emmc"
5 
6 config SYS_VENDOR
7 default "freescale"
8 
9 config SYS_SOC
10 default "mx6"
11
12 config SYS_CONFIG_NAME
13 default "mx6ull_alientek_emmc"
14
15 endif
  1. 修改 mx6ull_alientek_emmc 目录下的 MAINTAINERS 文件
1 MX6ULL_ALIENTEK_EMMC BOARD
2 M: Peng Fan <peng.fan@nxp.com>
3 S: Maintained
4 F: board/freescale/mx6ull_alientek_emmc/
5 F: include/configs/mx6ull_alientek_emmc.h

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

修改文件arch/arm/cpu/armv7/mx6/Kconfig,在207行加入如下内容:

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"

1.5 重新编译U-Boot

  1. 新建 s h e l l 脚本 \color{green}{新建shell脚本} 新建shell脚本mx6ull_alientek_emmc.sh
#!/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
  1. 修改权限并运行脚本 \color{green}{修改权限并运行脚本} 修改权限并运行脚本
chmod 777 mx6ull_alientek_emmc.sh //给予可执行权限,一次即可
./mx6ull_alientek_emmc.sh //运行脚本编译 uboot
  1. 查看头文件是否被引用 \color{green}{查看头文件是否被引用} 查看头文件是否被引用
grep -nR "mx6ull_alientek_emmc.h"

如果打印很多信息则说明板子添加成功。

1.6 修改LCD驱动

一般 uboot 中修改驱动基本是在 xxx.h 和 xxx.c 这两个文件中进行的,其中 xxx 为板子名称。并且LCD驱动修改需要注意以下三点:

  • L C D 所使用的 G P I O ,查看 u b o o t 中 L C D 的 I O 配置是否正确 \color{red}{LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确} LCD所使用的GPIO,查看ubootLCDIO配置是否正确
  • L C D 背光引脚 G P I O 的配置 \color{red}{LCD 背光引脚 GPIO 的配置} LCD背光引脚GPIO的配置
  • L C D 配置参数是否正确 \color{red}{LCD 配置参数是否正确} LCD配置参数是否正确

注:正点原子的开发板与NXP官方一致,IO与背光IO不用更改。

  1. LCD参数配置

打开文件 mx6ull_alientek_emmc.c,按照下面图片所示做相应修改即可。
U-Boot移植_第1张图片

编译下载重启,如果发现是黑屏,则进入uboot命令模式,输入print查看panel值
如果发现不是TFT7076则更改panel值:

setenv panel TFT7076
saveenv

如果是TFT7076则检查之前修改是否正确

1.7 修改网络驱动

网络驱动修改主要分为以下几步:

  • 网络地址修改
  • 删除uboot中74LV595驱动代码
  • 添加I.MX6U-ALPHA 开发板网络复位引脚驱动
  • 修改 drivers/net/phy/phy.c 文件中的函数 genphy_update_link

1.7.1 PHY:LAN8720A修改方法

I.MX6U-ALPHA 开发板 ENET1 上连接的 LAN8720A器件地址为 0X0,所以修改 ENET1 网络驱动的重点如下:

  • ENET1 复位引脚初始化
  • LAN8720A 的器件 ID:0X0
  • LAN8720 驱动
    U-Boot移植_第2张图片

ENET2 网络驱动的修改也应注意以下几点:

  • ENET2 的复位引脚 ENET2_RST 接到了I.MX6ULL 的 SNVS_TAMPER8 上
  • ENET2 所使用的 PHY 芯片器件地址为 0X1
  • ENET2驱动与ENET2一致
    U-Boot移植_第3张图片
  1. 网络地址修改 \color{green}{网络地址修改} 网络地址修改

打开mx6ull_alientek_emmc.h找到以下文件并作出修改:

  • 修改 ENET1 网络 PHY 的地址。
  • 修改 ENET2 网络 PHY 的地址。
  • 使能 SMSC 公司的 PHY 驱动。
    U-Boot移植_第4张图片
  1. 删除 u b o o t 中 74 L V 595 驱动代码 \color{green}{删除uboot中74LV595驱动代码} 删除uboot74LV595驱动代码

该部分为网络复位引脚驱动修改,打开mx6ull_alientek_emmc.c,找到以下代码:

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

修改为:

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

解释:NXP采用74LV595扩展IO,正点原子没有采用,故直接删除替换。ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07;ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08

删除74LV595 IO配置参数结构体iox_pads,初始化函数iox74lv_init,控制输出电平函数iox74lv_set

static iomux_v3_cfg_t const iox_pads[] = {
......
static void iox74lv_init(void)
......
void iox74lv_set(int index)

找到板子初始化函数 board_init 函数,删除里面关于74LV595芯片驱动代码

imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
iox74lv_init();
  1. I . M X 6 U − A L P H A 开发板网络复位引脚驱动 \color{green}{I.MX6U-ALPHA 开发板网络复位引脚驱动} I.MX6UALPHA开发板网络复位引脚驱动

继续打开mx6ull_alientek_emmc.c 函数

  • 添加网口复位的IO配置参数
    U-Boot移植_第5张图片
  • 添加网络复位IO初始化代码,并且 硬件复位 P H Y 芯片 \color{red}{硬件复位PHY芯片} 硬件复位PHY芯片
    U-Boot移植_第6张图片
  1. 修改 d r i v e r s / n e t / p h y / p h y . c 文件中的函数 g e n p h y _ u p d a t e _ l i n k \color{green}{修改}\color{red} {drivers/net/phy/phy.c }\color{green}{文件中的函数 }\color{red}{genphy\_update\_link} 修改drivers/net/phy/phy.c文件中的函数genphy_update_link

打开phy.c文件,找到genphy_update_link函数,该函数为通用 PHY 驱动函数,用于更新 PHY 的连接状态和速度。在函数里添加如下内容:

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

该段内容为SMSC公司要求添加才能执行

修改完成后,重新编译烧写u-boot.bin文件。进入命令模式,设置环境变量

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

ping主机,完成。

ping 192.168.1.250

1.8 修改打印信息

打开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;
}

重新编译,烧写,完成。

2. bootcmd和bootargs环境变量

2.1 bootcmd环境变量

bootcmd用于保存uboot默认命令,这些命令一般都是用来 启动 L i n u x 内核 \color{red}{启动Linux内核} 启动Linux内核。NXP中bootcmd为CONFIG_BOOTCOMMAND可简化为:

#define CONFIG_BOOTCOMMAND \
"mmc dev 1;" \						//切换到 EMMC
"fatload mmc 1:1 0x80800000 zImage;" \ //读取 zImage 到 0x80800000 处
"fatload mmc 1:1 0x83000000 imx6ull-alientek-emmc.dtb;" \ //读取设备树到 0x83000000 处
"bootz 0x80800000 - 0x83000000;" //启动 Linux

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

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

2.2 bootargs环境变量

bootargs用来 保存 u b o o t 传递给 L i n u x 内核的参数 \color{red}{保存 uboot 传递给 Linux 内核的参数} 保存uboot传递给Linux内核的参数。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

可以看出环境变量 mmcargs 就是设置 bootargs 的值为“console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw”

  • console为控制台 ttymxc0串口1 115200波特率
  • root根文件系统 /dev/mmcblkxpy(x=0~n,y=1~n)表示 mmc 设备x 的分区 y rootwait 表示等待 mmc 设备初始化完成以后再挂载 rw可读写
  • rootfstype用于指定根文件系统类型。ext 格式不需操作, yaffs、 jffs 或 ubifs 格式需要设置此选项,指定根文件系统的类型。

3. U-Boot启动Linux测试

3.1 从EMMC启动Linux测试

进入uboot命令模式,设置bootargs和bootcmd

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

设置好后, 直接进入 b o o t \color{red}{直接进入boot} 直接进入boot或者 r u n \color{red}{run} run b o o t c m d \color{red}{bootcmd} bootcmd即可启动Linux内核

3.2 从网络启动Linux测试

  • tftp挂载zImagedtb设备树
  • 设置 bootargs 和 bootcmd 环境变量
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
saveenv

下载完成后,自己会启动。
至此,U-Boot移植完毕。

uboot的主要目的就是启动 Linux 内核,所以一般需要解决串口、 NAND、 EMMC 或 SD 卡、网络和 LCD 驱动,不需要考虑太多的外设驱动。

你可能感兴趣的:(驱动开发,uboot,嵌入式)