U-Boot 移植深入

1. 在U-Boot中驱动LCD和网络

U-Boot 移植初探一文中介绍了如何修改官方uboot,使得 uboot能匹配我们自己的开发板,但是匹配完成后 LCD驱动和网络驱动还是不正常的,所以下面将介绍如何修改 LCD驱动和网络驱动等

1.1 LCD驱动修改

uboot 中修改驱动都是在对应板子的 .c文件和 .h文件中进行,即下面两个文件中:mx6ull_andyxi_emmc.cmx6ull_andyxi_emmc.h

修改 LCD驱动重点注意以下几点:

  • LCD的 IO配置是否正确
  • LCD背光引脚 GPIO的配置
  • LCD配置参数是否正确

我们使用的 I.MX6ULL开发板的 LCD原理图和 NXP官方的开发板一致,也就是LCD的IO和背光IO都是一样的, 所以IO部分就不用修改了,只需修改 LCD配置参数即可

⏩ mx6ull_andyxi_emmc.c 文件中修改下面内容:

/*######### 原始内容 ###############################*/
/*该代码定义了一个变量displays,类型为display_info_t,这个结构体
是LCD信息结构体,其中包括了LCD的分辨率,像素格式,LCD的各个参数等*/
struct display_info_t const displays[] = {
    
    
	{
    
    
    	.bus = MX6UL_LCDIF1_BASE_ADDR,
    	.addr = 0,
    	.pixfmt = 24,
    	.detect = NULL,
   	 	.enable = do_enable_parallel_lcd,
    	.mode = {
    
    
			.name	      = "TFT43AB",
			.xres         = 480,
			.yres         = 272,
			.pixclock     = 108695,
			.left_margin  = 8,
			.right_margin = 4,
			.upper_margin = 2,
			.lower_margin = 4,
			.hsync_len    = 41,
			.vsync_len    = 10,
			.sync         = 0,
			.vmode        = FB_VMODE_NONINTERLACED
		}
	}
};
/*######### 修改后的内容 ###########################*/
struct display_info_t const displays[] = {
    
    
	{
    
    
    	.bus = MX6UL_LCDIF1_BASE_ADDR,
   	 	.addr = 0,
    	.pixfmt = 24,
    	.detect = NULL,
    	.enable = do_enable_parallel_lcd,
    	.mode = {
    
    
			.name	      = "TFT7016",
			.xres         = 1024,
			.yres         = 600,
			.pixclock     = 19531,
			.left_margin  = 140,  //HBPD
			.right_margin = 160,  //HFPD
			.upper_margin = 20,  //VBPD
			.lower_margin = 12,  //VFPD
			.hsync_len    = 20,   //HSPW
			.vsync_len    = 3,   //VSPW
			.sync         = 0,
			.vmode        = FB_VMODE_NONINTERLACED
		} 
	} 
};

⏩ mx6ull_andyxi_emmc.h 文件中修改 panel值

panel=TFT7016    #根据具体使用型号修改

⏩ 重新编译 uboot并烧写到 SD中启动后,若 LCD仍不能显示,则需要在uboot命令模式下,检查环境变量 panel的值,确保与 LCD参数里的 name一致

panel=TFT7016    #与mx6ull_andyxi_emmc.c中修改的名称保持一致

1.2 网络驱动修改

I.MX6UL/ULL 内部有个以太网 MAC外设,需要外接一个 PHY芯片来实现网络通信功能。我们使用的 I.MX6U 开发板提供了这两个网络接口,都使用 LAN8720A 作为 PHY 芯片。NXP 官方的I.MX6ULL EVK 开发板使用 KSZ8081 的 PHY 芯片。下面将介绍更换了PHY 芯片以后如何调整网络驱动,使网络工作正常。

开发板 ENET1/ENET2的原理图如下示:

在这里插入图片描述

网络 PHY芯片LAN8720A,通过 RMII接口与 I.MX6ULL相连,引脚与 NXP官方的 I.MX6ULL EVK 开发板基本一样,只是复位引脚不同。从上图可以看出,复位引脚ENET1_RST 接到了 I.M6ULL 的 SNVS_TAMPER7 引脚上,复位引脚 ENET2_RST 接到了 SNVS_TAMPER8 引脚上

修改网络驱动重点注意以下几点:

  • LAN8720A复位引脚初始化
  • LAN8720A的器件ID
  • LAN8720A驱动

⏩ 在 mx6ull_andyxi_emmc.c中添加复位引脚驱动

/* 结构体数组fec1_pads和fec2_pads是ENET1和ENET2这两个网口的IO 
 * 配置参数,在这两个数组中添加两个网口的复位 IO 配置参数 */
/*######### 原始内容 ###############################*/
static iomux_v3_cfg_t const fec1_pads[] = {
    
    
  MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
  MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  ......
  MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
};

static iomux_v3_cfg_t const fec2_pads[] = {
    
    
  MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
  MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  ......
  MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
/*######### 修改后的内容 ###########################*/
static iomux_v3_cfg_t const fec1_pads[] = {
    
    
  MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
  MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  ......
  MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL), //添加此行
};

static iomux_v3_cfg_t const fec2_pads[] = {
    
    
  MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),
  MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  ......
  MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL),
  MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL), //添加此行
};

/* 函数 setup_iomux_fec 就是根据 fec1_pads 和 fec2_pads 这两个网络IO配置
   数组来初始化I.MX6ULL的网络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));
  else
    imx_iomux_v3_setup_multiple_pads(fec2_pads,	ARRAY_SIZE(fec2_pads));
}
/*######### 修改后的内容 ###########################*/
static void setup_iomux_fec(int fec_id)
{
    
    
  if (fec_id == 0)
  {
    
    
    imx_iomux_v3_setup_multiple_pads(fec1_pads,ARRAY_SIZE(fec1_pads));
    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);
  }
}

⏩ 在 mx6ull_andyxi_emmc.h中修改 PHY器件地址及驱动

/*######### 原始内容 ###############################*/
#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  //用于选择使用哪个网卡,默认为1(ENET2)
#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR 0x2  //ENET1的PHY地址,默认为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  //ENET2的PHY地址,默认为0x1
#define CONFIG_FEC_XCV_TYPE RMII
#endif
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_PHYLIB
#define CONFIG_PHY_MICREL  //用于使能Micrel公司的PHY驱动(KSZ8081芯片)
#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 0x0  //修改ENET1的PHY地址为0x0
#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  //修改ENET2的PHY地址为为0x1
#define CONFIG_FEC_XCV_TYPE RMII
#endif
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_PHYLIB
#define CONFIG_PHY_SMSC	 //使能SMSC公司的PHY驱动(LAN8720A是SMSC生产的)
#endif

⏩ 在 mx6ull_andyxi_emmc.c中删除 74LV595的驱动代码

/* NXP 官方I.MX6ULL EVK 开发板使用74LV595来扩展 IO,两个网络的复位引脚
 * 就是由74LV595来控制的,I.MX6U-ALPHA开发板并没有使用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)
/*##### 修改后的内容:以上四行替换为以下两行 #######*/
/* ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07
 * ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08
 */
#define ENET1_RESET IMX_GPIO_NR(5, 7)
#define ENET2_RESET IMX_GPIO_NR(5, 8)

//删除74LV595的IO配置参数结构体
/*######### 删除以下内容 ###############################*/
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),
};

//删除74LV595的初始化函数
/*######### 删除以下内容 ###############################*/
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);
};

//删除iox74lv_set函数(用于控制74LV595的IO输出电平)
/*######### 删除以下内容 ###############################*/
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);
};

/* 删除板子初始化函数 board_init 中的74lv595 的GPIO初始化代码 */
/*######### 删除部分代码 ###############################*/
int board_init(void)
{
    
    
  ......
  imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));//删除此行 
  iox74lv_init();  //删除此行
  ......
  return 0;
}

⏩ 在drivers/net/phy/phy.c 中的 genphy_update_link函数里,添加 SMSC的 PHY芯片条件编译代码段

/*######### 修改后的内容 ###########################*/
int genphy_update_link(struct phy_device *phydev){
    
    
  unsigned int mii_reg;
//以下为添加的SMSC的PHY芯片条件编译代码段,只有使用SMSC的PHY才会执行
#ifdef CONFIG_PHY_SMSC
  static int lan8720_flag = 0;
  int bmcr_reg = 0;
  if (lan8720_flag == 0) {
    
    
    bmcr_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
    phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
    while(phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR) & 0X8000) {
    
    
      udelay(100);
    }	
    phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr_reg);
    lan8720_flag = 1;
  }
#endif

  mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
  ......
  return 0;
}

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

在这里插入图片描述

由上图可见当前使用FEC1这个网口(ENET2),但此时网络地址还没有设置。在uboot使用网络之前还要先设置以下几个网络环境变量

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

设置好环境变量以后就可以在 uboot 中使用网络了,用网线将开发板上的 ENET2与电脑连接起来,保证开发板和电脑在同一个网段内,通过 ping 命令来测试网络连接,命令如下:

ping 192.168.1.100

结果如下图示,说明ping 主机成功,至此说明ENET2网络工作正常

在这里插入图片描述

将 mx6ull_andyxi_emmc.h中的CONFIG_FEC_ENET_DEV参数改为 0,然后重新编译 uboot 并烧写到 SD 卡中重启,按以上步骤可以测试 ENET1 的网络是否正常工作

1.3 其他修改

在 uboot启动信息中会有“Board: MX6ULL 14x14 EVK”这一句,即板子名字为“ MX6ULL 14x14 EVK”,可将其改为我们自已的名字“ MX6ULL ANDYXI EMMC”

⏩ 在mx6ull_andyxi_emmc.c中的checkboard函数里,做如下修改

/*######### 修改后的内容 ###########################*/
int checkboard(void)
{
    
    
  if (is_mx6ull_9x9_evk())
    puts("Board: MX6ULL 9x9 EVK\n");
  else
    puts("Board: MX6ULL ANDYXI EMMC\n");
  return 0;
}

修改完成以后重新编译 uboot 并烧写到 SD 卡中验证,uboot 启动信息如下图,可见名字已经修改过来了

在这里插入图片描述

2. bootcmd和bootargs环境变量

uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs,是采用类似 shell 脚本语言编写的,里面有很多 NXP自己定义的的环境变量引用
文件 mx6ull_andyxi_emmc.h中的宏CONFIG_EXTRA_ENV_SETTINGS保存着这些环境变量的默认值,其内容如下:

#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" \
  ......
  "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" \
  ......
  "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" \

2.1 bootcmd环境变量

bootcmd 保存着 uboot 默认命令, uboot 倒计时结束后就会执行其中的命令。一般是用来启动内核的,比如读取 EMMC或 NAND Flash中的内核镜像文件和设备树文件到 DRAM中,然后启动内核

可在 uboot启动后进入命令行设置 bootcmd环境变量的值。如果 EMMC或者 NAND中没有保存 bootcmd的值,那么 uboot就会使用默认值,板子第一次运行 uboot 时都会使用默认值来设置 bootcmd 环境变量

打开文件 include/env_default.h,在此文件中有如下所示内容:

......
#ifdef CONFIG_BOOTARGS
  "bootargs=" CONFIG_BOOTARGS "\0"
#endif
#ifdef CONFIG_BOOTCOMMAND
  "bootcmd=" CONFIG_BOOTCOMMAND "\0"
#endif
......

env_default.h中指定了很多环境变量的默认值,比如 bootcmd 的默认值是CONFIG_BOOTCOMMAND,bootargs的是CONFIG_BOOTARGS。我们可在mx6ull_andyxi_emmc.h 文件中通过设置宏CONFIG_BOOTCOMMAND来设置 bootcmd 的默认值, NXP官方设置的 CONFIG_BOOTCOMMAND 值如下:

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

2.2 bootargs环境变量

bootargs 保存着 uboot 传递给 Linux 内核的参数,以下面命令为例

setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw

bootargs 中常用的参数有:

  • console:用来设置 linux终端,即通过什么设备来和 Linux进行交互,是串口还是 LCD屏幕,一般设置串口作为 Linux终端,这样就可以在电脑上通过串口助手来和 linux进行交互了
console= ttymxc0, 115200
//console 为 ttymxc0,因为 linux启动以后I.MX6ULL的串口1
//在linux下的设备文件就是/dev/ttymxc0
//ttymxc0 后面的“115200”,是设置串口的波特率
  • root:用来设置根文件系统的位置
root= /dev/mmcblk1p2 rootwait rw
// /dev/mmcblk1p2用于指明根文件系统存放在mmcblk1设备的分区2中
// /dev/mmcblkxpy(x=0~ n,y=1~ n)表示mmc设备x的分区y
// rootwait表示等待mmc设备初始化完成以后再挂载,否则的话会出错
// rw 表示根文件系统是可以读写的,不加rw的话可能只能读而无法进行写操作

rootfstype:一般与root一起使用, 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs、 jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型

3. U-Boot启动Linux测试

uboot 已经移植好后,就要测试一下 uboot 能不能完成它的工作:启动 Linux 内核。这里测试两种启动 Linux 内核的方法,一种是直接从 EMMC 启动,一种是从网络启动

3.1 从EMMC启动Linux

从 EMMC 启动也就是将编译出来的 Linux 镜像文件 zImage 和设备树文件保存在 EMMC中, uboot 从 EMMC 中读取这两个文件并启动,这个是产品最终的启动方式。此处默认已经将 zImage 文件和设备树文件烧写到了 EMMC 中,可以直接读取来进行测试

⏩ 使用命令“ls mmc 1:1”检查 EMMC 的分区 1 中是否已有相关文件,下图结果表示已有相关文件

在这里插入图片描述

⏩ 设置 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-andyxi-emmc.dtb; bootz 80800000 - 83000000;'
saveenv

⏩ 输入“boot”命令,启动内核即可

3.2 从网络启动Linux

从网络启动 linux系统的唯一目的就是为了调试!不管是为了调试 linux系统还是 linux下的驱动,每次修改 linux系统文件或者 linux下的某个驱动后都要将其烧写到 EMMC 中去测试,这样太麻烦了。可以设置从网络启动,将 linux镜像文件和根文件系统都放到 Ubuntu下指定的文件夹中,这样每次重新编译 linux内核或者 linux驱动后只需要将其拷贝到这个指定的文件夹中即可,这样就无需频繁的烧写 EMMC

可以通过 nfs或者 tftp从 Ubuntu中下载 zImage和设备树文件,本文使用 tftp从 Ubuntu中下载 zImage和设备树文件,默认已经将 zImage和设备树文件放到 Ubuntu下的 tftp目录中

⏩ 设置 bootargs 和 bootcmd 这两个环境变量

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-andyxi-emmc.dtb; bootz
80800000 - 83000000'
saveenv

⏩ 输入“boot”命令,启动内核,下图结果表示内核启动成功

在这里插入图片描述

4.U-Boot移植总结

uboot 移植到此结束,简单总结一下 uboot 移植的过程:

  • 不管是购买的还是自己做的开发板,基本都是参考半导体厂商的 dmeo板,半导体厂商会在他们的开发板上移植好 uboot、kernel和 rootfs等,最终制作好 BSP包提供给用户。我们可在官方提供的 BSP包的基础上添加自已的板子,即俗称的移植
  • 购买的或者自己做的开发板一般不会原封不动的照抄半导体厂商的 demo板,都会根据实际情况来做修改,有修改就会涉及到 uboot下驱动的移植
  • 一般 uboot中需要解决串口、NAND、EMMC或 SD卡、网络和 LCD动,因为 uboot的主要目的是启动 Linux内核,所以不用考虑太多的外设驱动
  • 在 uboot中添加自己的开发板信息,并根据实际情况来修改 uboot中的驱动

猜你喜欢

转载自blog.csdn.net/Chuangke_Andy/article/details/126724626