提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
重新修改得到u-boot.imx
提示:以下是本篇文章正文内容,下面案例可供参考
一、 添加开发板默认配置文件
先在 configs 目录下创建默认配置文件,复制 mx6ull_14x14_evk_emmc_defconfig,然后重命名为 mx6ull_alientek_emmc_defconfig,命令如下:
cd configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig
二、添加开发板对应的头文件
三、添加开发板对应的板级文件夹
uboot 中每个板子都有一个对应的文件夹来存放板级文件,比如开发板上外设驱动文件等
等。 NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 board/freescale 目录下,在这个目录下
有个名为 mx6ullevk 的文件夹,这个文件夹就是 NXP 官方 I.MX6ULL EVK 开发板的板级文件
夹。复制 mx6ullevk,将其重命名为 mx6ull_alientek_emmc,命令如下:
cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc
进 入 mx6ull_alientek_emmc 目 录 中 , 将 其 中 的 mx6ullevk.c 文 件 重 命 名 为
mx6ull_alientek_emmc.c,命令如下:`
cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc.c
我们还需要对 mx6ull_alientek_emmc 目录下的文件做一些修改:
1 修改 mx6ull_alientek_emmc 目录下的 Makefile 文件
2、修改 mx6ull_alientek_emmc 目录下的 imximage.cfg 文件
3、修改 mx6ull_alientek_emmc 目录下的 Kconfig 文件
修改后的文件如下
4、修改 mx6ull_alientek_emmc 目录下的 MAINTAINERS 文件
修改 MAINTAINERS 文件,修改后的内容如下:
4、修改 U-Boot 图形界面配置文件
修改文件
arch/arm/cpu/armv7/mx6/Kconfig(如果用的 I.MX6UL 的话,应该修改 arch/arm/Kconfig 这个文
件),在 207 行加入如下内容:
在最后一行的 endif 的前一行添加如下内容:
整体修改内容:
到此为止, I.MX6U-ALPHA 开发板就已经添加到 uboot 中了,接下来就是编译这个新添加的开发板。
5、使用新添加的板子配置编译 uboot
在 uboot 根目录下新建一个名为 mx6ull_alientek_emmc.sh 的 shell 脚本,在这个 shell 脚本
里面输入如下内容:
chmod 777 mx6ull_alientek_emmc.sh //给予可执行权限,一次即可
./mx6ull_alientek_emmc.sh //运行脚本编译 uboot
grep -nR "mx6ull_alientek_emmc.h"
从图 33.2.5.1 可以看出,此时的 Board 还是“MX6ULL 14x14 EVK”,因为我们参考的 NXP官方的 I.MX6ULL 开发板来添加自己的开发板。如果接了 LCD 屏幕的话会发现 LCD 屏幕并没有显示 NXP 的 logo,而且从图 33.2.5.1 可以看出此时的网络同样也没识别出来。前面已经说
了,默认 uboot 中的 LCD 驱动和网络驱动在正点原子的 I.MX6U-ALPHA 开发板上是有问题的,需要修改。
回头修改部分:使用新添加的板子配置编译 uboot
编译完可以看到有uboot.imx了
编译完进入uboot-imx-rel_imx_4.1.15_2.1.0_ga_aliente下面目录,参看有无mx6ull_alientek_emmc.o文件,有则成功
/home/zero/linux/IMX6ULL/uboot/uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek/board/freescale/mx6ull_alientek_emmc
六、 LCD 驱动修改
注:LCD修改完会有NXP的logo
一般 uboot 中修改驱动基本都是在 xxx.h 和 xxx.c 这两个文件中进行的, xxx 为板子名称,比如mx6ull_alientek_emmc.h 和 mx6ull_alientek_emmc.c 这两个文件。一般修改 LCD 驱动重点注意以下几点:
①、 LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确。
②、 LCD 背光引脚 GPIO 的配置。
③、 LCD 配置参数是否正确。
正点原子的 I.MX6U-ALPHA 开发板 LCD 原理图和 NXP 官方 I.MX6ULL 开发板一致,也就是 LCD 的 IO 和背光 IO 都一样的,所以 IO 部分就不用修改了。需要修改的之后 LCD 参数,打开文件 mx6ull_alientek_emmc.c,找到struct display_info_t const displays[] 并用下面屏幕参数替换掉 mx6ull_alientek_emmc.c 中 uboot 默认的屏幕参数。
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,
.right_margin = 160,
.upper_margin = 20,
.lower_margin = 12,
.hsync_len = 20,
.vsync_len = 3,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
} } };
size_t display_count = ARRAY_SIZE(displays);
在终端重新编译uboot,输入:
make -j4
将u-boot.bin烧写到SD卡 查看SD卡分区
sudo fdisk -l
./imxdownload u-boot.bin /dev/sdb
修改完成以后重新编译 uboot 并烧写到 SD 卡中验证 调到SD卡启动模式,开发板复位重启以后, LCD 驱动一般就会工作正常了, LCD 上回显示 NXP 的 logo。但是有可能会遇到LCD 并没有工作,还是黑屏,这是什么原因呢?在 uboot 命令模式输入“print”来查看环境变量 panel 的值,会发现 panel 的值要是 TFT43AB(或其他的,反正不是 TFT7016),这是因为之前有将环境变量保存到 EMMC 中, uboot 启动以后会先从 EMMC 中读取环境变量,如果 EMMC 中没有环境变量的话才会使用 mx6ull_alientek_emmc.h 中的默认环境变量。如果 EMMC 中的环境变量 panel 不等于 TFT7016,那么 LCD 显示肯定不正常,我们只需要在uboot 中修改 panel 的值为 TFT7016 即可,在 uboot 的命令模式下输入如下命令:
setenv panel TFT7016
saveenv
上述命令修改环境变量 panel 为 TFT7016,然后保存,重启 uboot,此时 LCD 驱动就工作正常了。如果 LCD 还是没有正常工作的,那就要检查自己哪里有没有改错,或者还有哪里没有修改。如果不行,可能是SD原因,需要将SD用专业工具SDformatter/// 或者fdiskGenius重新格式化为FAT32格式
七 V2.4 及以后版本底板网络驱动修改
1 I.MX6U-ALPHA 开发板网络简介
ENET1 的网络 PHY芯片为 SR8201F,通过 RMII 接口与 I.MX6ULL 相连,正点原子 I.MX6UALPHA 开发板的 ENET1 引脚与 NXP 官方的 I.MX6ULL EVK 开发板基本一样,唯独复位引脚不同。从图 33.2.8.1可以看出,正点原子 I.MX6U-ALPHA 开发板的 ENET1复位引脚ENET1_RST接到了 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。
SR8201F 内部是有寄存器的, I.MX6ULL 会读取 SR8201F 内部寄存器来判断当前的物理链接状态、连接速度(10M 还是 100M)和双工状态(半双工还是全双工)。 I.MX6ULL 通过 MDIO 接口来读取 PHY 芯片的内部寄存器, MDIO 接口有两个引脚, ENET_MDC 和 ENET_MDIO,ENET_MDC 提供时钟, ENET_MDIO 进行数据传输。一个 MDIO 接口可以管理 32 个 PHY 芯片,同一个 MDIO 接口下的这些 PHY 使用不同的器件地址来做区分, MIDO 接口通过不同的器件地址即可访问到相应的 PHY 芯片。 I.MX6U-ALPHA 开发板 ENET1 上连接的 SR8201F 器件地址为 0X2,
所示我们要修改 ENET1 网络驱动的话重点就三点:
①、 ENET1 复位引脚初始化。
②、 SR8201F 的器件 ID。
③、 SR8201F 驱动
关于 ENET2 网络驱动的修改也注意一下三点:
①、 ENET2 的复位引脚,从图 33.2.8.2 可以看出, ENET2 的复位引脚 ENET2_RST 接到了
I.MX6ULL 的 SNVS_TAMPER8 上。
②、 ENET2 所使用的 PHY 芯片器件地址,从图 33.2.8.2 可以看出, PHY 器件地址为 0X1。
③、 SR8201F 驱动, ENET1 和 ENET2 都使用的 SR8201F,所以驱动肯定是一样的。
2 网络 PHY 地址修改
首先修改 uboot 中的 ENET1 和 ENET2 的 PHY 地址和驱动,打开 mx6ull_alientek_emmc.h这个文件,找到如下代码:
所以示例代码 33.2.8.1 中理论上有三处要修改:
①、修改 ENET1 网络 PHY 的地址。
②、修改 ENET2 网络 PHY 的地址。
③、使能 REALTEK 公司的 PHY 驱动。
但是,由于我们开发板上 SR8201F 的 PHY 地址和默认的配置一样,因此只需要是能REALTEK 公司的 PHY 驱动,大家如果使用的其他品牌的开发板,那么就要根据实际情况来修改对应的 ENET1 和 ENET2 网络 PHY 地址。
修改后的网络 PHY 地址参数如下所示:
3、删除 uboot 中 74LV595 的驱动代码
74LV595 引脚冲突,所以删除
#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)
{
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);
}
gpio_direction_output(IOX_STCP, 0);
udelay(500);
/*
* shift register will be output to pins
*/
gpio_direction_output(IOX_STCP, 1);
for (i = 7; i >= 0; i--) {
gpio_direction_output(IOX_SHCP, 0);
gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
udelay(500);
gpio_direction_output(IOX_SHCP, 1);
udelay(500);
}
gpio_direction_output(IOX_STCP, 0);
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);
}
gpio_direction_output(IOX_STCP, 0);
udelay(500);
/*
* shift register will be output to pins
*/
gpio_direction_output(IOX_STCP, 1);
for (i = 7; i >= 0; i--) {
gpio_direction_output(IOX_SHCP, 0);
gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);
udelay(500);
gpio_direction_output(IOX_SHCP, 1);
udelay(500);
}
gpio_direction_output(IOX_STCP, 0);
udelay(500);
/*
* shift register will be output to pins
*/
gpio_direction_output(IOX_STCP, 1);
};
iox74lv_init 函数是 74LV595 的初始化函数, iox74lv_set 函数用于控制 74LV595 的 IO 输出
电平,将这两个函数全部删除掉!
在 mx6ull_alientek_emmc.c 中找到 board_init 函数,此函数是板子初始化函数,会被
board_init_r 调用, board_init 函数内容如下:
board_init 会调用 imx_iomux_v3_setup_multiple_pads 和 iox74lv_init 这两个函数来初始化74lv595 的 GPIO,将这两行删除掉。至此, mx6ull_alientek_emmc.c 中关于 74LV595 芯片的驱动代码都删除掉了,接下来就是添加 I.MX6U-ALPHA 开发板两个网络复位引脚了。
imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));
iox74lv_init();
4、添加 I.MX6U-ALPHA 开发板网络复位引脚驱动
在 mx6ull_alientek_emmc.c 中找到如下所示代码:
fec1_pads中
MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
fec2_pads中
MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
继续在文件 mx6ull_alientek_emmc.c 中找到函数 setup_iomux_fec,此函数默认代码如下:
函数 setup_iomux_fec 就是根据 fec1_pads 和 fec2_pads 这两个网络 IO 配置数组来初始化I.MX6ULL 的网络 IO。我们需要在其中添加网络复位 IO 的初始化代码,并且复位一下 PHY 芯片,修改后的 setup_iomux_fec 函数如下:
分别对应 ENET1 和 ENET2 的复位 IO 初始化,将这两个 IO 设置为输出并且硬件复位一下 LAN8720A,这个硬件复位很重要!复位结束以后一定要至少延时 150ms 才能操作 SR8201F,这个在 SR8201F 数据手册里面有详细要求的, 否则会导致 uboot 无法识别 SR8201F。
至此网络的复位引脚驱动修改完成,重新编译 uboot,然后将 u-boot.bin 烧写到 SD 卡中并启动.可以看到“Net: FEC1”这一行,提示当前使用的 FEC1 这个网口,也就是 ENET2。在 uboot 中使用网络之前要先设置几个环境变量,命令如下: 在 uboot 中使用网络之前要先设置几个环境变量,命令如下:
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主机 192.168.1.70
5 其他需要修改的地方
在 uboot 启动信息中会有“Board: MX6ULL 14x14 EVK”这一句,也就是说板子名字为“ MX6ULL 14x14 EVK”,要将其改为我们所使用的板子名字,比如“ MX6ULL ALIENTEKEMMC”或者“MX6ULL ALIENTEK NAND”。打开文件 mx6ull_alientek_emmc.c,找到函数checkboard,将其改为如下所示内容:
puts("Board: MX6ULL 14x14 EVK\n");
八 uboot 启动 Linux 测试
1 从 EMMC 启动 Linux 系统
具体见 正点原子驱动文档 33.4.1 从 EMMC 启动 Linux 系统
2 从网络启动 Linux 系统
从网络启动 linux 系统的唯一目的就是为了调试!不管是为了调试 linux 系统还是 linux 下的驱动。每次修改 linux 系统文件或者 linux 下的某个驱动以后都要将其烧写到 EMMC 中去测试,这样太麻烦了。我们可以设置 linux 从网络启动,也就是将 linux 镜像文件和根文件系统都放到 Ubuntu 下某个指定的文件夹中,这样每次重新编译 linux 内核或者某个 linux 驱动以后只需要使用 cp 命令将其拷贝到这个指定的文件夹中即可,这样就不用需要频繁的烧写 EMMC,这样就加快了开发速度。我们可以通过 nfs 或者 tftp 从 Ubuntu 中下载 zImage 和设备树文件,根文件系统的话也可以通过 nfs 挂载,不过本小节我们不讲解如何通过 nfs 挂载根文件系统,这个在讲解根文件系统移植的时候再讲解。这里我们使用 tftp 从 Ubuntu 中下载 zImage 和设备树文件,前提是要将 zImage 和设备树文件放到 Ubuntu 下的 tftp 目录中,具体方法在 30.4.4 小节讲解 tftp 命令的时候已经详细的介绍过了。
boot 移植到此结束,简单总结一下 uboot 移植的过程:
①、不管是购买的开发板还是自己做的开发板,基本都是参考半导体厂商的 dmeo 板,而半导体厂商会在他们自己的开发板上移植好 uboot、 linux kernel 和 rootfs 等,最终制作好 BSP包提供给用户。我们可以在官方提供的 BSP 包的基础上添加我们的板子,也就是俗称的移植。
②、我们购买的开发板或者自己做的板子一般都不会原封不动的照抄半导体厂商的 demo板,都会根据实际的情况来做修改,既然有修改就必然涉及到 uboot 下驱动的移植。
③、一般 uboot 中需要解决串口、 NAND、 EMMC 或 SD 卡、网络和 LCD 驱动,因为 uboot的主要目的就是启动 Linux 内核,所以不需要考虑太多的外设驱动。
④、在 uboot 中添加自己的板子信息,根据自己板子的实际情况来修改 uboot 中的驱动。