U-BOOT移植 添加自己的开发板IMX6ULL

本篇梳理在uboot中添加自己的开发板,并且进行移植和启动。这里使用的是正点原子的linux教程以及正点原子的开发板,本篇只为梳理,为后续开发整理流程。

简介

在uboot中添加自己的开发板,这里是使用NXP官方imxull-evk开发板进行修改的,首先我们需要添加几个文件>>
1、创建配置文件 mx6ull_xxx_emmc_defconfig
2、添加开发板对应头文件 mx6ull_xxx_emmc.h
3、添加开发板对应的板级文件:文件夹 mx6ull_xxx_emmc
4、修改U-BOOT图形界面文件
5、LCD驱动修改
6、网络驱动修改
7、uboot编译及移植
8、bootcmd和bootargs环境变量

创建配置文件mx6ull_xxx_emmc_defconfig

第一步我们先复制configs目录下面的mx6ull_14x14_env_emmc_defconfig,放到同目录下命名为mx6ull_xxx_emmc_defconfig,后面我们编译需要使用这个配置文件。
修改配置文件内容:

CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_xxx_emmc/imximage.cfg"
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_XXX_EMMC=y
CONFIG_CMD_GPIO=y

添加开发板对应头文件

复制include/configs/mx6ullevk.h到configs目录下,命名为mx6ull_xxx_emmc.h,修改修改宏定义:

#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H
...

改为

#ifndef __MX6ULLEVK_XXX_EMMC_CONFIG_H
#define __MX6ULLEVK_XXX_EMMC_CONFIG_H
...

该头文件中有很多宏定义用于配置uboot。

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

uboot中每个板子都有对应的文件夹来存放板级文件,比如开发板上外设驱动文件等。复制board/freescale/mx6ullevk到freescale文件夹下,命名为mx6ull_xxx_emmc。

修改mx6ull_xxx_emmc.c

进入mx6ull_xxx_emmc文件夹下,将mx6ullevk.c命名为mx6ull_xxx_emmc.c。
修改mx6ull_xxx_emmc文件夹下的Makefile文件:

# (C) Copyright 2015 Freescale Semiconductor, Inc.
#
# SPDX-License-Identifier:	GPL-2.0+
#

obj-y  := mx6ullevk.o

extra-$(CONFIG_USE_PLUGIN) :=  plugin.bin
$(obj)/plugin.bin: $(obj)/plugin.o
	$(OBJCOPY) -O binary --gap-fill 0xff $< $@

# (C) Copyright 2015 Freescale Semiconductor, Inc.
#
# SPDX-License-Identifier:	GPL-2.0+
#

obj-y  := mx6ull_xxx_emmc.o

extra-$(CONFIG_USE_PLUGIN) :=  plugin.bin
$(obj)/plugin.bin: $(obj)/plugin.o
	$(OBJCOPY) -O binary --gap-fill 0xff $< $@

将obj-y修改为mx6ull_xxx_emmc.o,这样就会编译mx6ull_xxx_emmc.c了。

修改imximage.cfg文件

PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

改为

PLUGIN board/freescale/mx6ull_xxx_emmc/plugin.bin 0x00907000

修改Kconfig文件

将mx6ull_xxx_emmc目录下的Kconfig改为:

if TARGET_MX6ULL_XXX_EMMC

config SYS_BOARD
	default "mx6ull_xxx_emmc"

config SYS_VENDOR
	default "freescale"
	
config SYS_SOC
	default "mx6"

config SYS_CONFIG_NAME
	default "mx6ull_xxx_emmc"

endif

修改MAINTAINERS文件

修改mx6ull_xxx_emmc文件夹下MAINTAINERS文件:

MX6ULLEVK BOARD
M:	Peng Fan <peng.fan@nxp.com>
S:	Maintained
F:	board/freescale/mx6ull_xxx_emmc/
F:	include/configs/mx6ull_xxx_emmc.h

修改U-BOOT图形界面文件

修改 文件arch/arm/cpu/armv7/mx6/Kconfig 如下:

...
config TARGET_MX6ULL_9X9_EVK
	bool "Support mx6ull_9x9_evk"
	select MX6ULL
	select DM
	select DM_THERMAL
	
config TARGET_MX6ULL_ALIENTEK_EMMC
	bool "Support mx6ull_xxx_emmc"
	select MX6ULL
	select DM
	select DM_THERMAL
...
source "board/freescale/mx6sxscm/Kconfig"
source "board/freescale/mx6ull_xxx_emmc/Kconfig"
endif

LCD驱动修改

正点原子的LCD所使用的GPIO和NXP官方的开发板一致,背光IO也一致,所以IO部分不需要修改,徐娅ixiugai的只有LCD的配置,这里使用的是4.3寸屏幕,800*480分辨率,修改mx6ull_xxx_emmc.c文件:

...
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			= "ATK-LCD-4.3-800x480",
		.xres           = 800,
		.yres           = 480,
		.pixclock       = 10119,
		.left_margin    = 210,
		.right_margin   = 46,
		.upper_margin   = 22,
		.lower_margin   = 23,
		.hsync_len      = 20,
		.vsync_len      = 3,
		.sync           = 0,
		.vmode          = FB_VMODE_NONINTERLACED
} } };
...

这里定义了类型为display_info_t的变量displays,这个结构体是LCD信息结构体,其中包括了LCD分辨率,像素格式,LCD的各项参数。
pixfmt是像素格式(一个像素点是多少位),如果是RGB565的话就是16,如果是RGB888的话就是24。
变量mode中个成员变量如下:
name:LCD名字,要和环境变量中的panel相等。
xres、yres:LCD X轴和Y轴的像素数量。
pixclock:像素时钟,每个像素时钟周期的长度,单位皮秒。
left_margin:
right_margin:
upper_margin:
lower_,margin:
hsync_len:
vsync_len:
vmode:大多数使用FB_VMODE_NONINTERLACED,也就是不进行隔行扫描。
修改完成后找到mx6ull_xxx_emmc.h文件中的

panel=TFT43AB

改为:

panel=ATK-LCD-4.3-800x480

网络驱动修改

关于网络驱动修改,由于正点原子使用的PHY芯片LAN8720A和NXP官方开发板的PHY芯片KSZ8081不同,这里需要修改的地方比较多:
1、网络PHY地址修改
2、删除uboot中74LV595的驱动代码(官方开发板使用了74LV595扩展IO,正点原子开发板,没有用到)
3、添加开发板复位引脚驱动
4、修改drivers/net/phy.phy.c文件中函数genphy_update_link

网络PHY地址修改

正点原子开发板ENET1的PHY地址是0x0,ENET2的PHY地址是0x1,官方使用的PHY芯片KSZ8081是MICREL生产的,所以使用的是MICREL的驱动,定义宏:

#define CONFIG_PHY_MICREL

现在使用的是LAN8720A,是SMSC公司生产的,定义宏:

#define CONFIG_PHY_SMSC

所以需要修改:

#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE			ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR          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
#define CONFIG_FEC_XCV_TYPE		RMII
#endif
#define CONFIG_ETHPRIME			"FEC"

#define CONFIG_PHYLIB
#define CONFIG_PHY_SMSC
#endif

删除uboot中74LV595驱动代码

由于官方开发板使用了74LV595进行IO扩张,74LV595是一款计数器移位寄存器,在正点原子开发板上并未使用,可以在uboot中将涉及的代码删除,一下罗列:
这里打开mx6ull_xxx_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)

删除此段代码,ENET1的复位引脚是GPIO_IO07,ENET2的复位引脚是GPIO_IO08,故替换代码:

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

删除 static iomux_v3_cfg_t const iox_pads[] 函数
删除 static void iox74lv_init(void)
删除 void iox741v_set(int index)
删除在board_init函数中 imx_iomux_v3_setup_multiple_pads和 iox74lv_init的调用。

添加开发板复位引脚驱动

在mx6ull_xxx_emmc.c中找到网口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_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET1_TX_EN__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
	MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | 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_TX_DATA0__ENET2_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
	MX6_PAD_ENET2_TX_EN__ENET2_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

	MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL),
	MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01 | 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[] 和static iomux_v3_cfg_t const fec2_pads[] 添加网口复位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),
	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_TAMPER7__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
};

在mux6ull_xxx_emmc.c中找到set_iomux_fec函数,修改如下:

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

以上代码对应ENET1和ENET2复位引脚初始化,并设置成输出,并且硬件复位LAN8720A。

修改drivers/net/phy.phy.c文件中函数

uboot中关于LAN8720A的驱动有点问题(没试过),打开drivers/net/phy/phy.c,找到函数genphy_update_link,此函数是通用的PHY驱动函数,用于更新PHY的连接状态和速度,在此添加一些代码,修改后如下:

int genphy_update_link(struct phy_device *phydev)
{
	unsigned int mii_reg;
	//以下为新增内容
	#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(phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
			while( phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR) & 0x8000) {
				udelay(100);
			}
		}
	#endif
	
	
	/*
	 * Wait if the link is up, and autonegotiation is in progress
	 * (ie - we're capable and it's not done)
	 */
	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
...
	return 0;
}

以上完成了在uboot中添加自己的开发板!

bootcmd和bootargs环境变量

做完以上工作后我们需要编译uboot并且烧写到SD卡中,启动开发板,在倒计时结束前按下回车进入uboot命令行模式。
我们需要在命令行模式下设置bootcmd和bootargs这两个环境变量。

bootcmd

保存着uboot默认命令,uboot倒计时结束后就会执行bootcmd命令,将linux内核和设备树文件拷贝到DRAM中,然后启动linux内核,我们将zImage和设备树文件放到EMMC当中,然后在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

保存着uboot传递给linux内核的参数,主要分为以下三个参数:

console

用来设置linux终端,可选择串口或者LCD,这里选择使用串口1即/dev/ttymxc0,后面设置波特率。

root

用来设置根文件系统的位置,这里将根文件系统存放在emmc的分区二,参数设定为/dev/mmcblk1p2。

rootfstype

用于设定根文件系统类型:ext、yaffs、jffs、ubifs,如果时ext,此项可以不指定。

下面列出完整的bootargs环境变量的设置:
setenv bootargs ‘console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw’

uboot启动

完成上述工作后就可以重启开发板进行测试了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值