1. NXP官方uboot移植

uboot移植的一般流程:
①在uboot中找到参考的开发平台,一般为原厂开发板(半导体厂商移植好了uboot的开发板)。
②在原厂BSP包的基础上做修改将uboot移植到自己的开发板。

1.1 NXP官方uboot编译烧写测试

①编译:

./mx6ull_14x14_evk_emmc.sh

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维


②烧写:

&emap; 这里第一次烧写完如下图所示有一个unsupported,是因为之前烧录uboot配置的环境变量没有清除,需要格式化SD卡之后重新进行烧录,处理完之后如下下图所示。

./imxdownload u-boot.bin /dev/sdb

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_linux_02


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_服务器_03

③检测:

//检查SD卡和EMMC驱动
mmc list
mmc dev 0
mmc info
mmc dev 1
mmc info

//LCD驱动检测
分辨率不一致,需要修改

//网络驱动
正点原子的网络芯片复位引脚和NXP官方板不一样

1.2 在uboot中添加自己的开发板

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

&emap; mx6ull_14x14_evk_emmc_defconfig修改为mx6ull_alientek_emmc_defconfig修改mx6ull_alientek_emmc_defconfig,它的第一行和第四行改为:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_开发板_04


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_05

1.2.2 添加开发板对应的头文件

  修改自include/configs/mx6ullevk.h。mx6ull_alientek_emmc.h包含很多宏定义,用于配置uboot和IMX6ULL,可以在这里使能或禁止uboot的功能。在文件代码中打上了注释,该文件中CONFIG开头的宏都是完成一些配置功能,CONFIG_CMD开头的用于使能相应命令。

  文件修改如下:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_06

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

  NXP官方的IMX6ULL EVK开发板板级文件夹为board/freescale/mx6ullevk。
  将该文件夹拷贝一份重命名为mx6ull_alientek_emmc,将其中mx6ullevk.c重命名为mx6ull_alientek_emmc.c。
然后修改makefile:

obj-y := mx6ull_alientek_emmc.o         #为了编译mx6ull_alientek_emmc.c

修改imximage.cfg:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_07


修改Kconfig:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_linux_08


修改MAINTAINERS:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_服务器_09

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

修改arch/arm/cpu/armv7/mx6/Kconfig:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_10


这样,IMX6ULL-ALPHA开发板就添加到了uboot中,接下来进行编译即可。

1.3 LCD驱动修改

  一般在mx6ull_alientek_emmc.h和.c对驱动进行修改。LCD驱动修改重点在于:①GPIO配置;②背光引脚GPIO配置;③配置参数是否准确。

  正点原子的IO设置和NXP官方一样,所以修改参数即可,在.c中找到下图代码段,其中定义了一个结构体变量displays,对应结构体定义中包括了LCD分辨率,像素格式和其他参数,其中还包括一个结构体成员变量mode,对应结构体fb_videomode包含的是LCD参数。

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_11


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_12


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_13


  这里需要注意pixclock(像素时钟)参数,以ATK7016的LCD为例,要求像素时钟为51.2MHz,那么pixclock=(1/51200000)*10^12=19531。ATK7016参数如下:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_14


修改完后uboot启动信息中显示ATK7016,LCD上也会出现MXP的图案:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_开发板_15

1.4 网络驱动修改

  正点原子的ENET网络接口使用的PHY芯片是SR8201F,不是NXP的KSZ8081,所以需要修改网络驱动。我的开发板上ENET1上连接的SR8201F器件地址为0X2,所以修改ENET1网络驱动重点为:①复位引脚初始化;②SR8201F器件ID;③SR8201F驱动。修改ENET2网络驱动的重点则是:①复位引脚;②ENET2的PHY芯片地址,0X1;③SR8201F驱动。

1.4.1 网络PHY地址和PHY驱动修改

ENET1和2的地址和NXP一样,不用改,SR8201F是替换的RTL8201F(REALTEK公司生产),所以345行要改为下图所示代码:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_开发板_16

1.4.2 删除uboot中74LV595的驱动代码

#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)

  NXP官方的IMX6ULL EVK开发板使用74LV595来扩展IO,控制两个ENET的复位引脚,上图中IOX开头的宏就是74LV595的相关GPIO。正点原子的开发板没使用74LV595,所以将上述代码修改为:

#define ENET1_RESET IMX_GPIO_NR(5, 7)              /*ENET1复位引脚在SNVS_TAMPER7,对应GPIO5_IO07*/
#define ENET2_RESET IMX_GPIO_NR(5, 8)              /*ENET2复位引脚在SNVS_TAMPER8,对应GPIO5_IO08*/

  然后找到static iomux_v3_cfg_t const iox_pads[] = {},这是74LV595的IO配置参数结构体,直接删除。找到static void iox74lv_init(void),是74LV595的初始化函数,将其和iox74lv_set一起删除。
  最后找到board_init,将其中对74lv595的IO初始化函数imx_iomux_v3_setup_multiple_pads和iox74lv_init的调用删除。

1.4.3 添加网络复位引脚驱动

  找到fec1_pads和fec2_pads,这两个结构体数组是ENET1和2的IO配置参数,在其中添加两个网口的复位IO配置参数。然后找到setup_iomux_fec,这是根据前两个结构体数组来初始化6ULL的网络IO,在其中添加网络复位IO的初始化代码并复位PHY芯片。

static void setup_iomux_fec(int fec_id)
{
	if (fec_id == 0)
 	{
		imx_iomux_v3_setup_multiple_pads(fec1_pads,
			ARRAY_SIZE(fec1_pads));
		/*复位IO初始化,将IO设置为输出并硬件复位LAN8720A*/
		gpio_direction_output(ENET1_RESET, 1);
		gpio_set_value(ENET1_RESET, 0);
		mdelay(20);
		gpio_set_value(ENET1_RESET, 1);
	}
	else
	{
		imx_iomux_v3_setup_multiple_pads(fec2_pads,
			ARRAY_SIZE(fec2_pads));
		gpio_direction_output(ENET2_RESET, 1);
		gpio_set_value(ENET2_RESET, 0);
		mdelay(20);
		gpio_set_value(ENET2_RESET, 1);
	}
	mdelay(150); /* 复位结束后至少延时 150ms 才能正常使用,否则无法识别SR8201F*/
}
1.4.3.1 测试ENET2

设置一下环境变量:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_17


ping一下:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_开发板_18

1.4.3.2 测试ENET1

将.h中的CONFIG_FEC_ENET_DEV改为0X0,ping一下:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_linux_19

最终的uboot启动信息:

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_20

2. uboot移植测试

  uboot是为了启动linux内核,所以,通过启动linx内核可以判断uboot移植成功与否。

2.1 bootcmd环境变量

  保存uboot默认命令的环境变量,在uboot倒计时结束后执行bootcmd中的命令,一般是用于启动linux内核的。可以在uboot启动后在命令行对bootcmd的值进行设置,否则使用默认环境变量(include/env_default.h)。通过设置宏CONFIG_BOOTCOMMAND可以设置bootcmd。

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_21


  run findfdt:findfdt是NXP添加的环境变量,用于查找开发板对应的设备树文件,内容如下,其中变量fdt_file是undefined就根据board_name和board_rev得出所需设备树文件名。这句代码最后结果就是设置fdt_file=imx6ull-14x14-evk.dtb。

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_开发板_22


代码流程解读

  mmc dev用于切换mmc设备,此时mmcdev值为1,所以是mmc dev 1也就是切换为EMMC。然后使用mmc resacn扫描是否有SD或者EMMC存在,没有就跳到run netboot从网络启动linux,存在就从mmc设备启动。

  loadbootscript环境变量,内容如下,作用是从mmc1的分区1中读取文件boot.src到DRAM的0X80800000处:

loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
/*其中mmcdev=1,mmcpart=1,loadaddr=0X80800000,script=boot.scr*/
/*展开:loadbootscript=fatload mmc 1:1 0x80800000 boot.src;*/

  如果加载boot.src成功,就运行bootscript环境变量,如果不存在,就运行环境变量loadimage。loadimage如下,其功能是从mmc1的分区中读取zImage到DRAM的0X80800000:

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
/*展开:*/
loadimage=fatload mmc 1:1 0x80800000 zImage

  加载zImage成功后运行mmcboot,否则运行netboot。mmcboot中调用到了环境变量mmcargs和loadfdt,前者用于设置bootargs,后者用于从mmc1的分区1中读取设备树文件到DRAM的0X83000000
  读取dtb文件成功,调用命令bootz启动linux,最后实际调用其实就是以下代码:

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

  NXP将CONFIG_BOOTCOMMAND写的这么复杂是为了兼容多个板子,我们明确使用一个板子的时候可以将宏简化为以下形式,也可以在uboot中设置bootcmd的值并保存环境变量:

#define CONFIG_BOOTCOMMAND \
 	"mmc dev 1;" \
 	"fatload mmc 1:1 0x80800000 zImage;" \
 	"fatload mmc 1:1 0x83000000 imx6ull-alientek-emmc.dtb;" \
 	"bootz 0x80800000 - 0x83000000;"

2.2 bootargs环境变量

bootargs保存uboot传给linux内核的参数,由mmcargs进行设置,mmcargs环境变量如下:

mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
/*展开*/
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw

常用参数:
①console:设置linux终端,也就是选择什么设备进行和linux的交互,一般选择串口。linux启动后6ull的串口1在linux下的设备文件时/dev/ttymxc0,所以设置console=ttymxc0,115200是串口波特率。
②root:设置根文件系统的位置。这里root= /dev/mmcblk1p2指明根文件系统存放在mmcblk1(EMMC)设备的分区2.mmcblkX表示mmc设备,mmcblkXpY表示mmc设备X的分区Y。“rootwait rw”表示等mmc设备初始化完成再进行挂载,并且根文件系统允许读写。
③rootfstype:指定根文件系统类型,如果根文件系统是ext格式可以忽略。

2.3 启动linux

  前面其实已经试过了,只不过当时用的是正点原子改好的uboot。

2.3.1 EMMC启动linux

  我们还没有移植linux和设备树文件,正点原子已经把zImage和设备树文件烧写到了EMMC里面,先拿来直接用。首先用“ls mmc 1:1”,检查一下zImage和dtb都存在。

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-14x14-emmc-e7-1024x600-c.dtb; bootz 80800000 - 83000000;'

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_23

2.3.2 网络启动linux

  调试linux和驱动的时候每次都烧写到固件太麻烦,所以可以用网络调试。

uboot下有没有强制擦除eMMC的命令 uboot移植emmc_运维_24


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_服务器_25


uboot下有没有强制擦除eMMC的命令 uboot移植emmc_环境变量_26