IMX6ULL驱动开发前奏一:u-boot移植步骤明细

U-boot移植

uboot实际上就是一个裸机程序,但它是用来引导linux内核启动的,就像电脑上的bios。

本文只要是记录利用NXP官方的uboot进行改造,适配正点原子IMX6ULL阿尔法开发板的过程

涉及到的文件

(可能不全)

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/configs/mx6ull_14x14_evk_defconfig

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/include/configsmx6ullevk.h

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ullevk/Makefile

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ullevk/imximage.cfg

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ullevk/Kconfig

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ullevk/MAINTAINERS

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/cpu/armv7/mx6/Kconfig

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/mx6ull_14x14_evk_emmc.sh

/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/drivers/net/phy/phy.c

如上述所示,是需要与自己开发板进行适配调整的文件路径及文件名。如果原厂u-boot只是对NXP官方开发板进行适配,当我们用自己的开发板时还需要进行修改,比如显示屏、网络等。

官方u-boot文件目录

下图是NXP官方uboot解压后的文件目录概览
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第1张图片
每个文件/文件夹的介绍,加粗的是最重要的部分

名称 介绍
api 一些与硬件无关的API函数
arch 与架构体系有关的内容
board 板级支持包,用来适配不同开发板
cmd 命令相关的代码
common 通用代码
config.mk 被某个Makefile调用
configs 配置文件
disk 磁盘分区相关代码
doc 文档
drivers 驱动代码
dts 设备树
examples 例程
fs 文件系统
imxdownload SD卡烧写软件(来自正点原子)
include 头文件
kbuild 用于生成和汇编有关的文件
kconfig 图形化配置界面描述文件
lib 库文件
Licenses 许可证
load.imx 烧写SD卡后产生的文件
MAINTAINERS 维护者联系方式文件
MAKEALL shell脚本,辅助编译uboot
Makefile 主要的Makefile文件
mx6ull_14x14_evk_emmc.sh 编译原厂开发板的uboot脚本
mx6ull_alientek_emmc.sh 编译自己的开发板的uboot脚本
net 网络相关代码
post 上电自检程序
README 说明
scripts 脚本文件
snapshot.commit 快照提交(不知道是啥)
system.map 系统映射文件
test 测试代码
tools 工具
u-boot 编译得到的uboot文件
u-boot.xx 与uboot相关的文件,u-boot.bin文件是要烧写的文件

第一步

添加默认配置文件:进入configs文件夹中,该文件夹保存了各种开发板的默认配置文件。找到mx6ull_14x14_evk_emmc_defconfig这个文件。将其拷贝一份并重命名为mx6ull_alientek_emmc_defconfig(这里命名我是跟着原子来的,也可以自己设置个名字,注意配置过程中别输错名字就行。)
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第2张图片
要修改的内容:主要修改文件中以下的两个红框内的内容

一个是修改 .imx文件的生成工具imximage.sh的路径。

一个是修改默认目标参数名。
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第3张图片

第二步

添加对应的头文件:

​ 开发板的头文件位于**/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/include/configs目录下,找到mx6ullevk.h文件,复制一份重命名为mx6ull_alientek_emmc.h**,打开并修改一个宏定义
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第4张图片

将红框内的代码修改成如下代码:

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H
  • 这个头文件可以适当剪裁,也可直接用,随意。

第三步

添加并修改板级文件夹:

uboot关于开发板的板级文件夹位于**/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board这个目录下,而NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 该目录的freescale**文件夹下,在这个目录下有个名为 mx6ullevk 的文件夹,这个文件夹就是 NXP 官方 I.MX6ULL EVK 开发板的板级文件夹。

找到mx6ullevk 文件夹复制一份并重命名为mx6ull_alientek_emmc

cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc

文件夹的内容如下:
在这里插入图片描述
将其中的mx6ullevk.c文件重命名为mx6ull_alientek_emmc.c

然后开始修改文件内容

修改Makefile内容

IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第5张图片
将红框内容修改为:

obj-y := mx6ull_alientek_emmc.o

修改imximage.cfg内容

IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第6张图片
将红框内容修改为:

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

修改Kconfig内容

IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第7张图片

修改为:

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文件内容

原文件内容:
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第8张图片
修改后:

MX6ULL_ALIENTEK_EMMC BOARD
M: Peng Fan  
S: Maintained
F: board/freescale/mx6ull_alientek_emmc/ 
F: include/configs/mx6ull_alientek_emmc.h

第四步

修改uboot图形界面配置文件

文件路径:/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/cpu/armv7/mx6
在这里插入图片描述
主要修改Kconfig文件。打开文件,在207行的位置,添加如下内容

config TARGET_MX6ULL_ALIENTEK_EMMC
bool "Support mx6ull_alientek_emmc"
select MX6ULL
select DM
select DM_THERMAL

添加后如图示:
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第9张图片
然后在最后一行的endif前添加以下内容

source "board/freescale/mx6ull_alientek_emmc/Kconfig"

添加后如图示:
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第10张图片
经过这四步,阿尔法开发板就添加进了uboot里了,接下来就是编译uboot

第五步

在**/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek**下编写shell脚本。

脚本命名为mx6ull_alientek_emmc.sh,以下是脚本代码。但是要注意一点:执行distclean即清理时会将uboot图像化配置中的配置参数清除。

#!/bin/bash

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

然后给脚本分配权限

chmod 777 mx6ull_alientek_emmc.sh

最后是运行脚本编译uboot

./mx6ull_alientek_emmc.sh

这个命令可以查看头文件是否被引用。

grep -nR "mx6ull_alientek_emmc.h"

第六步

这时的uboot中的各种驱动还是默认配置,与开发板的外设还有些不匹配,主要是显示屏和网络接口参数,接下来就要修改这些驱动配置。

显示屏相关配置参数修改

打开文件:mx6ull_alientek_emmc.c

位于:/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ull_alientek_emmc

找到如下代码,按照自己用的显示屏修改参数,我这里用的是7寸800*480的屏幕,名字命名为TFT7084。

IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第11张图片

  • 该结构体的说明
    • name:LCD 名字,要和环境变量中的 panel 相等。
    • xres、yres:LCD X 轴和 Y 轴像素数量。
    • pixclock:像素时钟,每个像素时钟周期的长度,单位为皮秒。
    • left_margin:HBP,水平同步后肩。
    • right_margin:HFP,水平同步前肩。
    • upper_margin:VBP,垂直同步后肩。
    • lower_margin:VFP,垂直同步前肩。
    • hsync_len:HSPW,行同步脉宽。
    • vsync_len:VSPW,垂直同步脉宽。
    • vmode:大多数使用 FB_VMODE_NONINTERLACED,也就是不使用隔行扫描。

(其中pixclock = (1/屏幕要求的像素时钟)*10^12)

(不同种屏幕的各种参数可以在正点原子讲解RGB LCD的代码中找到,也可以参考各数据手册。)

打开文件:mx6ull_alientek_emmc.h

位于:/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/include/configs

将所有panel的值改为TFT7084,要和mx6ull_alientek_emmc.c文件中的name一致
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第12张图片
这样显示屏的相关参数就修改完了,接下来修改网络方面的代码

网络相关配置修改

先打开文件mx6ull_alientek_emmc.h文件

找到下面这段代码
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第13张图片
这三处对应:

①、 ENET1 网络 PHY 的地址。

②、 ENET2 网络 PHY 的地址。

③、 使能 PHY 驱动(要改为SMSC公司的PHY驱动)。

修改后的代码:
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第14张图片
再打开文件mx6ull_alientek_emmc.c文件

修改PHY芯片的网络复位引脚,找到以下代码:
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第15张图片
修改为:

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

让ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07,ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08

找到函数static void iox74lv_init**(void)** 和void iox74lv_set**(int index)** 并删除。
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第16张图片
再找到开发板初始化函数board_init(void)
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第17张图片
删除如下代码:

imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
iox74lv_init();

继续添加 I.MX6U-ALPHA 开发板网络复位引脚驱动,找到

static iomux_v3_cfg_t const fec1_pads[] 和 static iomux_v3_cfg_t const fec2_pads[] ,位于640行和653行

在static iomux_v3_cfg_t const fec1_pads[]中添加:

MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),

在static iomux_v3_cfg_t const fec2_pads[]中添加:

MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),

继续找到函数setup_iomux_fec(函数位于668行)进行修改,添加网络复位IO的初始化代码,修改后如下:

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

最后找到phy.c文件进行修改

文件位置:/home/swiler/uboot_official/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/drivers/net/phy

打开phy.c文件找到 genphy_update_link(struct phy_device *****phydev) ,这是个通用 PHY 驱动函数,此函数用于更新 PHY 的连接状态和速度,使用 LAN8720A 的时候需要在此函数中添加一些代码。修改后的函数如下:(主要是#ifdef到#endif之间的内容)

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,利用imxdownload工具将u-boot.bin烧入到SD卡中,把SD卡插入开发板,启动方式调节为SD卡启动,开发板连接网线和串口USB,上电复位。

在autoboot这里倒计时结束之前按任意键就可以进入uboot
IMX6ULL驱动开发前奏一:u-boot移植步骤明细_第18张图片
接下来配置网络相关的环境变量

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

然后ping下主机,即Ubuntu的IP,如果ping通了,就如下图所示。
在这里插入图片描述

从EMMC启动linux系统

先配置 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-alientek-emmc.dtb; bootz 80800000 - 83000000;'
saveenv

设置完输入boot,或者 run bootcmd 即可启动 Linux 内核。

如果内核启动成功就能进入系统了。

从网络启动 Linux 系统

先配置 bootargs 和 bootcmd这两个环境变量

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

下载好zImage和imx6ull-alientek-emmc.dtb后,效果和从EMMC启动linux系统类似。

以上就完成了利用原厂的u-boot来构建符合自身开发板的u-boot的移植了。

你可能感兴趣的:(Linux基础,嵌入式,c语言,mcu,linux,单片机)