【IMX6ULL学习笔记】五、U-BOOT移植与解析

一、移植自定义开发板流程

1、添加 mx6ull_kodo_emmc_defconfig 配置文件(.config)

在 /config s目录下,复制 mx6ull_14x14_evk_emmc_defconfig 文件,重命名为 mx6ull_kodo_emmc_defconfig 并修改其中内容,如下:

CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_kodoboard/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_KODO_EMMC=y
CONFIG_CMD_GPIO=y

注: 在执行 make xxx_defconfig 生成 .config 时,会将 mx6ull_kodo_emmc_defconfig 中定义的配置项写入到 .config 文件中,如:
image
image

2、添加 mx6ull_kodo_board.h 配置文件

在 /include/configs 目录下定义了开发板的配置头文件 ,复制 mx6ullevk.h 重命名为 mx6ull_kodo_board.h 并修改文件中的条件编译,如下:

/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc.
 *
 * Configuration settings for the Freescale i.MX6UL 14x14 EVK board.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#ifndef __MX6ULL_KODOBOARD_CONFIG_H
#define __MX6ULL_KODOBOARD_CONFIG_H

#include <asm/arch/imx-regs.h>
#include <linux/sizes.h>
#include "mx6_common.h"
#include <asm/imx-common/gpio.h>

3、添加 mx6ull_kodoboard 板级文件夹

添加板级文件,在 /board/freescale 目录下,复制 mx6ullevk 文件夹重命名为 mx6ull_kodoboard 并修改文件夹内的文件名,文件夹中内容对比如下:
image
将板级文件名修改为自定义的开发板名称,这里修改 mx6ullevk.c 文件为 mx6ull_kodoboard.c 文件。还需要修改 imximage.cfg 、Kconfig、Makefile中的内容,依次如下所示:

(1) imximage.cfg 文件:文件定义了 i.mx6ull 芯片启动的头部信息

#ifdef CONFIG_USE_PLUGIN
/*PLUGIN    plugin-binary-file    IRAM_FREE_START_ADDR*/
PLUGIN	board/freescale/mx6ull_kodoboard/plugin.bin 0x00907000  //指向mx6ull_kodoboard目录
#else

注:必须指向 /board/freescale/mx6ull_kodoboard 目录 plugin.bin 文件。

(2)Kconfig文件:执行 xxx_defconfig 时被调用

if TARGET_MX6ULL_KODO_EMMC

config SYS_BOARD
	default "mx6ull_kodoboard"           //定义自定义板级文件夹名

config SYS_VENDOR
	default "freescale"                  //使用芯片厂商

config SYS_CONFIG_NAME
	default "mx6ull_kodo_board"          //开发板的配置头文件名

endif
注:①、②、③、④、⑤

①、if TARGET_MX6ULL_KODO_EMMC 配置项
正确定义:CONFIG_TARGET_MX6ULL_KODO_EMMC=y
image
错误定义:CONFIG_TARGET_MX6ULL_KODO_EMMC_1=y
image
make xxx_defconfig 生成 .config 时,会根据 mx6ull_kodo_emmc_defconfig 中的 “CONFIG_TARGET_MX6ULL_KODO_EMMC=y” 配置项,使用"if TARGET_MX6ULL_KODO_EMMC"来决定 Kconfig 文件中的内容是否要写入到 .config 文件中去 ,所以:
"TARGET_MX6ULL_KODO_EMMC" : 必须与 “CONFIG_TARGET_MX6ULL_KODO_EMMC=y” 中的内容一致。

② default "mx6ull_kodoboard" 配置项
image
make 执行时会到文件夹名字为 "mx6ull_kodoboard" 的目录下寻找 Makefile 文件,所以:
"mx6ull_kodoboard": 必须与 /board/freescale 目录下自定义的板级文件夹名字相同。

③ default "freescale" 配置项
image
make 执行时会到文件夹名为 "freescale" 的目录下寻找名为 "mx6ull_kodoboard" 的文件夹下的 Makefile 文件,所以:
"freescale" :必须与 /board 目录下个产商板级文件夹名字相同。

④ default "mx6ull_kodo_board" 配置项
错误定义:default "mx6ull_kodo_board_1"
image
导致 config.h 错误引用:mx6ull_kodo_board_1.h
image
导致编译报错:/include/configs 目录下没有 mx6ull_kodo_board_1.h 文件
image
make 执行过程中会生成 config.h 文件,config.h 文件会引用 /include/configs 目录下名为 "mx6ull_kodo_board" 的头文件,所以:
"mx6ull_kodo_board" :必须与 /include/configs 目录下自定义的配置头文件名相同。

⑤ 在执行 make xxx_defconfig 生成 .config 时,会将 Kconfig 中定义的配置项写入到 .config 文件中
image

(3)Makefile文件:

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

obj-y  := mx6ull_kodoboard.o                  #依赖mx6ull_kodoboard.c文件

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

注:obj-y :依赖 /board/freescale/mx6ull 目录下的mx6ull_kodoboard.c文件

4、修改 Kconfig 文件

修改 /arch/arm/cpu/armv7/mx6/Kconfig 文件,添加开发板配置项:

config TARGET_MX6ULL_KODO_EMMC
	bool "mx6ull_kodo_emmc"
	select MX6ULL
	select DM
	select DM_THERMAL

image

并在文件尾部添加如下内容:

source "board/freescale/mx6ull_kodoboard/Kconfig"

image

5、LCD 驱动修改

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

开发板 LCD 的 IO 和背光 IO 和 NXP 官方 I.MX6ULL 开发板一致,所以 IO 部分就不用修改了。只需要修改 LCD 参数,打开文件 mx6ull_kodoboard.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
} } };

示例代码中定义了一个变量 displays,类型为 display_info_t,这个结构体是 LCD 信息结构体,其中包括了 LCD 的分辨率,像素格式,LCD 的各个参数等,定义在文件 arch/arm/include/asm/imx-common/video.h 中,定义如下:

struct display_info_t {
    int bus;
    int addr;
    int pixfmt;
    int (*detect)(struct display_info_t const *dev);
    void (*enable)(struct display_info_t const *dev);
    struct fb_videomode mode;
};

pixfmt 是像素格式,也就是一个像素点是多少位,如果是 RGB565 的话就是 16 位,如果是 888 的话就是 24 位,一般使用 RGB888。结构体 display_info_t 还有个 mode 成员变量,此成员变量也是个结构体,为 fb_videomode,定义在文件 include/linux/fb.h 中,定义如下:

struct fb_videomode {
    const char *name; /* optional */
    u32 refresh; /* optional */
    u32 xres;
    u32 yres;
    u32 pixclock;
    u32 left_margin;
    u32 right_margin;
    u32 upper_margin;
    u32 lower_margin;
    u32 hsync_len;
    u32 vsync_len;
    u32 sync;
    u32 vmode;
    u32 flag;
};

结构体 fb_videomode 里面的成员变量为 LCD 的参数,这些成员变量函数如下:

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 的含义:以正点原子的 7 寸 1024*600 分辨率的屏幕(ATK7016)为例,屏幕要求的像素时钟为 51.2MHz,因此:

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

移植使用的LCD为4.3寸800x480的屏幕,最终修改的配置参数如下:

struct display_info_t const displays[] = {{
	.bus = MX6UL_LCDIF1_BASE_ADDR,         //LCD base address
	.addr = 0,
	.pixfmt = 24,                          //RGB 24 BIT
	.detect = NULL,                        
	.enable	= do_enable_parallel_lcd,      //RESET AND ENABLE
	.mode	= {
		.name		= "KODO_TFT4384",
		.xres           = 800,
		.yres           = 480,
		.pixclock       = 32258,       //PIXCLOCK = (1/31000000)*10^12
		.left_margin    = 88,
		.right_margin   = 40,
		.upper_margin   = 32,
		.lower_margin   = 12,
		.hsync_len      = 48,
		.vsync_len      = 3,
		.sync           = 0,
		.vmode          = FB_VMODE_NONINTERLACED
} } };
size_t display_count = ARRAY_SIZE(displays);
#endif

除修改屏幕参数,还需修改默认的屏幕环境变量,在mx6ull_kodoboard.h 文件中找到所有如下语句:

panel=TFT43AB

将其改为:

panel=KODO_TFT4384

也就是设置 panel 为 KODO_TFT4384,panel 的值要与屏幕参数结构体中的.name 成员变量的值一致。

6、网络驱动修改

LAN8720A 内部是有寄存器的,I.MX6ULL 会读取 LAN8720 内部寄存器来判断当前的物理链接状态、连接速度(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 上连接的 LAN8720A 器件地址为 0X0,ENET1 引脚与 NXP 官方的 I.MX6ULL EVK 开发板基本一样,唯独复位引脚不同,所示要修改 ENET1 网络驱动的话重点就三点:
①、ENET1 复位引脚初始化。
②、LAN8720A 的器件 ID。
③、LAN8720 驱动

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

在 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                          //保存环境变量

二、自定义开发板参数如何被写入 .config ,以及如何参与源码编译的

make xxx_defconfig

前面分析 U-boot 顶层 Makefile 时,执行该命令后会生成一个 conf 的软件 ,然后调用 conf 软件去执行源码根目录下的 Kconfig 文件,最终命令如下:

@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig

打开源码根目录的 Kconfig 文件,有以下内容:

#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "U-Boot $UBOOTVERSION Configuration"

config UBOOTVERSION
	string
	option env="UBOOTVERSION"

# Allow defaults in arch-specific code to override any given here
source "arch/Kconfig"

menu "General setup"

对比 menuconfig 配置界面:
image
图中的第一项配置 Architecture select 和 第二项配置 ARM architecture 应该在 source "arch/Kconfig" 包含的文件中定义,打开 /arch 目录下的 Kconfig 文件,有以下定义:
image
正好对应第一项配置 Architecture select ,该配置为“使用芯片所属架构”的配置,ARM架构对应 ARM architecture ,该文件后面调用了 "arch/arm" 目录下的 Kconfig 文件:
image
"arch/arm" 目录下的 Kconfig 文件中有以下内容 :
image
正好对应第二项配置 ARM architecture,该配置为“不同厂商不同系列的ARM架构芯片”的配置,其中就有 Freescale 的 MX6 系列,如下:
image
该文件调用了 "arch/arm/cpu/armv7/mx6" 目录下的 Kconfig 文件,如下:
image
打开 "arch/arm/cpu/armv7/mx6" 目录下的 Kconfig 文件,在移植 U-BOOT 时恰好在该文件中添加了自定义开发板的内容,如下:
image
image

该文件调用了 /board/freescale 目录下自定义的开发板板级文件夹 mx6ull_kodoboard 目录下的 Kconfig 文件,其内容如下:
image
而在 /configs 目录下自定义的 mx6ull_kodo_emmc_defconfig 文件中有以下定义:
image

在执行make xxx_defconfig 时,传入 mx6ull_kodo_emmc_defconfig 文件中定义的配置项,Kconfig 读取配置项的值来使能响应的功能,并把结果写入到 .config 文件中,其内容大致如下图所示:
image
图中内容与 Makefile 语法中的变量定义一样,于是可以在 Maakefile 中直接调用,完成源码的编译。

posted @ 2023-02-17 15:20  酷电玩家  阅读(748)  评论(0编辑  收藏  举报