引言:
说实话,移植uboot真的没有必要整最新版的,因为uboot的作用就是来启动linux,能用就行了。我就是最求最新版,导致我仅仅在学习移植uboot的时候就花费了我一个星期的时间,我也尝试过移植uboot官网上的uboot,但是不能成功驱动LCD屏幕,最终放弃,去移植官方的uboot。
更改步骤比较无聊,基本上就是把evk换成alpha,把14x14_evk换成alpha,小写换小写,大写换大写。
网上关于这些信息为什么要更改的原因已经讲的十分详细了,所以我在这里并不详细介绍每个步骤是为什么。
想直接吃现成的就到我的仓库里来吧:我的码云仓库
开发环境:
开发软件:VScode + SSH
操作系统:Ubuntu22.04
编译工具链:arm-none-linux-gnueabihf-gcc,工具链版本:10.3-2021.07-x86_64
uboot版本:NXP官方的uboot-imx-lf_v2023.04
开发板版本:
核心板:EMMC 512MB
底板:ALPHA V2.0
移植步骤:
1、从github下载NXP官方uboot
2、添加默认配置文件
3、添加板级文件
4、添加板级头文件
5、配置Kconfig
6、添加相应设备树文件
7、移植网络
8、移植屏幕
9、解决杂项问题
具体操作:
1、从github下载NXP官方uboot
官方链接:GitHub - nxp-imx/uboot-imx at lf_v2023.04
下载并解压得到uboot-imx-lf_v2023.04目录。
注意:我这里使用VScode +SSH远程连接的方式移植uboot。
使用VScode打开uboot-imx-lf_v2023.04。
2、添加默认配置文件
找到configs/mx6ull_14x14_evk_emmc_defconfig文件,复制并重命名为configs/mx6ull_alpha_defconfig。
文件中默认配置为:
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_SYS_MALLOC_LEN=0x1000000
CONFIG_NR_DRAM_BANKS=1
CONFIG_SYS_MEMTEST_START=0x80000000
CONFIG_SYS_MEMTEST_END=0x88000000
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0xE0000
CONFIG_MX6ULL=y
CONFIG_TARGET_MX6ULL_14X14_EVK=y
# CONFIG_LDO_BYPASS_CHECK is not set
CONFIG_SYS_I2C_MXC_I2C1=y
CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-evk-emmc"
CONFIG_SUPPORT_RAW_INITRD=y
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="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"
CONFIG_BOOTDELAY=3
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_MAXARGS=32
CONFIG_SYS_PBSIZE=532
CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_BMP=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_NET=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=1
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_USE_ETHPRIME=y
CONFIG_ETHPRIME="eth1"
CONFIG_BOUNCE_BUFFER=y
CONFIG_DM_74X164=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MXC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_FSL_USDHC=y
CONFIG_MTD=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SF_DEFAULT_SPEED=40000000
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_PHYLIB=y
CONFIG_PHY_MICREL=y
CONFIG_PHY_MICREL_KSZ8XXX=y
CONFIG_DM_ETH_PHY=y
CONFIG_FEC_MXC=y
CONFIG_MII=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_IMX6=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_GPIO=y
CONFIG_DM_SERIAL=y
CONFIG_MXC_UART=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_FSL_QSPI=y
CONFIG_SOFT_SPI=y
CONFIG_IMX_THERMAL=y
CONFIG_ARCH_MISC_INIT=y
CONFIG_DM_RNG=y
CONFIG_CMD_RNG=y
CONFIG_FSL_DCP_RNG=y
CONFIG_USB=y
CONFIG_USB_MAX_CONTROLLER_COUNT=2
CONFIG_USB_STORAGE=y
CONFIG_CMD_USB_MASS_STORAGE=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y
CONFIG_VIDEO=y
CONFIG_VIDEO_LINK=y
CONFIG_VIDEO_LOGO=y
CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_VIDEO_MXS=y
CONFIG_SPLASH_SCREEN=y
CONFIG_SPLASH_SCREEN_ALIGN=y
CONFIG_BMP_16BPP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_GADGET_MANUFACTURER="FSL"
CONFIG_USB_GADGET_VENDOR_NUM=0x1fc9
CONFIG_USB_GADGET_PRODUCT_NUM=0x0152
CONFIG_CI_UDC=y
CONFIG_CMD_FASTBOOT=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_UUU_SUPPORT=y
CONFIG_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x83800000
CONFIG_FASTBOOT_BUF_SIZE=0x40000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_EFI_PARTITION=y
CONFIG_CMD_CRC32=y
CONFIG_CRC32_VERIFY=y
找到CONFIG_TARGET_MX6ULL_14X14_EVK=y配置项,将其更
改为CONFIG_TARGET_MX6ULL_ALPHA=y。
找到CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-evk"配置项,将其更改为CONFIG_DEFAULT_DEVICE_TREE="imx6ull-alpha"(注:此配置项所配置的是uboot启动时所需要的设备树名)
3、添加板级文件
复制board/freescale/mx6ullevk目录为board/freescale/mx6ullalpha。
更改board/freescale/mx6ullalpha目录下的文件。
将mx6ullevk.c重命名为mx6ullalpha.c。
更改Kconfig文件:
默认文件内容:
if TARGET_MX6ULL_14X14_EVK || TARGET_MX6ULL_9X9_EVK
config SYS_BOARD
default "mx6ullevk"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "mx6ullevk"
config IMX_CONFIG
default "board/freescale/mx6ullevk/imximage.cfg"
config TEXT_BASE
default 0x87800000
endif
修改后的文件内容:
if TARGET_MX6ULL_ALPHA
config SYS_BOARD
default "mx6ullalpha"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "mx6ullalpha"
config IMX_CONFIG
default "board/freescale/mx6ullalpha/imximage.cfg"
config TEXT_BASE
default 0x87800000
endif
更改MAINTAINERS文件:
默认文件内容:
MX6ULLEVK BOARD
M: Peng Fan <peng.fan@nxp.com>
S: Maintained
F: board/freescale/mx6ullevk/
F: include/configs/mx6ullevk.h
F: configs/mx6ull_14x14_evk_defconfig
F: configs/mx6ull_14x14_evk_plugin_defconfig
F: configs/mx6ulz_14x14_evk_defconfig
修改后文件内容:
MX6ULLALPHA BOARD
M: Peng Fan <peng.fan@nxp.com>
S: Maintained
F: board/freescale/mx6ullalpha/
F: include/configs/mx6ullalpha.h
F: configs/mx6ull_alpha_defconfig
更改Makefile文件:
默认文件内容:
# SPDX-License-Identifier: GPL-2.0+
# (C) Copyright 2016 Freescale Semiconductor, Inc.
obj-y := mx6ullevk.o
修改后文件内容:
# SPDX-License-Identifier: GPL-2.0+
# (C) Copyright 2016 Freescale Semiconductor, Inc.
obj-y := mx6ullalpha.o
更改mx6ullalpha.c文件:
(这部分修改比较繁琐)
默认文件内容:
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*/
#include <init.h>
#include <asm/arch/clock.h>
#include <asm/arch/iomux.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/mach-imx/boot_mode.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <asm/io.h>
#include <common.h>
#include <env.h>
#include <fsl_esdhc_imx.h>
#include <i2c.h>
#include <miiphy.h>
#include <linux/sizes.h>
#include <linux/delay.h>
#include <mmc.h>
#include <miiphy.h>
#include <power/pmic.h>
#include <power/pfuze3000_pmic.h>
#include "../common/pfuze.h"
DECLARE_GLOBAL_DATA_PTR;
#define I2C_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
PAD_CTL_ODE)
#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \
PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm)
#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \
PAD_CTL_SRE_FAST)
#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1)
#ifdef CONFIG_DM_PMIC
int power_init_board(void)
{
struct udevice *dev;
int ret, dev_id, rev_id;
unsigned int reg;
ret = pmic_get("pfuze3000@8", &dev);
if (ret == -ENODEV)
return 0;
if (ret != 0)
return ret;
dev_id = pmic_reg_read(dev, PFUZE3000_DEVICEID);
rev_id = pmic_reg_read(dev, PFUZE3000_REVID);
printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n", dev_id, rev_id);
/* disable Low Power Mode during standby mode */
reg = pmic_reg_read(dev, PFUZE3000_LDOGCTL);
reg |= 0x1;
pmic_reg_write(dev, PFUZE3000_LDOGCTL, reg);
/* SW1B step ramp up time from 2us to 4us/25mV */
pmic_reg_write(dev, PFUZE3000_SW1BCONF, 0x40);
/* SW1B mode to APS/PFM */
pmic_reg_write(dev, PFUZE3000_SW1BMODE, 0xc);
/* SW1B standby voltage set to 0.975V */
pmic_reg_write(dev, PFUZE3000_SW1BSTBY, 0xb);
return 0;
}
#ifdef CONFIG_LDO_BYPASS_CHECK
void ldo_mode_set(int ldo_bypass)
{
unsigned int value;
u32 vddarm;
struct udevice *dev;
int ret;
ret = pmic_get("pfuze3000@8", &dev);
if (ret == -ENODEV) {
printf("No PMIC found!\n");
return;
}
/* switch to ldo_bypass mode */
if (ldo_bypass) {
prep_anatop_bypass();
/* decrease VDDARM to 1.275V */
value = pmic_reg_read(dev, PFUZE3000_SW1BVOLT);
value &= ~0x1f;
value |= PFUZE3000_SW1AB_SETP(12750);
pmic_reg_write(dev, PFUZE3000_SW1BVOLT, value);
set_anatop_bypass(1);
vddarm = PFUZE3000_SW1AB_SETP(11750);
value = pmic_reg_read(dev, PFUZE3000_SW1BVOLT);
value &= ~0x1f;
value |= vddarm;
pmic_reg_write(dev, PFUZE3000_SW1BVOLT, value);
finish_anatop_bypass();
printf("switch to ldo_bypass mode!\n");
}
}
#endif
#endif
int dram_init(void)
{
gd->ram_size = imx_ddr_size();
return 0;
}
int board_mmc_get_env_dev(int devno)
{
return devno;
}
#ifdef CONFIG_FSL_QSPI
#ifndef CONFIG_DM_SPI
#define QSPI_PAD_CTRL1 \
(PAD_CTL_SRE_FAST | PAD_CTL_SPEED_MED | \
PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_120ohm)
static iomux_v3_cfg_t const quadspi_pads[] = {
MX6_PAD_NAND_WP_B__QSPI_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
MX6_PAD_NAND_READY_B__QSPI_A_DATA00 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
MX6_PAD_NAND_CE0_B__QSPI_A_DATA01 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
MX6_PAD_NAND_CE1_B__QSPI_A_DATA02 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
MX6_PAD_NAND_CLE__QSPI_A_DATA03 | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
MX6_PAD_NAND_DQS__QSPI_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL1),
};
#endif
static int board_qspi_init(void)
{
#ifndef CONFIG_DM_SPI
/* Set the iomux */
imx_iomux_v3_setup_multiple_pads(quadspi_pads,
ARRAY_SIZE(quadspi_pads));
#endif
/* Set the clock */
enable_qspi_clk(0);
return 0;
}
#endif
#ifdef CONFIG_NAND_MXS
static iomux_v3_cfg_t const nand_pads[] = {
MX6_PAD_NAND_DATA00__RAWNAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA01__RAWNAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA02__RAWNAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA03__RAWNAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA04__RAWNAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA05__RAWNAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA06__RAWNAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA07__RAWNAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_CLE__RAWNAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_ALE__RAWNAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_CE0_B__RAWNAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_CE1_B__RAWNAND_CE1_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_RE_B__RAWNAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_WE_B__RAWNAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_WP_B__RAWNAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_READY_B__RAWNAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DQS__RAWNAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
};
static void setup_gpmi_nand(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
/* config gpmi nand iomux */
imx_iomux_v3_setup_multiple_pads(nand_pads, ARRAY_SIZE(nand_pads));
setup_gpmi_io_clk((MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)));
/* enable apbh clock gating */
setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
}
#endif
#ifdef CONFIG_FEC_MXC
static int setup_fec(void)
{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
/*
* Use 50M anatop loopback REF_CLK1 for ENET1,
* clear gpr1[13], set gpr1[17].
*/
clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
/*
* Use 50M anatop loopback REF_CLK2 for ENET2,
* clear gpr1[14], set gpr1[18].
*/
if (!check_module_fused(MODULE_ENET2)) {
clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK,
IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
}
ret = enable_fec_anatop_clock(0, ENET_50MHZ);
if (ret)
return ret;
if (!check_module_fused(MODULE_ENET2)) {
ret = enable_fec_anatop_clock(1, ENET_50MHZ);
if (ret)
return ret;
}
enable_enet_clk(1);
return 0;
}
int board_phy_config(struct phy_device *phydev)
{
phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif
#ifdef CONFIG_VIDEO
static iomux_v3_cfg_t const lcd_pads[] = {
/* Use GPIO for Brightness adjustment, duty cycle = period. */
MX6_PAD_GPIO1_IO08__GPIO1_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static int setup_lcd(void)
{
enable_lcdif_clock(LCDIF1_BASE_ADDR, 1);
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
/* Reset the LCD */
gpio_request(IMX_GPIO_NR(5, 9), "lcd reset");
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_request(IMX_GPIO_NR(1, 8), "backlight");
gpio_direction_output(IMX_GPIO_NR(1, 8) , 1);
return 0;
}
#else
static inline int setup_lcd(void) { return 0; }
#endif
int board_early_init_f(void)
{
return 0;
}
int board_init(void)
{
/* Address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
#ifdef CONFIG_FEC_MXC
setup_fec();
#endif
#ifdef CONFIG_FSL_QSPI
board_qspi_init();
#endif
#ifdef CONFIG_NAND_MXS
setup_gpmi_nand();
#endif
return 0;
}
#ifdef CONFIG_CMD_BMODE
static const struct boot_mode board_boot_modes[] = {
/* 4 bit bus width */
{"sd1", MAKE_CFGVAL(0x42, 0x20, 0x00, 0x00)},
{"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
{"qspi1", MAKE_CFGVAL(0x10, 0x00, 0x00, 0x00)},
{NULL, 0},
};
#endif
int board_late_init(void)
{
#ifdef CONFIG_CMD_BMODE
add_board_boot_modes(board_boot_modes);
#endif
env_set("tee", "no");
#ifdef CONFIG_IMX_OPTEE
env_set("tee", "yes");
#endif
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_name", "EVK");
if (is_mx6ull_9x9_evk())
env_set("board_rev", "9X9");
else
env_set("board_rev", "14X14");
if (is_cpu_type(MXC_CPU_MX6ULZ)) {
env_set("board_name", "ULZ-EVK");
env_set("usb_net_cmd", "usb start");
}
#endif
setup_lcd();
#ifdef CONFIG_ENV_IS_IN_MMC
board_late_mmc_env_init();
#endif
set_wdog_reset((struct wdog_regs *)WDOG1_BASE_ADDR);
return 0;
}
int checkboard(void)
{
if (is_mx6ull_9x9_evk())
puts("Board: MX6ULL 9x9 EVK\n");
else if (is_cpu_type(MXC_CPU_MX6ULZ))
puts("Board: MX6ULZ 14x14 EVK\n");
else
puts("Board: MX6ULL 14x14 EVK\n");
return 0;
}
void board_quiesce_devices(void)
{
#if defined(CONFIG_VIDEO_MXS)
enable_lcdif_clock(LCDIF1_BASE_ADDR, 0);
#endif
}
搜索CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG配置项,默认内容是:
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_name", "EVK");
if (is_mx6ull_9x9_evk())
env_set("board_rev", "9X9");
else
env_set("board_rev", "14X14");
if (is_cpu_type(MXC_CPU_MX6ULZ)) {
env_set("board_name", "ULZ-EVK");
env_set("usb_net_cmd", "usb start");
}
#endif
将其内容缩减更改为:
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_name", "ALPHA");
env_set("board_rev", "14X14");
#endif
找到checkboard函数,默认内容:
int checkboard(void)
{
if (is_mx6ull_9x9_evk())
puts("Board: MX6ULL 9x9 EVK\n");
else if (is_cpu_type(MXC_CPU_MX6ULZ))
puts("Board: MX6ULZ 14x14 EVK\n");
else
puts("Board: MX6ULL 14x14 EVK\n");
return 0;
}
更改为:
int checkboard(void)
{
puts("Board: MX6ULL ALPHA\n");
return 0;
}
4、添加板级头文件
复制include/configs/mx6ullevk.h文件并重命名为include/configs/mx6ullalpha.h。
文件默认内容:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* Configuration settings for the Freescale i.MX6UL 14x14 EVK board.
*/
#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H
#include <asm/arch/imx-regs.h>
#include <linux/sizes.h>
#include <linux/stringify.h>
#include "mx6_common.h"
#include <asm/mach-imx/gpio.h>
#include "imx_env.h"
#define is_mx6ull_9x9_evk() CONFIG_IS_ENABLED(TARGET_MX6ULL_9X9_EVK)
#ifdef CONFIG_TARGET_MX6ULL_9X9_EVK
#define BOOTARGS_CMA_SIZE "cma=96M "
#else
#define BOOTARGS_CMA_SIZE ""
#endif
#define CFG_MXC_UART_BASE UART1_BASE
/* MMC Configs */
#ifdef CONFIG_FSL_USDHC
#define CFG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR
/* NAND pin conflicts with usdhc2 */
#ifdef CONFIG_NAND_MXS
#define CONFIG_SYS_FSL_USDHC_NUM 1
#else
#define CONFIG_SYS_FSL_USDHC_NUM 2
#endif
#endif
#ifdef CONFIG_NAND_BOOT
#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:64m(nandboot),16m(nandkernel),16m(nanddtb),16m(nandtee),-(nandrootfs)"
#else
#define MFG_NAND_PARTITION ""
#endif
#define CFG_MFG_ENV_SETTINGS \
CFG_MFG_ENV_SETTINGS_DEFAULT \
"initrd_addr=0x86800000\0" \
"initrd_high=0xffffffff\0" \
"emmc_dev=1\0"\
"emmc_ack=1\0"\
"sd_dev=1\0" \
"mtdparts=" MFG_NAND_PARTITION \
"\0"\
#if defined(CONFIG_NAND_BOOT)
#define CFG_EXTRA_ENV_SETTINGS \
CFG_MFG_ENV_SETTINGS \
TEE_ENV \
"splashimage=0x8c000000\0" \
"fdt_addr=0x83000000\0" \
"fdt_high=0xffffffff\0" \
"tee_addr=0x84000000\0" \
"console=ttymxc0\0" \
"bootargs=console=ttymxc0,115200 ubi.mtd=nandrootfs " \
"root=ubi0:rootfs rootfstype=ubifs " \
BOOTARGS_CMA_SIZE \
MFG_NAND_PARTITION \
"\0" \
"bootcmd=nand read ${loadaddr} 0x4000000 0xc00000;"\
"nand read ${fdt_addr} 0x5000000 0x100000;"\
"if test ${tee} = yes; then " \
"nand read ${tee_addr} 0x6000000 0x400000;"\
"bootm ${tee_addr} - ${fdt_addr};" \
"else " \
"bootz ${loadaddr} - ${fdt_addr};" \
"fi\0"
#else
#define CFG_EXTRA_ENV_SETTINGS \
CFG_MFG_ENV_SETTINGS \
TEE_ENV \
"script=boot.scr\0" \
"image=zImage\0" \
"console=ttymxc0\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
"fdt_file=undefined\0" \
"fdt_addr=0x83000000\0" \
"tee_addr=0x84000000\0" \
"tee_file=undefined\0" \
"boot_fdt=try\0" \
"ip_dyn=yes\0" \
"splashimage=0x8c000000\0" \
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
"mmcpart=1\0" \
"mmcroot=/dev/mmcblk1p2 rootwait rw\0" \
"mmcautodetect=yes\0" \
"mmcargs=setenv bootargs console=${console},${baudrate} " \
BOOTARGS_CMA_SIZE \
"root=${mmcroot}\0" \
"loadbootscript=" \
"fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
"bootscript=echo Running bootscript from mmc ...; " \
"source\0" \
"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
"loadtee=fatload mmc ${mmcdev}:${mmcpart} ${tee_addr} ${tee_file}\0" \
"mmcboot=echo Booting from mmc ...; " \
"run mmcargs; " \
"if test ${tee} = yes; then " \
"run loadfdt; run loadtee; bootm ${tee_addr} - ${fdt_addr}; " \
"else " \
"if test ${boot_fdt} = yes || test ${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; " \
"fi;\0" \
"netargs=setenv bootargs console=${console},${baudrate} " \
BOOTARGS_CMA_SIZE \
"root=/dev/nfs " \
"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
"netboot=echo Booting from net ...; " \
"${usb_net_cmd}; " \
"run netargs; " \
"if test ${ip_dyn} = yes; then " \
"setenv get_cmd dhcp; " \
"else " \
"setenv get_cmd tftp; " \
"fi; " \
"${get_cmd} ${image}; " \
"if test ${tee} = yes; then " \
"${get_cmd} ${tee_addr} ${tee_file}; " \
"${get_cmd} ${fdt_addr} ${fdt_file}; " \
"bootm ${tee_addr} - ${fdt_addr}; " \
"else " \
"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; then " \
"bootz; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"fi; " \
"else " \
"bootz; " \
"fi; " \
"fi;\0" \
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = ULZ-EVK && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ulz-14x14-evk.dtb; fi; " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
"if test $board_name = 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;\0" \
"findtee="\
"if test $tee_file = undefined; then " \
"if test $board_name = ULZ-EVK && test $board_rev = 14X14; then " \
"setenv tee_file uTee-6ulzevk; fi; " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv tee_file uTee-6ullevk; fi; " \
"if test $board_name = EVK && test $board_rev = 14X14; then " \
"setenv tee_file uTee-6ullevk; fi; " \
"if test $tee_file = undefined; then " \
"echo WARNING: Could not determine tee to use; " \
"fi; " \
"fi;\0" \
#endif
/* Miscellaneous configurable options */
/* Physical Memory Map */
#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR
#define CFG_SYS_SDRAM_BASE PHYS_SDRAM
#define CFG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR
#define CFG_SYS_INIT_RAM_SIZE IRAM_SIZE
/* environment organization */
/* NAND stuff */
#define CFG_SYS_NAND_BASE 0x40000000
#endif
我们可以搜索evk关键字进行修改,防止遗漏。
上面注释一起更改了吧。
将__MX6ULLEVK_CONFIG_H更改为:__MX6ULLALPHA_CONFIG_H 。
删除is_mx6ull_9x9_evk所在行。
找到CONFIG_TARGET_MX6ULL_9X9_EVK。
默认内容为:
#ifdef CONFIG_TARGET_MX6ULL_9X9_EVK
#define BOOTARGS_CMA_SIZE "cma=96M "
#else
#define BOOTARGS_CMA_SIZE ""
#endif
将此处修改为
#define BOOTARGS_CMA_SIZE ""
找到findfdt=,默认内容为:
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = ULZ-EVK && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ulz-14x14-evk.dtb; fi; " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
"if test $board_name = 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;\0" \
修改为:
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = ALPHA && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ull-14x14-emmc-4.3-800x480-c.dtb; fi; " \
"if test $fdt_file = undefined; then " \
"echo WARNING: Could not determine dtb to use; " \
"fi; " \
"fi;\0" \
这里配置的设备树是linux启动时所需要的设备树。
找到findtee=,虽然没有用到,但也还是修改一下吧,修改为:
"findtee="\
"if test $tee_file = undefined; then " \
"if test $board_name = ALPHA && test $board_rev = 14X14; then " \
"setenv tee_file uTee-6ullalpha; fi; " \
"if test $tee_file = undefined; then " \
"echo WARNING: Could not determine tee to use; " \
"fi; " \
"fi;\0" \
5、配置Kconfig
找到arch/arm/mach-imx/mx6/Kconfig文件。
搜索TARGET_MX6ULL_14X14_EVK,默认内容为:
config TARGET_MX6ULL_14X14_EVK
bool "Support mx6ull_14x14_evk"
depends on MX6ULL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
select IOMUX_LPSR
select IMX_MODULE_FUSE
select OF_SYSTEM_SETUP
imply CMD_DM
在其下方添加 如下代码:
config TARGET_MX6ULL_ALPHA
bool "Support mx6ull_alpha"
depends on MX6ULL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
select IOMUX_LPSR
select IMX_MODULE_FUSE
select OF_SYSTEM_SETUP
imply CMD_DM
搜索source "board/freescale/mx6ullevk/Kconfig" ,在其下方添加:
source "board/freescale/mx6ullalpha/Kconfig"
6、添加相应设备树文件
找到arch/arm/dts/imx6ull-14x14-evk.dts文件,复制为arch/arm/dts/imx6ull-alpha.dts。
找到arch/arm/dts/imx6ul-14x14-evk.dtsi文件,复制为arch/arm/dts/imx6ull-alpha.dtsi。
找到arch/arm/dts/imx6ull-14x14-evk-u-boot.dtsi文件,复制为arch/arm/dts/imx6ull-alpha-u-boot.dtsi。
修改imx6ull-alpha.dts文件。
文件默认内容为:
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (C) 2016 Freescale Semiconductor, Inc.
/dts-v1/;
#include "imx6ull.dtsi"
#include "imx6ul-14x14-evk.dtsi"
#include "imx6ul-14x14-evk-u-boot.dtsi"
/ {
model = "i.MX6 ULL 14x14 EVK Board";
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
};
&clks {
assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
<&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <320000000>, <786432000>;
};
&csi {
status = "okay";
};
&ov5640 {
status = "okay";
};
/delete-node/ &sim2;
由于我们移植的是EMMC版本的,所以需要将imx6ull-14x14-evk-emmc.dts文件的usdhc2结点复制到imx6ull-alpha.dts文件中,修改后文件内容为:
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (C) 2016 Freescale Semiconductor, Inc.
/dts-v1/;
#include "imx6ull.dtsi"
#include "imx6ull-alpha.dtsi"
#include "imx6ull-alpha-u-boot.dtsi"
/ {
model = "i.MX6 ULL ALPHA Board";
compatible = "fsl,imx6ull-alpha", "fsl,imx6ull";
};
&clks {
assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
<&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <320000000>, <786432000>;
};
&csi {
status = "okay";
};
&ov5640 {
status = "okay";
};
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_8bit>;
pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
/delete-node/ &sim2;
至此,我们的移植工作告一段落。
7、编译测试
编写shell脚本文件方便编译。
脚本内容:
#/bin/bash
make distclean
make mx6ull_alpha_defconfig
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- -j20
给予可执行权限:chmod +x mkuboot.sh
编译如果出错,请仔细查看并修改。
编译、烧写到SD卡,运行测试。
可以看到uboot成功跑了起来,但是显示的信息不全,我们可以使用reset命令重新启动uboot,这样就能打印详细信息了,具体是什么原因,我并不清楚。
接下来就是移植网络和平木驱动了。
8、移植网络
找到configs/mx6ull_alpha_defconfig文件,搜索CONFIG_PHY_MICREL和CONFIG_PHY_MICREL_KSZ8XXX,注释掉这两行,添加CONFIG_PHY_SMSC=y。
找到arch/arm/dts/imx6ull-alpha.dtsi文件,搜索fec1,看到网络默认配置为:
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
phy-mode = "rmii";
phy-handle = <ðphy0>;
phy-supply = <®_peri_3v3>;
status = "okay";
};
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
phy-mode = "rmii";
phy-handle = <ðphy1>;
phy-supply = <®_peri_3v3>;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@2 {
compatible = "ethernet-phy-id0022.1560";
reg = <2>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET_REF>;
clock-names = "rmii-ref";
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-id0022.1560";
reg = <1>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET2_REF>;
clock-names = "rmii-ref";
};
};
};
更改为:
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1
&pinctrl_enet1_reset>;
phy-mode = "rmii";
phy-handle = <ðphy0>;
phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
status = "disable";
};
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2
&pinctrl_enet2_reset>;
phy-mode = "rmii";
phy-handle = <ðphy1>;
phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-id0022.1560";
reg = <0>;
smsc,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET_REF>;
clock-names = "rmii-ref";
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-id0022.1560";
reg = <1>;
smsc,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET2_REF>;
clock-names = "rmii-ref";
};
};
};
uboot只能使能一个网口,所以我们需要disable一个网口,fec1使能比较麻烦,所以我这里使能fec2,同时添加了复位引脚。
搜索找到pinctrl_enet1结点位置,在此节点后面添加:
pinctrl_enet1_reset:enet1resetgrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0
>;
};
搜索找到pinctrl_enet2结点位置,在此节点后面添加:
pinctrl_enet2_reset:enet2resetgrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0
>;
};
这里我们还需要修改drivers/net/phy/phy.c文件,找到genphy_config_aneg函数,在int result;后面加上phy_reset(phydev);让碗口复位。
我们编译、烧写、运行,发现报错信息已经发生改变。
此时,我们只需要设置好eth1addr、serverip、ipaddr这三个环境变量,保存重启便可以正常连接到网络了。
我设置的是:
setenv eth1addr 32:34:46:78:9A:DD # 本地MAC地址
setenv serverip 192.168.8.2 # 服务器端地址
setenv ipaddr 192.168.8.3 # 本机地址
saveenv
此时,网络已经通畅。
接下来就开始移植屏幕。
9、移植屏幕
找到arch/arm/dts/imx6ull-alpha.dtsi文件,搜索lcdif,默认配置为:
&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>;
display = <&display0>;
status = "okay";
display0: display@0 {
bits-per-pixel = <24>;
bus-width = <24>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <9200000>;
hactive = <480>;
vactive = <272>;
hfront-porch = <8>;
hback-porch = <4>;
hsync-len = <41>;
vback-porch = <2>;
vfront-porch = <4>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
};
这一块主要修改display-timings节点,具体怎么更改,在正点原子的linuxLCD移植视频里面有详细的讲解。
因为我用的是正点原子的800x480的屏幕,所以我得配置如下:
&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>;
display = <&display0>;
status = "okay";
display0: display@0 {
bits-per-pixel = <24>;
bus-width = <24>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <9200000>;
hactive = <480>;
vactive = <272>;
hfront-porch = <8>;
hback-porch = <4>;
hsync-len = <41>;
vback-porch = <2>;
vfront-porch = <4>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
};
至此,LCD移植工作大功告成。
我们编译、烧写、运行,可以看到屏幕上已经出现了NXP的logo和一行uboot信息。
10、解决杂项问题
虽然现在uboot已经完美启动了,但是会发现它在启动linux内核的时候会报错,解决这个报错的方法也很简单,是需要将arch/arm/mach-imx/mx6/Kconfig文件中TARGET_MX6ULL_ALPHA配置项中的OF_SYSTEM_SETUP选项删除即可。
正点原子的uboot移植视频里还讲了校验码的修改,这个文件写的就是生成的bin文件的头部信息,只有校验码正确了,我们才能够直接烧写uboot编译生成的uboot-dtb.imx文件。
找到board/freescale/mx6ullalpha/imximage.cfg文件,搜索0x021B083C,连续三行默认值为:
DATA 4 0x021B083C 0x41640158
DATA 4 0x021B0848 0x40403237
DATA 4 0x021B0850 0x40403C33
修改为:
DATA 4 0x021B083C 0x01380138
DATA 4 0x021B0848 0x40402E32
DATA 4 0x021B0850 0x40403432
至此,所有移植工作大功告成!!