【系统移植一】uboot移植

开发板类型:emmc、7寸屏

前言

Linux的启动需要一段bootloader程序,也就是芯片上电以后运行一段bootloader程序。这段程序会先初始化DDR等外设,然后将linux内核从flash(NAND、NOR FLASH、 SD、MMC等)拷贝到DDR中,最后启动linux内核。bootloader最主要的作用是启动Linux内核。uboot是bootloader的一种。

1 NXP官方开发板uboot编译测试

1.1 获取源码

1)源码路径:1、例程源码->4、NXP 官方原版 Uboot 和 Linux -> uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2。
2)将源码拷贝到ubuntu中的~/linux/IMX6ULL/uboot/temp目录下,解压。解压后入下图所示:
在这里插入图片描述

1.2 编译

1 安装ncurses库

sudo apt-get install libncurses5-dev

2 配置
在编译之前首先要配置uboot,uboot的配置文件在configs目录下,因为开发是使用的是14x14mm尺寸的芯片,emmc版本,所以关注官方的 mx6ull_14x14_evk_emmc_defconfig配置文件。

3 编译
编写脚本/mx6ull_14x14_evk_emmc.sh,内如如下

#!/bin/bash
 make ARCH=arm CROSS_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

给脚本可执行权限,执行脚本

./mx6ull_14x14_evk_emmc.sh

4 烧写验证
1)烧写
将逻辑开发时用到的下载软件imxdownload拷贝到该目录下,使用下面语句下载到SD卡中。

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

sdb是SD卡,下载后将SD卡插入开发版的板槽,打开MobaXterm软件,设置好串口并打开,复位开发板后可以看到如下信息:
在这里插入图片描述
2)SD卡和emmc驱动检查
使用如下命令验证SD卡和emmc,

mmc list     	//查看设备中的mmc设备
mmc dev 0/1		//切换mmc设备
mmc info		//查看mmc设备信息

查看结果如下,SD卡和emmc都可以查到。
在这里插入图片描述
3)LCD检查
因为开发板上链接的是7寸屏,所以不会显示NXP的logo
4)网络检查
uboot启动的时候提示“Board Net Initialization Failed”和“No ethernet found.”这两行,说明网络驱动也是有问题的。这是因为开发版的网络芯片复位引脚和NXP官方开发版不一样,因此需要修改驱动。

5 总结
移植NXP官方I.MX6ULL EVK开发板的uboot到正点原子EMMC开发板上的运行情况:

  1. uboot启动正常,DRAM识别正确,SD卡和EMMC驱动正常
  2. uboot里面的LCD默认是4.3寸480写72分辨率的,其他分辨率需修改
  3. 网络不能正常工作,识别不出网络信息,需要修改

移植需要做的工作:
4. 在uboot中添加自己的开发板
5. 解决LCD和网络驱动问题

2 在U-boot中添加自己的开发板

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

1)所在目录:configures
2)复制文件:mx6ull_14x14_evk_emmc_defconfig
3)重命名为:mx6ull_alientek_emmc_defconfig
命令如下:

cd configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig

4)修改内容:
然后将文件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行和第4行

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

1)目录:include/configs
2)复制文件:mx6ullevk.h
3)重命令为:mx6ull_alientek_emmc.h
命令如下:

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

4)修改内容:

#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H

修改为:

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

这里面有很多宏定义,这些宏基本是用来配置uboot的,也有些是I.MX6ULL的配置项,如果项使能或者禁止uboot的某些功能,则修改本文件。里面内容较多在后面详细记录。

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

uboot的每个板子都有一个对应的文件夹用来存放板级文件,I.MX系列芯片的板级文件在board/freescale目录下。
1)目录:board/freescal
2)复制文件:mx6ullevk
3)重命名为:mx6ull_alientek_emmc
命令如下:

cd board/freescal
cp -r mx6ullevk mx6ull_alientek_emmc

4)进入mx6ull_alientek_emmc目录,将mx6ullevk.c重命名为mx6ull_alientek_emmc.c,命令如下:

cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc

5)修改mx6ull_alientek_emmc内容:

  1. 修改Makefile文件
    修改内容如下:
    在这里插入图片描述

    重点是红框内容,这样才会编译mx6ull_alientek_emmc.c

  2. 修改imximage.cfg文件

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

    改为:

    PLUGIN board/freescale/mx6ull_alientek_emmc /plugin.bin 0x00907000
    
  3. 修改Kconfig文件

     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
    
  4. 修改MAINTAINERS文件

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

2.4 修改U-boot图形界面配置文件

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

201 config TARGET_MX6ULL_9X9_EVK
202     bool "Support mx6ull_9x9_evk"
203     select MX6ULL
204     select DM
205     select DM_THERMAL
206 
207 config TARGET_MX6ULL_ALIENTEK_EMMC
208     bool "Support mx6ull_alientek_emmc"
209     select MX6ULL
210     select DM
211     select DM_THERMAL
212 
213 config TARGET_SECOMX6
214     bool "secomx6 boards"

在最后一行的endif前添加如下内容:

 source "board/freescale/mx6ull_alientek_emmc/Kconfig"

2.5 使用新添加的板子编译uboot

1)在uboot跟目录新建一个名为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 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

2)执行脚本,脚本要有可执行权限

./imx6ull_alientek_emmc.sh

3)查看是否添加成功

grep -nr "mx6ull_alientek_emmc.h"

如果有很多文件都引用了mx6ull_alientek_emmc.h这个头文件,则说明板子添加成功,如图所示:
在这里插入图片描述
4)下载验证:
下载到SD卡中,开启开发板,在串口中可以看到如下信息:
在这里插入图片描述
此时屏幕上是无法显示NXP的logo的,因为屏幕驱动不正确,同时网络驱动也是有问题的。

2.6 LCD驱动修改

一般uboot的驱动修改都是在xxx.hxxx.c这两个文件中进行的。比如 mx6ull_alientek_emmc.h 和mx6ull_alientek_emmc.c 这两个文件。

1)一般修改LCD驱动重点注意一下几点:
①、LCD所使用的GPIO,查看uboot中LCD的IO配置是否正确
②、LCD背光引脚GPIO配置
③、LCD配置参数是否正确

2)正点原子的LCD原理图和NXP的相同,也就是LCD的IO和背光IO都一样,因此IO部分就不需要修改了。只修改LCD的参数即可

3)参数修改:
修改mx6ull_alientek_emmc.c文件
① 目录:board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c

② 修改内容:
找到display_info_t结构体,大约在780行,修改为如下内容

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",	//LCD 名字,要和环境变量中的 panel 相等
        .xres           = 1024,			//LCD X 轴和 Y 轴像素数量
        .yres           = 600,
        .pixclock       = 19531,		//像素时钟,每个像素时钟周期的长度,单位为皮秒
        .left_margin    = 140,			//HBP,水平同步后肩。
        .right_margin   = 160,			//HFP,水平同步前肩
        .upper_margin   = 20,			//VBP,垂直同步后肩。
        .lower_margin   = 12,			//VFP,垂直同步前肩。
        .hsync_len      = 20,			//HSPW,行同步脉宽。
        .vsync_len      = 3,			//VSPW,垂直同步脉宽。
        .sync           = 0,
        .vmode          = FB_VMODE_NONINTERLACED		//大多数使用 FB_VMODE_NONINTERLACED,也就是不使用隔行扫描
} } };

pixclock的计算方法:
7寸1024*600分辨率的屏幕像素时钟为51.2MHz

pixclock=(1/51200000)*10^12 = 19531

4)验证
重新编译代码,将编译出的u-boot.bin下载到SD卡中。重启开发板,此时屏幕上会显示NXP的logo。
若没有logo则查看环境变量panel是否为TFT7016,如果不是则用如下命令修改环境变量。

setenv panel TFT7016
saveenv

2.7 网络修改

开发板为2.4以前版本。使用的PHY芯片为LAN8720。正点原子 开发板 ENET1 引脚与NXP官方 I.MX6ULL EVK开发板只有复位引脚不同,I.MX6U-ALPHA 开发板 ENET1 上连接的 LAN8720A器件地址为 0X0,所以ENET1网络驱动的重点只有如下三点:
① ENET1复位引脚初始化
② LAN8720A的器件ID
③ LAN8720驱动

关于 ENET2 网络驱动的修改也注意一下三点:
① ENET2 的复位引脚,ENET2 的复位引脚 ENET2_RST 接到了I.MX6ULL 的 SNVS_TAMPER8 上。
② ENET2 所使用的 PHY 芯片器件地址,PHY 器件地址为 0X1。
③ LAN8720 驱动,ENET1 和 ENET2 都使用的 LAN8720,所以驱动肯定是一样的。

2.7.1 网络PHY芯片修改

打开mx6ull_alientek_emmc.h,所在目录:include/configs,修改内容如下:

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
332 
333 #if (CONFIG_FEC_ENET_DEV == 0)
334 #define IMX_FEC_BASE            ENET_BASE_ADDR
335 #define CONFIG_FEC_MXC_PHYADDR          0x0		//改为0
336 #define CONFIG_FEC_XCV_TYPE             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"
343 
344 #define CONFIG_PHYLIB
345 #define CONFIG_PHY_SMSC		//这个地方修改为CONFIG_PHY_SMSC
346 #endif

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

打开imx6ull_alientek_emmc.c

  1. 删除与74LV595有关代码
    1)将:

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

    因为正点原子没有使用74LV595,所以需要将与74LV595有关代码删掉,IOX开头的宏定义就是与74LV595有关的。
    ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07,ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08

    2)删除iox_pads[]数组、iox74lv_init()函数和iox74lv_set函数。
    3)删除board_init()函数中的 imx_iomux_v3_setup_multiple_padsiox74lv_init两行,这两行是用来初始化74lv595函数的

2.7.3 添加I.MX6ULL-ALPHA开发板网络复位引脚驱动

1)fec1_padsfec2_pads是ENET1和ENET2两个网口的IO配置参数,在这两个数组中添加两个网口的复位IO配置参数,完成以后如下图:

/*
 * pin conflicts for fec1 and fec2, GPIO1_IO06 and GPIO1_IO07 can only
 * be used for ENET1 or ENET2, cannot be used for both.
 */
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),
    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_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),
    MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),	//新添加
};

2)修改setup_iomux_fec函数,该函数根据fec1_pads和fec2_pads两个配置数组来初始化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));
	//ENET1复位
	     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));
		//ENET2复位
        gpio_direction_output(ENET2_RESET, 1);
        gpio_set_value(ENET2_RESET, 0);
        mdelay(20);
        gpio_set_value(ENET2_RESET, 1);
    }
}

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

uboot的LAN8720的驱动有些问题,需要修改,打开文件
drivers/net/phy/phy.c,找到函数 genphy_update_link,这是个通用 PHY 驱动函数,此函数用于更新 PHY 的连接状态和速度。使用 LAN8720A 的时候需要在此函数中添加一些代码,修改后的函数 genphy_update_link 如下所示:

int genphy_update_link(struct phy_device *phydev)
{
    unsigned int mii_reg;
//新添加代码为ifdef部分
#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;

2.7.5 下载验证

1)编译代码,下载到SD卡中,可以从串口助手上看到 Net:FEC1 字样,说明网络驱动配置成功。如下图所示:
在这里插入图片描述
2)修改环境变量,配置开发板网络:
1)配置网络:

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

2)测试网络:

ping 192.168.0.12

结果如图:
在这里插入图片描述
我的这个开始链接出现问题是因为网线插错网口了,应该插到挨着db9的网口上。

终于搞完了,详细的解释后面补充

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值