Uboot的移植

首先从官方下载一个Uboot,之后在此上面进行移植,可以进行使用脚本进行编译一下。

1
2
3
make ARCH=arm CORSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

在Uboot中添加使用的开发板

添加开发板默认配置文件

将cofigs目录下复制原有的mx6ull_14x14_evk_emmc_defconfig进行修改

1
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig

修改mx6ull_alientek_emmc_defconfig文件,将原有的替换成mx6ull_alientek_emmc

1
2
3
4
5
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

添加开发板对应的头文件

在 目 录 include/configs 下 添 加 I.MX6ULL-ALPHA 开 发 板 对 应 的 头 文 件 , 复 制include/configs/mx6ullevk.h,并重命名为 mx6ull_alientek_emmc.h,命令如下:

1
cp include/configs/mx6ullevk.h mx6ull_alientek_emmc.h

拷贝完成以后将:

1
2
#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H

改为:

1
2
#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

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

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

NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 board/freescale 目录下,在这个目录下有个名为 mx6ullevk 的文件夹,这个文件夹就是 NXP 官方 I.MX6ULL EVK 开发板的板级文件夹。

1
2
3
4
cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc
cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc.c

分别需要修改Makefile文件、imximage.cfg 文件、Kconfig 文件 、MAINTAINERS 文件

Makefile要改编译的.o的文件名字。

imximage.cfg 需要修改PLUGIN 后面的板载二进制文件所在路径。

Kconfig 文件 需要改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if TARGET_MX6ULL_ALIENTEK_EMMC

config SYS_BOARD
default "mx6ull_alientek_emmc"

config SYS_VENDOR
default "freescale"

config SYS_SOC
default "mx6"

config SYS_CONFIG_NAME
default "mx6ull_alientek_emmc"

endif

MAINTAINERS 文件需改

1
2
3
4
5
MX6ULL_ALIENTEK_EMMC BOARD
M: Peng Fan <peng.fan@nxp.com>
S: Maintained
F: board/freescale/mx6ull_alientek_emmc/
F: include/configs/mx6ull_alientek_emmc.h

修改U-boot图形化配置文件

修改文件arch/arm/cpu/armv7/mx6/Kconfig ,207行加入

1
2
3
4
5
config TARGET_MX6ULL_ALIENTEK_EMMC
bool "Support mx6ull_alientek_emmc"
select MX6ULL
select DM
select DM_THERMAL

endif前加入

1
source "board/freescale/mx6ull_alientek_emmc/Kconfig"

LCD驱动修改

一般 uboot 中修改驱动基本都是在 xxx.h 和 xxx.c 这两个文件中进行的, xxx 为板子名称,比如 mx6ull_alientek_emmc.h 和 mx6ull_alientek_emmc.c 这两个文件。
一般修改 LCD 驱动重点注意以下几点:
①、 LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确。
②、 LCD 背光引脚 GPIO 的配置。
③、 LCD 配置参数是否正确。

基于使用的lcd设置参数为

1
2
3
4
5
6
7
8
9
10
11
12
13
.mode	= {
.name = "TFT4384",
.xres = 800,
.yres = 480,
.pixclock = 31746,
.left_margin = 88,
.right_margin = 40,
.upper_margin = 32,
.lower_margin = 13,
.hsync_len = 48,
.vsync_len = 3,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED

将mx6ull_alientek_emmc.h中的panel进行修改

1
panel=TFT4384

之后就可以编译烧录。正常显示出现以下东西。

如果没有出现效果,修改环境变量

1
2
setenv panel TFT7016
saveenv

如果只显示NXP没有uboot的版本号,并且报错no valid bmp image at 88000000,使用uboot命令清除一下环境变量。

1
2
env default -a
saveenv

网络驱动修改

更换 PHY 芯片以后如何调整网络驱动

修改 ENET1 网络驱动的话重点就三点:
①、 ENET1 复位引脚初始化。
②、 LAN8720A 的器件 ID。
③、 LAN8720 驱动

ENET2 网络驱动的修改也注意一下三点:
①、 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地址修改

修改ENETI和ENET2的PHY地址和驱动,ENET1和ENET2的PHY的地址存在mx6ull_alientek_emmc.h中

1
2
3
4
5
#if (CONFIG_FEC_ENET_DEV == 0)
#define CONFIG_FEC_MXC_PHYADDR 0x2 //ENET1的地址改为0x0
#elif (CONFIG_FEC_ENET_DEV == 1)
#define CONFIG_FEC_MXC_PHYADDR 0x1 //ENET2的地址相同不用改
#define CONFIG_PHY_MICREL //使用 LAN8720A则改为CONFIG_PHY_SMSC

因为两个板子的复位引脚不同。删除之前为了复位的扩展IO的代码,在mx6ull_alientek_emmc.c中

1
2
3
4
#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)

替换为自己使用板子的网络复位IO

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

删除原有结构体和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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),
};
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);
};

删掉板子初始化函数中的相关程序

1
2
3
4
5
6
7
8
int board_init(void)
{
......
imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads)); //删掉
iox74lv_init(); //删掉
......
return 0;
}

添加自己开发板的网络复位引脚驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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),//新加的
};

修改初始化网络IO的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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(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

/*
* 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中设置环境变量网址就可以应用了。