当前位置: 首页 > article >正文

56. Uboot移植实验

一、NXP官方Uboot编译与测试

1、将NXP提供的uboot拷贝到ubuntu中。

一个开发板也好运行uboot,DDR或者叫DRAM,串口,SD、EMMC、NAND。板子能工作。

测似结果:
1、uboot能正常启动
2、LCD驱动要根据所使用的屏幕修改。
3、NET初始化失败。

SD卡Formatter V4.0 格式化后,环境变量会被格式化掉。再烧录,
在这里插入图片描述

U-Boot 2016.03 (Feb 03 2025 - 19:31:00 +0800)

CPU:   Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 32C
Reset cause: WDOG
Board: MX6ULL 14x14 EVK
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment

Display: TFT43AB (480x272)
Video: 480x272x24
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc0 is current device
Net:   Board Net Initialization Failed
No ethernet found.
Normal Boot
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
switch to partitions #0, OK
mmc0 is current device
** No partition table - mmc 0 **
** No partition table - mmc 0 **
Booting from net ...
No ethernet found.
No ethernet found.
Bad Linux ARM zImage magic!
=>

环境变量没清是这样
在这里插入图片描述

二、移植NXP官方uboot到ALPHA开发板

2.1 添加板子默认配置文件
借鉴NXP官方6ULL EVK开发板,默认配置文件也用他的,
/uboot_m/configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_14x14_my_emmc_defconfig

新建my.sh

#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_my_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

修改mx6ull_14x14_my_emmc_defconfig

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

修改Kconfig
在这里插入图片描述

if TARGET_MX6ULL_MY_EMMC

config SYS_BOARD
default “mx6ull_my_emmc”

config SYS_VENDOR
default “freescale”

config SYS_CONFIG_NAME
default “mx6ull_my_emmc”

endif
修改MAINTAINERS
在这里插入图片描述

MX6ULLEVK BOARD
M:	Peng Fan <peng.fan@nxp.com>
S:	Maintained
F:	board/freescale/mx6ull_my_emmc/
F:	include/configs/mx6ull_my_emmc.h
F:	configs/mx6ull_my_emmc_defconfig
2.2添加板子对应的头文件

不同的板子,有一些需要配置的信息,一般是在一个头文件里面配置,每个板子有一个。对于NXP官方的6ULL EVK板子,这个头文件就是

/uboot_m/include/configs
 cp mx6ullevk.h mx6ull_my_emmc.h

在这里插入图片描述

2.3 添加板子对应的板级文件夹
每个板子都有特有的文件,也叫做板级文件。这里我们将6ULL EVK的板级文件直接拷贝过来。
/uboot_m/board/freescale
cp mx6ullevk/ mx6ull_my_emmc -r

在这里插入图片描述

重命名

/uboot_m/board/freescale/mx6ull_my_emmc
mv mx6ullevk.c mx6ull_my_emmc.c

在这里插入图片描述

修改Makefile
在这里插入图片描述

修改
在这里插入图片描述

#ifdef CONFIG_USE_PLUGIN
/*PLUGIN    plugin-binary-file    IRAM_FREE_START_ADDR*/
PLUGIN  board/freescale/mx6ull_my_emmc/plugin.bin 0x00907000
#else
2.4 修改uboot的配置界面

在这里插入图片描述

config TARGET_MX6ULL_9X9_EVK
    bool "Support mx6ull_9x9_evk"
    select MX6ULL
    select DM
    select DM_THERMAL

config TARGET_MX6ULL_MY_EMMC
    bool "Support mx6ull_my_emmc"
    select MX6ULL
    select DM
    select DM_THERMAL

source "board/freescale/mx6dqscm/Kconfig"
source "board/freescale/mx6sxscm/Kconfig"
source "board/freescale/mx6ull_my_emmc/Kconfig"
endif
2.5 使用新添加的板子配置并编译Uboot

编译

./my.sh

在这里插入图片描述

mx6ull_my_emm.c编译成.o,mx6ullevk里没有编译
在这里插入图片描述

查看.h文件有没有被引用

~/uboot_m/uboot_m$ grep -nR "mx6ull_my_emmc.h"
disk/.part.o.cmd:152:  include/configs/mx6ull_my_emmc.h \
disk/.part_dos.o.cmd:134:  include/configs/mx6ull_my_emmc.h \
drivers/block/.disk-uclass.o.cmd:133:  include/configs/mx6ull_my_emmc.h \
drivers/gpio/.mxc_gpio.o.cmd:142:  include/configs/mx6ull_my_emmc.h \
drivers/spi/.spi.o.cmd:134:  include/configs/mx6ull_my_emmc.h \
drivers/spi/.fsl_qspi.o.cmd:139:  include/configs/mx6ull_my_emmc.h \

至此,说明我们在uboot里成功添加了我们的板子。下载测试下。

2.6 LCD驱动修改

般 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,找到如下所示内容:
1、确定LCD IO初始化正确,mx6ull_alientek_emmc.c中的lcd_pads。

#ifdef CONFIG_VIDEO_MXS
static iomux_v3_cfg_t const lcd_pads[] = {
    MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_ENABLE__LCDIF_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_HSYNC__LCDIF_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_VSYNC__LCDIF_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA00__LCDIF_DATA00 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA01__LCDIF_DATA01 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA02__LCDIF_DATA02 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA03__LCDIF_DATA03 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA04__LCDIF_DATA04 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA05__LCDIF_DATA05 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA06__LCDIF_DATA06 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA07__LCDIF_DATA07 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA08__LCDIF_DATA08 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA09__LCDIF_DATA09 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA10__LCDIF_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA11__LCDIF_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA12__LCDIF_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA13__LCDIF_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA14__LCDIF_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA15__LCDIF_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA16__LCDIF_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA17__LCDIF_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA18__LCDIF_DATA18 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA19__LCDIF_DATA19 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA20__LCDIF_DATA20 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA21__LCDIF_DATA21 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA22__LCDIF_DATA22 | MUX_PAD_CTRL(LCD_PAD_CTRL),
    MX6_PAD_LCD_DATA23__LCDIF_DATA23 | MUX_PAD_CTRL(LCD_PAD_CTRL),

    /* LCD_RST */
  	MX6_PAD_SNVS_TAMPER9__GPIO5_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),

    /* Use GPIO for Brightness adjustment, duty cycle = period. */
    MX6_PAD_GPIO1_IO08__GPIO1_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
};

改为

/* LCD_RST */
//  	MX6_PAD_SNVS_TAMPER9__GPIO5_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),

2、LCD参数,mx6ull_alientek_emmc.c中的displays。fb_videomode表示RGB LCD参数。

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
} } };
size_t display_count = ARRAY_SIZE(displays);
	MX6ULL_LCDIF1_BASE_ADDR      (AIPS2_OFF_BASE_ADDR + 0x48000)
	AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000)
	ATZ2_BASE_ADDR              AIPS2_ARB_BASE_ADDR
AIPS2_ARB_BASE_ADDR             0x02100000
	MX6ULL_LCDIF1_BASE_ADDR = 0x02100000 +  0x80000 +  0x48000 = 0x21c8000

在这里插入图片描述

void do_enable_parallel_lcd(struct display_info_t const *dev)
{
    enable_lcdif_clock(dev->bus);

    imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));

    /* Reset the LCD */
    gpio_direction_output(IMX_GPIO_NR(5, 9) , 0);
    udelay(500);
    gpio_direction_output(IMX_GPIO_NR(5, 9) , 1);

    /* Set Brightness to high */
    gpio_direction_output(IMX_GPIO_NR(1, 8) , 1);
}

改为

 /* Reset the LCD */
    // gpio_direction_output(IMX_GPIO_NR(5, 9) , 0);
    // udelay(500);
    // gpio_direction_output(IMX_GPIO_NR(5, 9) , 1);

修改参数
在这里插入图片描述

12 .left_margin = 88, //HBPD
13 .right_margin = 40 //HFPD
14 .upper_margin = 32, //VBPD
15 .lower_margin = 13, //VFBD
16 .hsync_len = 48, //HSPW
17 .vsync_len = 3, //VSPW
结构体 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,也就是不使用隔行扫描。
可以看出,这些参数和我们第二十四章讲解 RGB LCD 的时候参数基本一样,唯一不同的像素时钟 pixclock 的含义不同,以正点原子的 7 寸 1024*600 分辨率的屏幕(ATK7016)为例,屏幕要求的像素时钟为 51.2MHz,因此:
pixclock=(1/51200000)*10^12=19531

struct display_info_t const displays[] = {{
    .bus = MX6UL_LCDIF1_BASE_ADDR,
    .addr = 0,
    .pixfmt = 24,
    .detect = NULL,
    .enable = do_enable_parallel_lcd,
    .mode   = {
        .name           = "TFT4384",
        .xres           = 800,
        .yres           = 480,
        .pixclock       = 19531,
        .left_margin    = 88,
        .right_margin   = 40,
        .upper_margin   = 32,
        .lower_margin   = 13,
        .hsync_len      = 48,
        .vsync_len      = 3,
        .sync           = 0,
        .vmode          = FB_VMODE_NONINTERLACED
} } };

Panel环境变量表示LCD ID。
打开 mx6ull_my_emmc.h,找到所有如下语句:
panel=TFT43AB将其改为: panel=TFT4384

SD全部格式化
在这里插入图片描述
在这里插入图片描述

U-Boot 2016.03 (Feb 04 2025 - 16:19:07 +0800)

CPU:   Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 32C
Reset cause: POR
Board: MX6ULL 14x14 EVK
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment

Display: TFT4384 (800x480)
Video: 800x480x24
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc0 is current device
Net:   Board Net Initialization Failed
No ethernet found.
Normal Boot
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
switch to partitions #0, OK
mmc0 is current device
** No partition table - mmc 0 **
** No partition table - mmc 0 **
Booting from net ...
No ethernet found.
No ethernet found.
Bad Linux ARM zImage magic!

环境变量panel=TFT4384,识别出TFT4384,LCD屏显示NXP图标。

如果 EMMC 中的环境变量 panel 不等于 TFT7016,那么 LCD 显示肯定不正常,我们只需要在uboot 中修改 panel 的值为 TFT7016 即可,在 uboot 的命令模式下输入如下命令:
setenv panel TFT4384
saveenv

2.7 网络驱动修改

I.MX6UL/ULL 内部有个以太网 MAC 外设,也就是 ENET,需要外接一个 PHY 芯片来实现网络通信功能,也就是内部 MAC+外部 PHY 芯片的方案。大家可能听过 DM9000 这个网络芯片,在一些没有内部 MAC 的 CPU 中,比如三星的 2440, 4412 等,就会采用 DM9000 来实现联网功能。 DM9000 提供了一个类似 SRAM 的访问接口,主控 CPU 通过这个接口即可与DM9000 进行通信, DM9000 就是一个 MAC+PHY 芯片。这个方案就相当于外部 MAC+外部PHY,那么 I.MX6U 这样的内部 MAC+PHY 芯片与 DM9000 方案比有什么优势吗?那优势大了去了!首先就是通信效率和速度,一般 SOC 内部的 MAC 是带有一个专用 DMA 的,专门用于处理网络数据包,采用 SRAM 来读写 DM9000 的速度是压根就没法和内部 MAC+外部 PHY 芯片的速度比。采用外部 DM9000 完全是无奈之举,谁让 2440, 4412 这些芯片内部没有以太网外设呢,现在又想用有线网络,没有办法只能找个 DM9000 的方案。从这里也可以看出,三星的 2440、 4412 这些芯片设计之初就不是给工业产品用的,他们是给消费类电子使用的,比如手机、平板等,手机或平板要上网,可以通过 WIFI 或者 4G,我是没有见过哪个手机或者平板上网是要接根网线的。正点原子的 I.MX6U-ALPHA 开发板也可以通过 WIFI 或者 4G 上网,这个是后话了。
I.MX6UL/ULL 有两个网络接口 ENET1 和 ENET2,正点原子的 I.MX6U-ALPHA 开发板提供了这两个网络接口,其中 ENET1 和 ENET2 都使用 LAN8720A 作为 PHY 芯片。 NXP 官方的I.MX6ULL EVK 开发板使用 KSZ8081 这颗 PHY 芯片, LAN8720A 相比 KSZ8081 具有体积小、外围器件少、价格便宜等优点。直接使用 KSZ8081 固然可以,但是我们在实际的产品中不一定会使用 KSZ8081,有时候为了降低成本会选择其他的 PHY 芯片,这个时候就有个问题:换了PHY 芯片以后网络驱动怎么办?为此,正点原子的 I.MX6U-ALPHA 开发板将 ENET1 和 ENET2的 PHY 换成了 LAN8720A,这样就可以给大家讲解更换 PHY 芯片以后如何调整网络驱动,使网络工作正常。

6ULL网络方案采用内部MAC+外部PHY,6ULL官方开发板使用的PHY芯片就是KSZ8081。正点原子的ALPHA开发板没有使用KSZ8081,我们使用的LAN8720A。因此要修改驱动。
LAN872有一个管理接口,叫做MDIO,两根线,MDIO和MDC,一个MDIO接口可以管理32个PHY芯片。MIDO通过PHY ADDR来确定访问那个PHY芯片。ALPHA开发板ENET1的PHY ADDR是0x0,ENET2的PHY ADDR是0X1.
每个LAN8720都有一个复位引脚,ENET1是SNVS_TAMPER7,ENET2是SNVS_TAMPER8。

LAN8720驱动,因为所有的PHY,其前16个寄存器一模一样,因此uboot里面已经写好了通用PHY驱动,所以理论上不需要修改。

驱动修改
1、修改PHY ADDR
/uboot_m/uboot_m/include/configs/mx6ull_my_emmc.h

#ifdef CONFIG_CMD_NET
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_MII
#define CONFIG_FEC_MXC
#define CONFIG_MII
#define CONFIG_FEC_ENET_DEV     1

#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE            ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR          0x2
#define CONFIG_FEC_XCV_TYPE             RMII
#elif (CONFIG_FEC_ENET_DEV == 1)
#define IMX_FEC_BASE            ENET2_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR      0x1
#define CONFIG_FEC_XCV_TYPE     RMII
#endif
#define CONFIG_ETHPRIME         "FEC"

#define CONFIG_PHYLIB
#define CONFIG_PHY_MICREL
#endif

改为

#if (CONFIG_FEC_ENET_DEV == 0)
#define IMX_FEC_BASE            ENET_BASE_ADDR
#define CONFIG_FEC_MXC_PHYADDR          0x0

#define CONFIG_PHY_SMSC
2、删除原有的74LV595相关代码。
// #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)


// 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)
//{
//
//}

//void iox74lv_set(int index)
//{
//
//}

3、添加ALPHA开发板的网络复位IO

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

修改

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


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

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

修改

static void setup_iomux_fec(int fec_id)
{
    if (fec_id == 0)
        imx_iomux_v3_setup_multiple_pads(fec1_pads,
                         ARRAY_SIZE(fec1_pads));
    else
        imx_iomux_v3_setup_multiple_pads(fec2_pads,
                         ARRAY_SIZE(fec2_pads));
}

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
修改

/**
 * genphy_update_link - update link status in @phydev
 * @phydev: target phy_device struct
 *
 * Description: Update the value in phydev->link to reflect the
 *   current link value.  In order to do this, we need to read
 *   the status register twice, keeping the second value.
 */
int genphy_update_link(struct phy_device *phydev)
{
    unsigned int mii_reg;

    /*
     * 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);

    /*
     * If we already saw the link up, and it hasn't gone down, then
     * we don't need to wait for autoneg again
     */
    if (phydev->link && mii_reg & BMSR_LSTATUS)
        return 0;

    if ((phydev->autoneg == AUTONEG_ENABLE) &&
        !(mii_reg & BMSR_ANEGCOMPLETE)) {
        int i = 0;

        printf("%s Waiting for PHY auto negotiation to complete",
            phydev->dev->name);
        while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
            /*
             * Timeout reached ?
             */
            if (i > PHY_ANEG_TIMEOUT) {
                printf(" TIMEOUT !\n");
                phydev->link = 0;
                return 0;
            }

            if (ctrlc()) {
                puts("user interrupt!\n");
                phydev->link = 0;
                return -EINTR;
            }

            if ((i++ % 500) == 0)
                printf(".");

            udelay(1000);   /* 1 ms */
            mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
        }
        printf(" done\n");
        phydev->link = 1;
    } else {
        /* Read the link a second time to clear the latched state */
        mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);

        if (mii_reg & BMSR_LSTATUS)
            phydev->link = 1;
        else
            phydev->link = 0;
    }

    return 0;
}

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

成功了

U-Boot 2016.03 (Feb 04 2025 - 18:54:14 +0800)

CPU:   Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 38C
Reset cause: POR
Board: MX6ULL 14x14 EVK
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Display: TFT4384 (800x480)
Video: 800x480x24
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc0 is current device
Net:   FEC1
Normal Boot
Hit any key to stop autoboot:  0

在这里插入图片描述

改到ETH0

#define CONFIG_FEC_ENET_DEV     0

在这里插入图片描述

2.8 其他需要修改的地方

在 uboot 启动信息中会有“Board: MX6ULL 14x14 EVK”这一句,也就是说板子名字为“ MX6ULL 14x14 EVK”,要将其改为我们所使用的板子名字,比如“ MX6ULL ALIENTEK EMMC”或者“MX6ULL ALIENTEK NAND”。打开文件 mx6ull_alientek_emmc.c,找到函数checkboard,将其改为如下所示内容:

int checkboard(void)
{
    if (is_mx6ull_9x9_evk())
        puts("Board: MX6ULL 9x9 EVK\n");
    else
        puts("Board: MX6ULL 14x14 EVK\n");

    return 0;
}

改为

int checkboard(void)
{
    if (is_mx6ull_9x9_evk())
        puts("Board: MX6ULL 9x9 EVK\n");
    else
        puts("Board: MX6ULL MY EMMC\n");

    return 0;
}

在这里插入图片描述

打印环境变量

U-Boot 2016.03 (Feb 04 2025 - 19:07:16 +0800)

CPU:   Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 43C
Reset cause: POR
Board: MX6ULL MY EMMC
I2C:   ready
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Display: TFT4384 (800x480)
Video: 800x480x24
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc0 is current device
Net:   FEC1
Normal Boot
Hit any key to stop autoboot:  0
=> print
baudrate=115200
board_name=EVK
board_rev=14X14
boot_fdt=try
bootargs=console=ttymxc0,115200 root=/dev/nfs ip=dhcp nfsroot=:,v3,tcp
bootcmd=run findfdt;mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; then if
run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot
; else run netboot; fi; fi; else run netboot; fi
bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};
bootdelay=3
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc0
ethact=FEC1
ethaddr=00:04:9f:04:d2:35
ethprime=FEC
fdt_addr=0x83000000
fdt_file=imx6ull-14x14-evk.dtb
fdt_high=0xffffffff
findfdt=if test $fdt_file = undefined; then if test $board_name = EVK && test $b
oard_rev = 9X9; then setenv fdt_file imx6ull-9x9-evk.dtb; fi; if test $board_nam
e = EVK && test $board_rev = 14X14; then setenv fdt_file imx6ull-14x14-evk.dtb;
fi; if test $fdt_file = undefined; then echo WARNING: Could not determine dtb to
 use; fi; fi;
gatewayip=192.168.32.1
get_cmd=dhcp
image=zImage
initrd_addr=0x83800000
initrd_high=0xffffffff
ip_dyn=yes
ipaddr=192.168.32.50
loadaddr=0x80800000
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_ma
ss_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_st
orage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass
_storage.iSerialNumber="" clk_ignore_unused
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
mmcautodetect=yes
mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || tes
t ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr};
else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT;
fi; fi; else bootz; fi;
mmcdev=0
mmcpart=1
mmcroot=/dev/mmcblk0p2 rootwait rw
netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfs
root=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then se
tenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${
boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_
file}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; the
n bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
netmask=255.255.255.0
panel=TFT4384
script=boot.scr
serverip=192.168.32.100

Environment size: 2657/8188 bytes
=>

在启动 Linux 内核之前我们先来学习两个重要的环境变量 bootcmd 和 bootargs。

三、bootcmd和bootargs环境变量

3.1 bootcmd环境变量
宏CONFIG_BOOTCOMMAND也可以设置bootcmd的值。

   "run findfdt;" \
   "mmc dev ${mmcdev};" \
   "mmc dev ${mmcdev}; if mmc rescan; then " \
	   "if run loadbootscript; then " \
		   "run bootscript; " \
	   "else " \
		   "if run loadimage; then " \
			   "run mmcboot; " \
		   "else run netboot; " \
		   "fi; " \
	   "fi; " \
   "else run netboot; fi"

Findfdt 设置fdt_file环境变量,也就是dtb文件名字。

mmc dev 1 //切换到emmc
fatload mmc 1:1 80800000 zImage
fatload mmc 1:1 83000000 imx6ull-14x14-evk.dtb
booz 80800000 - 83000000

"loadbootscript=" \
	"fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
展开以后:fatload mmc 1:1 80800000 boot.scr

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
	展开:fatload mmc 1:1 80800000 zImage
	

"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
	展开
fatload mmc 1:1 83000000 imx6ull-14x14-evk.dtb

bootz ${loadaddr} - ${fdt_addr};
booz 80800000 - 83000000

3.2 bootargs环境变量
宏CONFIG_BOOTARGS也可以设置bootargs的值

mmcargs=setenv bootargs console=${console},${baudrate} " \
		CONFIG_BOOTARGS_CMA_SIZE \
		"root=${mmcroot}\0" \

展开以后就是:
bootargs console= ttymxc0,115200 root=/dev/mmcblk1p2

Bootargs是会传递给Linux内核,设置了一些东西

Bootargs环境变量也叫做命令行参数。

四、uboot启动Linux测试

4.1 从EMMC启动
1、首先查看EMMC里面是否有系统,linux镜像zImage和.dtb文件。先将当前设备切换到EMMC:

mmc dev 1	//切换到EMMC
mmcinfo		//查看信息
fatls mmc 1:1  //查看EMMC分区1里面的文件
fatload mmc 1:1 80800000 zImage //将zimage下载到DDR的0x80800000处
fatload mmc 1:1 83000000 imx6ull-14x14-emmc-4.3-800x480-c.dtb //将dtb读取到0X83000000
bootz 8080000083000000 //启动内核

如果内核启动成功,说明uboot支持emmc启动,验证成功。

4.2 从网络启动
\8、系统镜像\1、出厂系统镜像\2、kernel镜像\linux-imx-4.1.15-2.1.0-gb78e551-v1.4
在这里插入图片描述

imx6ull-14x14-emmc-4.3-800x480-c.dtb、zImage复制到tftp服务器

先启动下tftp服务器

sudo service tftpd-hpa restart	
tftp 80800000 zImage		//从tftp服务器下载zimage
tftp 83000000 imx6ull-14x14-emmc-4.3-800x480-c.dtb //从tftp服务器下载.dtb	
bootz 80800000 - 83000000//启动系统

五、uboot DDR初始化

1、裸 机
imxdownload软件下载,会在bin文件头部添加IVT DCD数据,

2、uboot
uboot编译生成u-boot.imx。u-boot.imx已经包含了IVT DCD数据。
u-boot.imx的头部信息是怎么添加的?
u-boot.imx的DCD中的DDR初始化代码该怎么修改。
uboot编译会输出
./tools/mkimage -n board/freescale/mx6ull_alientek_emmc/imximage.cfg.cfgtmp -T imximage -e 0x87800000 -d u-boot.bin u-boot.imx

可以看出uboot使用/tools/mkimage工具,向u-boot.bin添加board/freescale/mx6ull_alientek_emmc/imximage.cfg.cfgtmp文件信息,从而得到u-boot.imx。

默认只有imximage.cfg文件,imximage.cfg里面保存的就是DCD数据。DDR初始化也此文件里面。
我们要修改DDR初始化代码,就需要修改imximage.cfg文件。此文件默认拷贝的NXP给IMX6ULL EVK开发板写的,默认是给512MB DDR3L写的。


http://www.kler.cn/a/534963.html

相关文章:

  • 02.06 网络编程_概述
  • 02-合并两个有序数组
  • 文献阅读分享《新闻推荐中的审议式多样性:操作化与实验用户研究》
  • 【吾爱出品】开源桌面组件:widgets
  • TensorFlow是个啥玩意?
  • 【C++】STL——stack的底层实现
  • 【银河麒麟高级服务器操作系统】系统日志Call trace现象分析及处理全流程
  • Redis持久化-秒杀系统设计
  • flappy-bird-gymnasium
  • 【Linux系统】线程:线程的优点 / 缺点 / 超线程技术 / 异常 / 用途
  • 深入理解 Unix Shell 管道 Pipes:基础和高级用法 xargs tee awk sed等(中英双语)
  • 第二节 程序设计的基本结构
  • 无人机在铁路隧道检查应用技术详解
  • DeepSeek之python实现API应用
  • 【LLM运用】在Ubuntu上Cosyvoice的部署
  • java异常分类,异常处理,面试中常见异常问题!
  • Java并发面试题(题目来源JavaGuide)
  • 算法设计与分析三级项目--管道铺设系统
  • css-根据不同后端返回值返回渲染不同的div样式以及公共组件设定
  • Spring JDBC模块解析 -深入SqlParameterSource
  • 论文解读 | NeurIPS'24 Spotlight ChronoMagic-Bench 评估文本到视频生成的质变幅度评估基准...
  • B站自研的第二代视频连麦系统(上)
  • 拧紧“安全阀”,AORO-P300 Ultra防爆平板畅通新型工业化通信“大动脉”
  • .net的一些知识点3
  • Windows本地部署DeepSeek-R1大模型并使用web界面远程交互
  • 网络面试题(第一部分)