为Exynos4412移植U-Boot-2017.11的步骤(一)——让U-Boot跑起来
为Exynos4412移植U-Boot-2017.11(二)——SD卡、eMMC驱动
为Exynos4412移植U-Boot-2017.11(三)——DM9000A驱动
这篇文章主要描述如何把u-boot-2017.11移植到在cbt4412核心板。主要是想尝试用u-boot-2017.11能不能引导Linux kernel 4.9。(之前移植u-boot-2022.01,可以引导Linux kernel5.4,但是引导Linux kernel 4.9出错。不知道是什么原因。)
参考大水猫的专题【TINY4412】U-BOOT移植笔记。
虚拟机: VisualBox 6.1
宿主机:Linux version 5.4.0-96-generic (buildd@lcy02-amd64-007) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #109~18.04.1-Ubuntu SMP Thu Jan 13 15:06:26 UTC 2022Ubuntu 18.04
目标板[核心板]: CBT4412(类似于Tiny4412,网卡是DM9000A)
U-BOOT版本:2017.11
交叉编译器: arm-linux-gnueabihf-gcc 版本 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))
日期: 2022-3-11
作者: HelloTonyGo
toolchain下载地址:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads
cp -rf board/samsung/origen/ board/samsung/cbt4412
文件夹名可以根据自己的开发板取名。该文件夹内是origen开发板的相关文件,要把相关文件的代码更改为自己开发板的相关代码。
mv board/samsung/cbt4412/origen.c board/samsung/cbt4412/cbt4412.c
这个很好理解,把生成目标文件名改为cbt4412(或者其他开发板名)。
@@ -6,7 +6,7 @@ ifdef CONFIG_SPL_BUILD
# necessary to create built-in.o
obj- := __dummy__.o
+hostprogs-y := tools/mkcbt4412spl
-hostprogs-y := tools/mkorigenspl
always := $(hostprogs-y)
# omit -O2 option to suppress
@@ -14,7 +14,7 @@ always := $(hostprogs-y)
#
# TODO:
# Fix the root cause in tools/mkorigenspl.c and delete the following work-around
+$(obj)/tools/mkcbt4412spl: HOSTCFLAGS:=$(filter-out -O2,$(HOSTCFLAGS))
-$(obj)/tools/mkorigenspl: HOSTCFLAGS:=$(filter-out -O2,$(HOSTCFLAGS))
else
+obj-y += cbt4412.o
-obj-y += origen.o
endif
@@ -1,6 +1,6 @@
+CBT4412 BOARD
-ORIGEN BOARD
M: Minkyu Kang <mk7.kang@samsung.com>
S: Maintained
+F: board/samsung/cbt4412/
+F: include/configs/cbt4412.h
+F: configs/cbt4412_defconfig
-F: board/samsung/origen/
-F: include/configs/origen.h
-F: configs/origen_defconfig
@@ -1,12 +1,12 @@
+if TARGET_CBT4412
-if TARGET_ORIGEN
config SYS_BOARD
+ default "cbt4412"
- default "origen"
config SYS_VENDOR
default "samsung"
config SYS_CONFIG_NAME
+ default "cbt4412"
- default "origen"
endif
cp include/configs/origen.h include/configs/cbt4412.h
include/configs/cbt4412.h头文件非常重要,要深入理解,正确配置。
+CONFIG_DEBUG_UART_BASE=0x13800000 是配置串口0的地址
+CONFIG_DEBUG_UART_CLOCK=100000000 是配置串口0的时钟为100MHz
#define CONFIG_DEFAULT_CONSOLE “console=ttySAC0,115200n8\0”
配置默认终端是串口0,波特率115200,数据位8位。
diff --git a/include/configs/cbt4412.h b/include/configs/cbt4412.h
index 69f6930..d87f9f0 100644
--- a/include/configs/cbt4412.h
+++ b/include/configs/cbt4412.h
@@ -6,14 +6,14 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#ifndef __CONFIG_ORIGEN_H
-#define __CONFIG_ORIGEN_H
+#ifndef __CONFIG_CBT4412_H
+#define __CONFIG_CBT4412_H
#include <configs/exynos4-common.h>
/* High Level Configuration Options */
-#define CONFIG_EXYNOS4210 1 /* which is a EXYNOS4210 SoC */
-#define CONFIG_ORIGEN 1 /* working with ORIGEN*/
+#define CONFIG_EXYNOS4412 1 /* which is a EXYNOS4412 SoC */
+#define CONFIG_CBT4412 1 /* working with CBT4412*/
#define CONFIG_SYS_DCACHE_OFF 1
@@ -30,13 +30,23 @@
#define CONFIG_SYS_TEXT_BASE 0x43E00000
-#define CONFIG_MACH_TYPE MACH_TYPE_ORIGEN
+#define CONFIG_MACH_TYPE MACH_TYPE_EXYNOS4412
/* Console configuration */
-#define CONFIG_DEFAULT_CONSOLE "console=ttySAC1,115200n8\0"
+#define CONFIG_DEFAULT_CONSOLE "console=ttySAC0,115200n8\0"
/* select serial console configuration */
-#define CONFIG_SERIAL2
+#define CONFIG_SERIAL0
+#define CONFIG_BAUDRATE 115200
+
+/* DEBUG UART */
+
+#define CONFIG_DEBUG_UART 1
+#define CONFIG_SPL_SERIAL_SUPPORT 1
+#define CONFIG_SPL_GPIO_SUPPORT 1
+#define CONFIG_DEBUG_UART_S5P 1
+#define CONFIG_DEBUG_UART_BASE 0x13800000
+#define CONFIG_DEBUG_UART_CLOCK (100000000)
/* Console configuration */
-#define CONFIG_DEFAULT_CONSOLE "console=ttySAC1,115200n8\0"
+#define CONFIG_DEFAULT_CONSOLE "console=ttySAC0,115200n8\0"
#define CONFIG_SYS_MEM_TOP_HIDE (1 << 20) /* ram console */
@@ -51,14 +61,14 @@
/* MMC SPL */
#define COPY_BL2_FNPTR_ADDR 0x02020030
-#define CONFIG_SPL_TEXT_BASE 0x02021410
+#define CONFIG_SPL_TEXT_BASE 0x02023400
#define CONFIG_EXTRA_ENV_SETTINGS \
"loadaddr=0x40007000\0" \
"rdaddr=0x48000000\0" \
"kerneladdr=0x40007000\0" \
"ramdiskaddr=0x48000000\0" \
- "console=ttySAC2,115200n8\0" \
+ "console=ttySAC0,115200n8\0" \
"mmcdev=0\0" \
"bootenv=uEnv.txt\0" \
"loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}\0" \
@@ -92,7 +102,7 @@
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */
#define RESERVE_BLOCK_SIZE (512)
-#define BL1_SIZE (16 << 10) /*16 K reserved for BL1*/
+#define BL1_SIZE (8 << 10) /*8 K reserved for BL1*/
#define CONFIG_ENV_OFFSET (RESERVE_BLOCK_SIZE + BL1_SIZE)
#define CONFIG_SPL_MAX_FOOTPRINT (14 * 1024)
BL1(第一引导加载程序)是从SD卡的 512B 的偏移量处开始烧录,BL2是从SD卡的Block17处开始烧录。2
因此,BL1和BL2的起始地址和大小需要配置。
这个文件很重要,是自动生成u-boot.cfg等关键。从宏定义名上就可以看出宏标识符的作用。
+CONFIG_DEFAULT_DEVICE_TREE=“exynos4412-cbt4412” 是与设备树有关
+CONFIG_SYS_PROMPT=“CBT4412 #” 是U-Boot启动之后的提示符
diff --git a/configs/cbt4412_defconfig b/configs/cbt4412_defconfig
index 2cb5539..d3b5c0a 100644
--- a/configs/cbt4412_defconfig
+++ b/configs/cbt4412_defconfig
@@ -1,14 +1,14 @@
CONFIG_ARM=y
CONFIG_ARCH_EXYNOS=y
CONFIG_ARCH_EXYNOS4=y
-CONFIG_TARGET_ORIGEN=y
-CONFIG_IDENT_STRING=" for ORIGEN"
-CONFIG_DEFAULT_DEVICE_TREE="exynos4210-origen"
+CONFIG_TARGET_CBT4412=y
+CONFIG_IDENT_STRING=" for CBT4412"
+CONFIG_DEFAULT_DEVICE_TREE="exynos4412-cbt4412"
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_SPL=y
CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="ORIGEN # "
+CONFIG_SYS_PROMPT="CBT4412 # "
CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_XIMG is not set
CONFIG_CMD_THOR_DOWNLOAD=y
把origen的源代码改为以下代码。
这个是关于设备树的配置,很重要。这里实现的功能是配置串口0为默认终端。如果设备树语法错误,会导致串口0不能工作。
// SPDX-License-Identifier: GPL-2.0+
/*
* Samsung's Exynos4210 based Origen board device tree source
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*/
/dts-v1/;
#include "skeleton.dtsi"
#include "exynos4412.dtsi"
/ {
model = "CBt4412 board based on Exynos4412";
compatible = "samsung,exynos4412";
chosen {
bootargs ="";
};
aliases {
serial0 = "/serial@13800000";
serial1 = "/serial@13800020";
console = "/serial@13800000";
};
};
添加cbt4412核心板设备树编译。
dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \
exynos4210-smdkv310.dtb \
exynos4210-universal_c210.dtb \
exynos4210-trats.dtb \
exynos4412-trats2.dtb \
- exynos4412-odroid.dtb
+ exynos4412-odroid.dtb \
+ exynos4412-cbt4412.dtb
#define CONFIG_MACH_TYPE MACH_TYPE_EXYNOS4412
u-boot的机器码和linux内核的要一致。网上大多数都是修改的linux内核的机器码,在arch/arm/tools/mach-types.h中。
查找U-Boot中arch/arm/include/asm/mach-types.h,存在
#define MACH_TYPE_TINY4412 4608
#define MACH_TYPE_EXYNOS4412 5030
所以,配置CONFIG_MACH_TYPE为MACH_TYPE_EXYNOS4412。
路径 arch/arm/mach-exynos/ 中都是关于exynos系列芯片的代码,时钟的修改、DRAM的开启等都在这里。涉及的源文件包括:
arch/arm/mach-exynos/include/mach/clock.h
clock_init_exynos4412.c
dmc_init_exynos4412.c
exynos4412_setup.h
Makefile(在此基础上还要再修改,见下文)
lowlevel_init.c
具体的修改方法请参考三周子的博文,本人亲测可行正确。3
本人建议初学者直接复制GitHub中的源文件。
其中,lowlevel_init.c中配置了串口0的引脚复用功能,使能串口0。
(1)注意:要在三周子的exynos4412_setup.h中,把“TINY4412”修改为“CBT4412”
(2)注意:lowlevel_init.c中,删除“#include <init.h>”。否则,报错
arch/arm/mach-exynos/lowlevel_init.c:30:10: 致命错误: init.h:没有那个文件或目录
#include <init.h>
^~~~~~~~
编译中断。
(3)如果在编译clock_init_exynos4412.c的时候,报错cam0和lcd错误,可能是因为2017版和2020版之间稍有区别。可以复制以下代码(U-Boot-2017.11的clock_init_exynos4412.c代码),其实就是把cam0改为cam,把lcd改为lcd0。代码如下:
/*
* Clock Initialization for board based on EXYNOS4210
*
* Copyright (C) 2013 Samsung Electronics
* Rajeshwari Shinde <rajeshwari.s@samsung.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/clock.h>
#include "common_setup.h"
#include "exynos4412_setup.h"
/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
void system_clock_init(void)
{
struct exynos4_clock *clk =
(struct exynos4_clock *)samsung_get_base_clock();
writel(CLK_SRC_CPU_VAL_FINPLL, &clk->src_cpu);
sdelay(0x10000);
writel(CLK_SRC_DMC_VAL_FINPLL, &clk->src_dmc);
writel(CLK_SRC_TOP0_VAL_RESET, &clk->src_top0);
writel(CLK_SRC_TOP1_VAL, &clk->src_top1);
writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus);
writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus);
writel(CLK_SRC_FSYS_VAL, &clk->src_fsys);
writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0);
writel(CLK_SRC_CAM_VAL, &clk->src_cam);
writel(CLK_SRC_MFC_VAL, &clk->src_mfc);
writel(CLK_SRC_G3D_VAL, &clk->src_g3d);
writel(CLK_SRC_LCD0_VAL, &clk->src_lcd0);
sdelay(0x10000);
writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0);
writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1);
writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0);
writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1);
writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus);
writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus);
writel(CLK_DIV_TOP_VAL, &clk->div_top);
writel(CLK_DIV_FSYS1_VAL, &clk->div_fsys1);
writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2);
writel(CLK_DIV_FSYS3_VAL, &clk->div_fsys3);
writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0);
writel(CLK_DIV_CAM_VAL, &clk->div_cam);
writel(CLK_DIV_MFC_VAL, &clk->div_mfc);
writel(CLK_DIV_G3D_VAL, &clk->div_g3d);
writel(CLK_DIV_LCD0_VAL, &clk->div_lcd0);
/* Set PLL locktime */
writel(PLL_LOCKTIME, &clk->apll_lock);
writel(PLL_LOCKTIME, &clk->mpll_lock);
writel(PLL_LOCKTIME, &clk->epll_lock);
writel(PLL_LOCKTIME, &clk->vpll_lock);
writel(APLL_CON1_VAL, &clk->apll_con1);
writel(APLL_CON0_VAL, &clk->apll_con0);
writel(MPLL_CON1_VAL, &clk->mpll_con1);
writel(MPLL_CON0_VAL, &clk->mpll_con0);
writel(EPLL_CON1_VAL, &clk->epll_con1);
writel(EPLL_CON0_VAL, &clk->epll_con0);
writel(VPLL_CON1_VAL, &clk->vpll_con1);
writel(VPLL_CON0_VAL, &clk->vpll_con0);
sdelay(0x30000);
writel(CLK_SRC_CPU_VAL_APLL, &clk->src_cpu);
writel(CLK_SRC_DMC_VAL_MPLL, &clk->src_dmc);
writel(CLK_SRC_TOP0_VAL_UP_V_E_PLL, &clk->src_top0);
}
这一步很重要,因为会自动生成 #define CONFIG_SYS_BOARD “cbt4412”。
在适当位置添加以下代码。
+config TARGET_CBT4412
+ bool "Exynos4412 CBT4412 board"
+ select SUPPORT_SPL
+source "board/samsung/cbt4412/Kconfig"
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2009 Samsung Electronics
# Minkyu Kang <mk7.kang@samsung.com>
obj-y += soc.o
-obj-$(CONFIG_CPU_V7A) += clock.o pinmux.o power.o system.o
+obj-$(CONFIG_CPU_V7) += clock.o pinmux.o power.o system.o
obj-$(CONFIG_ARM64) += mmu-arm64.o
obj-$(CONFIG_EXYNOS5420) += sec_boot.o
@@ -13,6 +13,7 @@
obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o
obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o
obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o
+obj-$(CONFIG_EXYNOS4412)+= dmc_init_exynos4412.o clock_init_exynos4412.o
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif
在scripts/config_whitelist.txt中添加
CONFIG_CBT4412
CONFIG_EXYNOS4412
否则报错:make Error:You must add new CONFIG options using Kconfig.The following new ad-hoc CONFIG options were detected。
注意一定按字母顺序添加如下:
@@ -100,6 +100,7 @@ CONFIG_BS_SIZE
CONFIG_BTB
CONFIG_BUILD_ENVCRC
CONFIG_BUS_WIDTH
+CONFIG_CBT4412
CONFIG_CDP_APPLIANCE_VLAN_TYPE
CONFIG_CDP_CAPABILITIES
CONFIG_CDP_DEVICE_ID
@@ -189,6 +190,7 @@ CONFIG_DEBUG_UART_LINFLEXUART
CONFIG_DEBUG_WRITECOUNT
CONFIG_DEEP_SLEEP
CONFIG_DEFAULT
+CONFIG_DEFAULT_CONSOLE
CONFIG_DEFAULT_IMMR
CONFIG_DESIGNWARE_ETH
CONFIG_DEVICE_TREE_LIST
@@ -294,6 +296,7 @@ CONFIG_EXT_PHY
CONFIG_EXT_USB_HOST_BASE
CONFIG_EXYNOS4
CONFIG_EXYNOS4210
+CONFIG_EXYNOS4412
CONFIG_EXYNOS5
CONFIG_EXYNOS5250
CONFIG_EXYNOS5420
在Ubuntu终端中,输入:
ARCH=arm && CROSS_COMPILE=arm-linux-gnueabihf- && export ARCH CROSS_COMPILE
make distclean && make cbt4412_defconfig && make
这里CROSS_COMPILE配置成你自己的交叉编译器名称。
如果显示
./spl/board/samsung/cbt4412/tools/mkcbt4412spl spl/u-boot-spl.bin spl/cbt4412-spl.bin
COPY u-boot.dtb
表明编译成功。注意此处都是关于cbt4412的。如果不是之前配置的核心板型号,则说明有某个宏定义CONFIG_XXX_XXX没有配置正确。
由于本人没有三星提供的mkbl2,所以采用的是三周子的烧写脚本sd_fusing.sh,亲测可用。3
初学者可以直接把/sd_fuse/复制出来。
打开/sd_fuse/tiny4412/sd_fusing.sh,可以看到MKBL2把…/…/spl/u-boot-spl.bin经过校验处理之后生成了bl2.bin。
####################################
# check files
E4412_UBOOT=../../u-boot.bin
E4412_UBOOT_SPL=../../spl/u-boot-spl.bin
MKBL2=../mkbl2
if [ ! -f ${E4412_UBOOT} ]; then
echo "Error: u-boot.bin NOT found, please build it & try again."
exit -1
fi
if [ ! -f ${MKBL2} ]; then
echo "Error: can not find host tool - mkbl2, stop."
exit -1
fi
#<make bl2>
${MKBL2} ${E4412_UBOOT_SPL} bl2.bin 14336
####################################
以下代码可以看到,BL1的地址在第1个block的位置,BL2的地址在第17个block的位置。bl2.bin从第17个block的位置写入。
####################################
# fusing images
signed_bl1_position=1
bl2_position=17
uboot_position=49
#tzsw_position=705
#tzsw_position=1649
#<BL1 fusing>
echo "---------------------------------------"
echo "BL1 fusing"
dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=$1 seek=$signed_bl1_position
#<BL2 fusing>
echo "---------------------------------------"
echo "BL2 fusing"
dd iflag=dsync oflag=dsync if=./bl2.bin of=$1 seek=$bl2_position
#<u-boot fusing>
echo "---------------------------------------"
echo "u-boot fusing"
dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
本人在win10系统中,设置COM6口的参数为波特率115200、8位数据位、1位停止位、无奇偶校验位。
打开xshell连接COM6口,COM6口连接cbt4412核心板的串口0。
U-Boot 2017.11-g0e88f33-dirty (Mar 13 2022 - 13:44:59 +0800) for CBT4412
CPU: Exynos4412 @ 1.4 GHz
Model: CBt4412 board based on Exynos4412
Board: CBt4412 board based on Exynos4412
DRAM: 1 GiB
WARNING: Caches not enabled
MMC Device 0 not found
*** Warning - No MMC card found, using default environment
CBT4412 #
移植后的U-Boot源码地址:https://github.com/HelloTonyLu/u-boot-2022.01-rc4-cbt4412.git
这里讲述的移植工作仅仅是个开头,后面的工作还有很多,比如uart不在debug模式下还不能使用,在eMMC中不能启动uboot, 不支持USB功能,无网络功能等等,需要进一步的完善。
抛砖引玉,供大家讨论,有错误的地方,请不吝赐教。希望有博主分享U-Boot支持DM9000网卡的方法。
非常感谢三周子和大水猫分享其代码!!! 如果没有他们的代码,我可能仍然在黑暗中摸索。