您尚未登录。

楼主 # 2026-05-19 01:47:56

2074840899
会员
注册时间: 2026-05-19
已发帖子: 2
积分: 2

移植202504版本imx6ul的uboot

step 1:增加mx6ul_14x14_nes_game_emmc_defconfig(由mx6ul_14x14_evk_emmc_defconfig复制修改而来)
step 2:修改mx6ul_14x14_nes_game_emmc_defconfig中的内容,下边为修改内容
step 2.1:CONFIG_DEFAULT_DEVICE_TREE="imx6ul-14x14-nes-game-emmc"
step 2.2:CONFIG_IMX_CONFIG="board/freescale/mx6ul_14x14_nes_game_emmc/imximage.cfg"
step 2.3:CONFIG_TARGET_MX6UL_14X14_NES_GAME_EMMC=y
注意点: mx6ul_14x14_nes_game_emmc_defconfig与TARGET_MX6UL_14X14_NES_GAME_EMMC必须严格对应
即_defconfig之前文件名与TARGET_之后文件名相同
step 3:修改编译脚本imx6ul_nes_game_compile.sh
step 3.1:make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- mx6ul_14x14_nes_game_emmc_defconfig
step 4: 增加mx6ul_14x14_nes_game_emmc.h,并修改头文件的防重复添加的宏(由mx6ul_14x14_evk.h修改)
step 5: 增加board/freescale/mx6ul_14x14_nes_game_emmc文件夹(由mx6ul_14x14_evk复制而来)
step 5.1 修改mx6ul_14x14_evk.c为mx6ul_14x14_nes_game_emmc.c,同时修改内容,修改如下
修改点1: #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG-----board_late_init函数中
env_set("board_name", "imx6ul_nes_game_emmc");
修改点2: if (is_mx6ul_9x9_evk())---------checkboard函数中
puts("Board: MX6UL 9x9 EVK\n");
else
puts("Board: IMX6UL 14x14 NES GAME EMMC BOARD\n");
step 5.2 修改MAINTAINERS文件中相关内容,修改如下
F: board/freescale/mx6ul_14x14_nes_game_emmc/
F: include/configs/mx6ul_14x14_nes_game_emmc.h
F: configs/mx6ul_14x14_nes_game_emmc_defconfig
step 5.3 修改imximage.cfg文件,修改如下
PLUGIN board/freescale/mx6ul_14x14_nes_game_emmc/plugin.bin 0x00907000
step 5.4 修改Kconfig文件,修改如下
if TARGET_MX6UL_14X14_NES_GAME_EMMC
config SYS_BOARD
default "mx6ul_14x14_nes_game_emmc"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "mx6ul_14x14_nes_game_emmc"
step 5.5 修改Makefile,修改如下
obj-y := mx6ul_14x14_nes_game_emmc.o
step 6:修改arch/arm/mach-imx/mx6/修改Kconfig文件,修改如下
config TARGET_MX6UL_14X14_NES_GAME_EMMC------新增
bool "mx6ul_14x14_nes_game_emmc"
depends on MX6UL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
select SUPPORT_SPL
select IMX_MODULE_FUSE
select OF_SYSTEM_SETUP
imply CMD_DM
select FSL_CAAM
select FSL_BLOB
select ARCH_MISC_INIT

source "board/freescale/mx6ul_14x14_nes_game_emmc/Kconfig"------新增

step 7: 修改arch/arm/dts中设备树
step 7.1: 增加imx6ul-14x14-nes-game-emmc.dts(由imx6ul-14x14-evk-emmc.dts复制修改)
修改:#include "imx6ul-14x14-nes-game.dts"
step 7.2: 增加imx6ul-14x14-nes-game.dtsi(由imx6ul-14x14-evk.dtsi复制修改)
step 7.3: 增加imx6ul-14x14-nes-game.dts(由imx6ul-14x14-evk.dts复制修改)
修改: #include "imx6ul-14x14-nes-game.dtsi"
/ {
model = "Freescale i.MX6 UltraLite 14x14 Nes_Game_Emmc Board";
compatible = "fsl,imx6ul-14x14-nes-game-emmc", "fsl,imx6ul";
};
step 7.4: 增加imx6ul-14x14-nes-game-emmc-u-boot.dtsi(由imx6ul-14x14-evk-emmc-u-boot.dtsi复制修改)
修改:: #include "imx6ul-14x14-nes-game-u-boot.dtsi"
step 7.5: 增加imx6ul-14x14-nes-game-u-boot.dtsi(由imx6ul-14x14-evk-u-boot.dtsi复制修改)
step 7.6: (optional)可在imx6ul-14x14-nes-game-emmc.dts显式增加#include "imx6ul-14x14-nes-game-emmc-u-boot.dtsi"
step 7.7: 修改Makefile,dtb-$(CONFIG_MX6UL) +=中新增imx6ul-14x14-nes-game-emmc.dtb \

step 8: 修改增加mx6ul_14x14_nes_game_emmc.h,修改如下
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = imx6ul_nes_game_emmc; then " \
"setenv fdt_file imx6ul-14x14-nes-game-emmc.dtb; fi; " \

step 9: 使用网络,只要设置如下内容即可

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

step 10: 将SD进行分区,分区脚本如下:
#!/bin/bash

SD卡一键分区脚本(470MB:100MB FAT32 + 370MB ext4)

SD_CARD=/dev/sdb

echo "=========================================="
echo "SD卡一键分区脚本"
echo "目标设备: ${SD_CARD}"
echo "=========================================="

检查是否为root权限

if [ "$EUID" -ne 0 ]; then
echo "请使用 sudo 运行此脚本"
exit 1
fi

卸载所有分区

echo "卸载所有分区..."
sudo umount ${SD_CARD}* 2>/dev/null

创建分区表

echo "创建分区表..."
sudo parted ${SD_CARD} --script mklabel msdos

创建第一个分区(100MB FAT32)

echo "创建分区1(100MB FAT32)..."
sudo parted ${SD_CARD} --script mkpart primary fat32 1MiB 100MiB

创建第二个分区(370MB ext4)

echo "创建分区2(剩余空间 ext4)..."
sudo parted ${SD_CARD} --script mkpart primary ext4 100MiB 100%

格式化分区1

echo "格式化分区1为FAT32..."
sudo mkfs.vfat -F 32 ${SD_CARD}1

格式化分区2

echo "格式化分区2为ext4..."
sudo mkfs.ext4 ${SD_CARD}2

echo "=========================================="
echo "分区完成!"
echo "分区1: ${SD_CARD}1 (100MB FAT32)"
echo "分区2: ${SD_CARD}2 (370MB ext4)"
echo "=========================================="

step 11: 将sd卡分区1与分区2添加"777"权限
step 11.1: sudo chmod 777 /media/你的linux登录用户名/分区1对应的文件夹
step 11.2: sudo chmod 777 /media/你的linux登录用户名/分区2对应的文件夹
step 11.3: 将zImage与对应的设备树文件(xxx.dtb)复制到分区1中

step 12: 修改为由SD卡启动
step 12.1: 修改mx6ul_14x14_nes_game_emmc.h中mmcpart=1对应分区1
step 12.2: 修改mx6ul_14x14_nes_game_emmc.h中mmcroot=/dev/mmcblk0p2 rootwait rw 根文件系统指向 SD 卡 2 分区
step 12.3: 修改mx6ul_14x14_nes_game_emmc_defconfig中CONFIG_SYS_MMC_ENV_DEV=0

最近编辑记录 2074840899 (2026-05-19 01:57:12)

离线

#1 2026-05-27 13:39:05

小兵
会员
注册时间: 2026-05-27
已发帖子: 23
积分: 23

Re: 移植202504版本imx6ul的uboot

移植步骤整体方向是对的,不过 i.MX6UL 新增板级支持时,除了文件名/TARGET 对齐,还建议重点核对 SPL、imximage 和 pinmux 这几处,否则很容易“能编译但不能启动”。

可以按这个清单再过一遍:

  1. CONFIG_TARGET_...、defconfig 文件名、SYS_BOARDSYS_CONFIG_NAME、board 目录名必须完全一致;

  2. imximage.cfg 里的 DCD/PLUGIN 是否适配你自己的 DDR、电源和启动介质,不能只复制 EVK;

  3. 如果走 eMMC,确认 USDHC 的 iomux、pad 配置、供电、reset 没沿用 EVK 不匹配的管脚;

  4. arch/arm/dts/Makefile 加了 dtb 后,确认最终编译产物里确实生成并打包了对应 dtb;

  5. SPL 阶段如果启用,board_init_f、DDR init、clock init、watchdog 这些也要跟板子匹配;

  6. findfdt 只影响运行时选择 dtb,不等于启动镜像里一定带了这个 dtb,最好用 dumpimage 或编译输出确认。

如果现在已经能进 U-Boot prompt,主要查 env/fdt/emmc;如果连 SPL/U-Boot 都没打印,优先查 imximage.cfg、DDR 初始化和启动介质管脚。

离线

楼主 #3 2026-06-06 12:35:17

2074840899
会员
注册时间: 2026-05-19
已发帖子: 2
积分: 2

Re: 移植202504版本imx6ul的uboot

================================================================================
SiI9022A HDMI Transmitter - U-Boot移植教程 (DM Bridge)
适用: i.MX6ULL + SiI9022A | U-Boot 2025.04 (Driver Model)
================================================================================
硬件连接 :
I2C2_SCL (UART5_TX) -> SCL (I2C addr: 0x39)
I2C2_SDA (UART5_RX) -> SDA
LCD_CLK -> PCLK
LCD_DE -> DE
LCD_HSYNC -> HSYNC
LCD_VSYNC -> VSYNC
LCD_DATA[3:7] -> D[0:7] (Blue)
LCD_DATA[10:15] -> D[8:15] (Green)
LCD_DATA[19:23] -> D[16:23] (Red)
LCD_DATA16 (GPIO3_IO21) -> RESET# (低有效)
SNVS_TAMPER3 (GPIO5_IO03) -> INT# (低有效,下降沿触发)

================================================================================
Step 1: 复制驱动文件
================================================================================

将文件替换到 U-Boot 源码:
sii902x.h -> uboot.../drivers/video/sii902x.h
sii902x.c -> uboot.../drivers/video/sii902x.c

================================================================================
Step 2: 修改 drivers/video/Makefile
================================================================================

在 lt8912b 行之后添加:
obj-$(CONFIG_VIDEO_SII902X) += sii902x.o

================================================================================
Step 3: 修改 drivers/video/Kconfig
================================================================================

在 VIDEO_LT8912B 配置项之后添加:

config VIDEO_SII902X
bool "Silicon Image SiI9022A HDMI transmitter"
depends on VIDEO
select VIDEO_BRIDGE
default n
help
Support for SiI9022A/9024A HDMI transmitter connected via I2C.
Uses UCLASS_VIDEO_BRIDGE for automatic probe via device tree.

================================================================================
Step 4: 修改 defconfig
================================================================================

文件: configs/mx6ull_14x14_nes_game_emmc_defconfig

添加:
CONFIG_VIDEO_BRIDGE=y
CONFIG_VIDEO_CONSOLE=y
CONFIG_VIDEO_SII902X=y
CONFIG_CONSOLE_MUX=y
CONFIG_DM_VIDEO=y

================================================================================
Step 5: 修改设备树
================================================================================

文件: arch/arm/dts/imx6ull-14x14-nes-game.dts (或对应 .dtsi)

5.1 引脚配置 (与 V3 相同):

&iomuxc {
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0

;

};

pinctrl_sii902x: sii902xgrp {
fsl,pins = <
MX6UL_PAD_LCD_DATA16__GPIO3_IO21 0x10b0
MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x10b0

;

};
};

5.2 I2C2 + SiI9022A 节点 (V4 关键变化 — 包含 port/endpoint):

&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";

sii9022a: hdmi@39 {
compatible = "sil,sii902x";
reg = <0x39>;
reset-gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;

/ 加上这两行!引用引脚配置 /
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sii902x>;

/ V4 新增: 视频模式选择 /
/ 1=480p 2=576p 3=720p60 4=720p50 /
/ 5=1080p60 6=1080p50 7=1024x768 8=800x600 /
/ 不设置则默认 3 (720p@60Hz) /
sil,video-mode = <3>;

/ V4 关键: port/endpoint 连接到 LCDIF /
/ 没有这个连接,video_link 框架找不到 SiI9022A /
port {
sii9022_in: endpoint {
remote-endpoint = <&lcdif_out>;
};
};
};
};

5.3 LCDIF 节点 (必须包含 port/endpoint + display-timings):

&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif>;
status = "okay";

/ V4 关键: port/endpoint 连接到 SiI9022A /
/ video_link 框架通过这个连接发现 SiI9022A 桥接芯片 /
port {
lcdif_out: endpoint {
remote-endpoint = <&sii9022_in>;
};
};

display0: display@0 {
bits-per-pixel = <24>;
bus-width = <24>;

display-timings {
native-mode = <&timing0>;
timing0: timing0 {
/ 必须与 sil,video-mode = <3> (720p@60Hz) 匹配 /
clock-frequency = <74250000>;
hactive = <1280>;
vactive = <720>;
hback-porch = <220>;
hfront-porch = <110>;
vback-porch = <20>;
vfront-porch = <5>;
hsync-len = <40>;
vsync-len = <5>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
};

port/endpoint 连接原理:
LCDIF port.endpoint <--remote-endpoint--> SiI9022A port.endpoint
(lcdif_out) (sii9022_in)

U-Boot video_link 框架通过 remote-endpoint 建立设备链:
LCDIF → SiI9022A
LCDIF probe 时自动发现 SiI9022A,自动调用 bridge attach/set_backlight。
如果没有 port/endpoint,LCDIF 不知道 SiI9022A 的存在,HDMI 不会初始化。

显示时序来源(后续修改对应的uboot文件):
video_link 框架只从 UCLASS_PANEL / UCLASS_DISPLAY 设备读取时序,
UCLASS_VIDEO_BRIDGE (SiI9022A) 的时序会被跳过。
实际时序来源: LCDIF 节点的 display-timings。
因此 LCDIF 的 display-timings 必须与 SiI9022A 的 sil,video-mode 一致!
如果 sil,video-mode = <1> (480p), LCDIF timing 也要改为 480p 参数。

SiI9022A 节点中不需要 display-timings 子节点 (驱动不会读取它)。

================================================================================
Step 6: 设置 HDMI 控制台输出 (可选)
================================================================================

文件: /home/kdd/linux_study/linux_program/imx6ull_nes_game_uboot/board/freescale/mx6ull_14x14_nes_game_emmc/mx6ull_14x14_nes_game_emmc.c

a.函数board_late_init中最后添加
#ifdef CONFIG_VIDEO

env_set("stdout", "serial,vidconsole");
env_set("stderr", "serial,vidconsole");

#endif

b.函数board_late_init中删除(同时将setup_lcd()函数源码删除即可)
setup_lcd();

================================================================================
Step 6.1: CONFIG_SPLASH_SCREEN 与 HDMI 控制台的关系 (重要)-----不设置splashimage环境变量即可
================================================================================

CONFIG_SPLASH_SCREEN 的作用:
启用后,U-Boot 启动时显示开机 Logo (splash screen)
同时会将 stdout 重定向到串口,防止启动 log 覆盖 Logo

影响: common/console.c:1199-1202
if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
}

================================================================================
Step 7: 修改文件: drivers/video/mxsfb.c
================================================================================

修改文件: drivers/video/mxsfb.c

找到 mxs_of_get_timings() 中以下代码块 (约第 303-316 行):

priv->disp_dev = video_link_get_next_device(dev);
if (priv->disp_dev) {
ret = video_link_get_display_timings(timings);
if (ret) {
dev_err(dev, "failed to get any video link display timings\n");
return -EINVAL;
}
} else {
ret = ofnode_decode_display_timing(display_node, 0, timings);
if (ret) {
dev_err(dev, "failed to get any display timings\n");
return -EINVAL;
}
}

替换为:

priv->disp_dev = video_link_get_next_device(dev);
if (priv->disp_dev) {
ret = video_link_get_display_timings(timings);
if (ret)
debug("video link timings not found, trying display node\n");
}

if (ret || !priv->disp_dev) {
ret = ofnode_decode_display_timing(display_node, 0, timings);
if (ret)
dev_err(dev, "display node timing not found\n");
}

if (ret) {
dev_err(dev, "failed to get any display timings\n");
return -EINVAL;
}

================================================================================
Step 8: 修改文件: drivers/video/mxsfb.c
================================================================================

修改文件: drivers/video/mxsfb.c

找到 mxs_video_probe() 修改为以下代码块

static int mxs_video_probe(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct mxsfb_priv *priv = dev_get_priv(dev);

struct display_timing timings;
u32 bpp = 0;
u32 fb_start, fb_end;
int ret;
bool enable_bridge = false;

debug("%s() plat: base 0x%lx, size 0x%x\n",
__func__, plat->base, plat->size);

priv->reg_base = dev_read_addr(dev);
if (priv->reg_base == FDT_ADDR_T_NONE) {
dev_err(dev, "lcdif base address is not found\n");
return -EINVAL;
}

ret = mxs_of_get_timings(dev, &timings, &bpp);
if (ret)
return ret;
timings.flags |= DISPLAY_FLAGS_DE_HIGH;

if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (check_module_fused(MODULE_LCDIF)) {
printf("LCDIF@0x%lx is fused, disable it\n", (ulong)priv->reg_base);
return -ENODEV;
}
}

if (priv->disp_dev) {
#if IS_ENABLED(CONFIG_DISPLAY)
if (device_get_uclass_id(priv->disp_dev) == UCLASS_DISPLAY) {
ret = display_enable(priv->disp_dev, bpp, &timings);
if (ret) {
dev_err(dev, "fail to enable display\n");
return ret;
}
}
#endif

/*
#if IS_ENABLED(CONFIG_VIDEO_BRIDGE)
if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {
ret = video_bridge_attach(priv->disp_dev);
if (ret) {
dev_err(dev, "fail to attach bridge\n");
return ret;
}

ret = video_bridge_set_backlight(priv->disp_dev, 80);
if (ret) {
dev_err(dev, "fail to set backlight\n");
return ret;
}

enable_bridge = true;

// sec dsim needs enable ploarity at low, default we set to high
if (!strcmp(priv->disp_dev->driver->name, "imx_sec_dsim"))
timings.flags &= ~DISPLAY_FLAGS_DE_HIGH;

}
#endif
if (device_get_uclass_id(priv->disp_dev) == UCLASS_PANEL) {
ret = panel_enable_backlight(priv->disp_dev);
if (ret) {
dev_err(dev, "panel %s enable backlight error %d\n",
priv->disp_dev->name, ret);
return ret;
}
}
}

ret = mxs_probe_common(dev, &timings, bpp, plat->base, enable_bridge);

*/

#if IS_ENABLED(CONFIG_VIDEO_BRIDGE)
if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {
ret = video_bridge_attach(priv->disp_dev);
if (ret) {
dev_err(dev, "fail to attach bridge\n");
return ret;
}

//ret = video_bridge_set_backlight(priv->disp_dev, 80);
//if (ret) {
// dev_err(dev, "fail to set backlight\n");
// return ret;
//}

enable_bridge = true;

// sec dsim needs enable ploarity at low, default we set to high
if (!strcmp(priv->disp_dev->driver->name, "imx_sec_dsim"))
timings.flags &= ~DISPLAY_FLAGS_DE_HIGH;

}
#endif
if (device_get_uclass_id(priv->disp_dev) == UCLASS_PANEL) {
ret = panel_enable_backlight(priv->disp_dev);
if (ret) {
dev_err(dev, "panel %s enable backlight error %d\n",
priv->disp_dev->name, ret);
return ret;
}
}
}

ret = mxs_probe_common(dev, &timings, bpp, plat->base, enable_bridge);
if (ret)
return ret;

#if IS_ENABLED(CONFIG_VIDEO_BRIDGE)
/ LCDIF已启动,现在配置SiI9022A /
if (priv->disp_dev && device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {

ret = video_bridge_set_backlight(priv->disp_dev, 80);
if (ret) {
dev_err(dev, "fail to set backlight\n");
return ret;
}

}
#endif

switch (bpp) {
case 32:
case 24:
case 18:
uc_priv->bpix = VIDEO_BPP32;
break;
case 16:
uc_priv->bpix = VIDEO_BPP16;
break;
case 8:
uc_priv->bpix = VIDEO_BPP8;
break;
default:
dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
return -EINVAL;
}

uc_priv->xsize = timings.hactive.typ;
uc_priv->ysize = timings.vactive.typ;

/ Enable dcache for the frame buffer /
fb_start = plat->base;
fb_end = plat->base + plat->size;

mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
DCACHE_WRITEBACK);
video_set_flush_dcache(dev, true);

return ret;
}

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn


东莞哇酷科技有限公司开发