本文主要是uboot——uboot移植的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows windows11 Ubuntu Ubuntu16.04的64位版本 VMware® Workstation 16 Pro 16.2.3 build-19376536 SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 Linux开发板 华清远见 底板: FS4412_DEV_V5 核心板: FS4412 V2 u-boot 2013.01
点击查看本文参考资料
点击查看相关文件下载
一、文件准备 1. u-boot
源码 1.1 源码获取途径 关于u-boot
的官方源码我们可以从这里获取:Obtaining the source 。从官网文档可以看到我们可以有多种下载源码的途径:
仓库地址为:u-boot/u-boot: “Das U-Boot” Source Tree (github.com)
各版本地址为:Tags · u-boot/u-boot (github.com)
我们可以通过以下命令来获取最新版本:
1 git clone https://github.com/u-boot/u-boot
仓库地址为:U-Boot / U-Boot · GitLab (denx.de)
各版本地址为:Tags · U-Boot / U-Boot · GitLab (denx.de)
我们可以通过以下命令获取最新版本:
1 git clone https://source.denx.de/u-boot/u-boot.git
这种方式在官网文档上我没看到,不过也是可以通过ftp
服务器来下载我们需要的版本的,我一般都是在这里下载的,毕竟Github
有时候也没那么好进。通过ftp
服务器下载的话,下载下来的就直接是压缩包了,我是用的华清远见的FS4412
开发板,所以这里选择相配套的版本,也就是u-boot-2013.01.tar.bz2
这个压缩包。
各版本下载地址:Index of /pub/u-boot/ (denx.de)
1.2 获取源码文件 我下载的是u-boot-2013.01.tar.bz2
这个压缩包并将其存放于ubuntu
下的共享文件夹下,路径为:
1 /mnt/hgfs/Sharedfiles/test
1.3 拷贝解压 然后我们可以将这个源码文件拷贝解压到ubuntu
中,方便后边编译,我们可以在终端执行以下命令:
1 2 3 cp /mnt/hgfs/Sharedfiles/test/u-boot-2013.01.tar.bz2 ~/6temp/ # 拷贝压缩包 cd ~/6temp/ tar -xvf u-boot-2013.01.tar.bz2 # 解压
然后我们可以得到下边这些文件(通过ls
命令查看):
1 2 3 4 5 api config.mk drivers include mkconfig rules.mk arch COPYING dts lib nand_spl snapshot.commit board CREDITS examples MAINTAINERS net spl boards.cfg disk fs MAKEALL post test common doc helper.mk Makefile README tools
点击查看部分文件说明
即与CPU
架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改。
arch 与CPU架构相关的源代码 board 与开发板相关的源代码,包含各种官方评估板对应的源码
api 应用接口,一些与硬件无关的API函数 common uboot命令源码 disk 对磁盘设备的支持,主要是磁盘分区相关代码 drivers 设备驱动源码 fs 对文件系统的支持 include 头文件 lib 库文件 net 对网络协议的支持 post 上电自检程序 tools 一些工具文件夹,有些工具编译后才能生成,比如后边会用到的mkimage工具
还有一些其他的文件,这里就不再写了。
2. 移植相关文件 移植相关文件是老师已经写好了的,后边按教程使用即可,可以在这里下载:u-boot-2013.01移植相关文件
下载完毕后,存放于ubuntu
的共享文件夹中:
1 /mnt/hgfs/Sharedfiles/test
我们可直接在windows
下将压缩文件解压,我们将得到下边这些文件:
二、移植过程 首先我们要进入uboot
源码目录,后边所有的命令都在源码的顶层目录下进行:
1 cd ~/6temp/u-boot-2013.01
1. 指定交叉编译工具 uboot
源码并不知道我们使用的处理器架构及交叉编译工具是什么,这里我们需要自己在Makefile
中指定,我们通过下边的命令打开顶层Makefile
文件:
找到下边的语句:
1 2 3 4 ifeq ($(HOSTARCH) ,$(ARCH) )CROSS_COMPILE ?= endif
将其修改为:
1 2 3 4 ifeq (arm,arm)CROSS_COMPILE ?= arm-none-linux-gnueabi- endif
【注意】arm-none-linux-gnueabi-
后边不要有多余的空格。
但是其实还有一种方式,可以避免修改原来的makefile
文件,那就是在使用make
命令的时候指定两个参数:
1 make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- <command>
2. 添加Board
信息 uboot
源码并华清远见的fs4412
开发板,所以需要从源码支持的开发板中找一个硬 件与我们使用的开发板最类似的,在其基础上进行修改,这里参考的是samsung
公司的origen
评估板,这个评估板使用的处理器就是fs4412
。
2.1 准备相关文件 1 2 3 cp -rf board/samsung/origen/ board/samsung/fs4412 # 拷贝相关文件夹 mv board/samsung/fs4412/origen.c board/samsung/fs4412/fs4412.c # 重命名为fs4412 cp include/configs/origen.h include/configs/fs4412.h # 拷贝相关头文件
2.2 修改相关文件 具体修改了哪些文件,及修改前后对比可以看我的github
仓库:feat:修改fs4412相关支持文件 · sumumm/u-boot@e4e483e (github.com) 。修改过程如下:
修改board/samsung/fs4412/Makefile
我们找到如下语句:
1 2 3 ifndef CONFIG_SPL_BUILD COBJS += origen.o endif
将其修改为:
1 2 3 ifndef CONFIG_SPL_BUILD COBJS += fs4412.o endif
(1)我们找到如下语句:
1 # define CONFIG_SYS_PROMPT "ORIGEN # "
将其修改为:
1 # define CONFIG_SYS_PROMPT "fs4412 # "
(2)再找到下边语句:
1 # define CONFIG_IDENT_STRING " for ORIGEN"
将其修改为:
1 # define CONFIG_IDENT_STRING " for fs4412"
我们找到如下语句:
1 origen arm armv7 origen samsung exynos
然后在其下一行添加如下内容(FS4412的相关信息):
1 fs4412 arm armv7 fs4412 samsung exynos
至此,我们在uboot
源码中给我们的板子添加了信息,此时源码就支持我们现在使用的开发板了。
2.3 编译u-boot
接下来我们就可以编译我们刚才修改过的u-boot
了,我们在顶层源码目录下执行:
1 2 make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- fs4412_config # 指定使用 fs4412 配置信息 make V=1 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- j4 # 开始编译整个 u-boot
V=1
表示显示详细编译过程。
j4
表示使用编译平台的4
个核同时进行多线程编译。
3. 添加三星加密引导方式 考虑芯片启动的安全性,Exynos4412
需要三星提供的初始引导加密后我们移植的u-boot
才能被引导运行,所以我们需要在uboot
源码中添加三星提供的加密处理相关代码。
3.1 准备相关文件 主要是拷贝CodeSign4SecureBoot
和sdfuse_q
两个目录及其目录下的所有文件到u-boot
源码顶层目录下,我们在终端执行以下命令:
1 2 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/CodeSign4SecureBoot/ . mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/sdfuse_q/ .
【注意】这之后不要执行make clean
或make distclean
,这会将加密文件清除。
3.2 修改相关文件 具体修改了哪些文件,及修改前后对比可以看我的github
仓库:feat:添加三星加密引导方式相关文件 · sumumm/u-boot@102e8fa (github.com)
我们找到如下语句:
1 2 3 $(obj) u-boot.bin: $(obj) u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $(BOARD_SIZE_CHECK)
修改为如下内容(紧随其后添加一些与加密引导方式相关的编译命令):
1 2 3 4 5 6 7 8 9 10 11 12 13 $ (obj)u-boot.bin: $(obj)u-boot $ (OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $ (BOARD_SIZE_CHECK) @# ./mkuboot @split -b 14336 u-boot.bin bl2 @+make -C sdfuse_q/ @# cp u-boot.bin u-boot-4212.bin @# cp u-boot.bin u-boot-4412.bin @# ./sdfuse_q/add_sign @./sdfuse_q/chksum @./sdfuse_q/add_padding @rm bl2a* @echo
【注意】若是不修改的话,编译的时候可能会报错。
3.3 编写编译脚本 添加了三星加密引导方式后,编译完u-boot
后,我们还需要进行一些列的操作,所以这里边写一个编译脚本,方便编译。
点击查看编译脚本详细内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 # !/bin/sh # ===================================================== # Copyright © hk. 2022-2025. All rights reserved. # File name: qidaink_make.sh # Author : qidaink # Date : 2022-08-19 # Version : # Description: # Others : CROSS_COMPILE -- 当前使用的编译器 # Log : # ====================================================== # # ===================相关参数定义========================= CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}') # 参与编译的内核数量获取 BOARD_NAME="fs4412" # 硬件平台,后续以 origen 评估板为模板 MAKE_PARAM="ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-" # 交叉编译器 sec_path="CodeSign4SecureBoot/" # 三星加密引导方式路径 ROOT_DIR=$(pwd) # 顶层(当前)目录路径 CUR_DIR=${ROOT_DIR##*/} # ===================配置与编译=========================== case "$1" in clean) # 清除编译过程中产生的中间文件而不清除加密文件 echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]make ${MAKE_PARAM} clean \033[0m" echo "\033[1;33m************************************************\033[0m" make ${MAKE_PARAM} mrproper ;; *) # 判断加密引导方式文件目录是否存在 if [ ! -d ${sec_path} ] then echo echo "\033[1;31m************************************************\033[0m" echo "\033[1;31m[ERROR]please get the CodeSign4SecureBoot first!\033[0m" echo "\033[1;31m************************************************\033[0m" return fi # 指定当前使用的硬件平台 make <BOARD_NAME>_config echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]Configuring the Project ... \033[0m" echo "\033[1;33m************************************************\033[0m" make ${MAKE_PARAM} ${BOARD_NAME}_config # 开始编译整个 uboot echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]Building project in progress ... \033[0m" echo "\033[1;33m************************************************\033[0m" make V=1 ${MAKE_PARAM} -j${CPU_JOB_NUM} # 判断是否编译成功 if [ ! -f checksum_bl2_14k.bin ] then echo echo "\033[1;31m!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\033[0m" echo "\033[1;31m[ERROR]There are some error(s) while building uboot, please use command make to check.\033[0m" echo "\033[1;31m!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\033[0m" exit 0 fi # 三星加密引导方式相关操作,必须要有 cp -rf checksum_bl2_14k.bin ${sec_path} cp -rf u-boot.bin ${sec_path} rm checksum_bl2_14k.bin cd ${sec_path} cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-fs4412.bin mv u-boot-fs4412.bin ${ROOT_DIR} rm checksum_bl2_14k.bin rm u-boot.bin # 编译完成提示已经完成 echo echo "\033[1;32m************************************************\033[0m" echo "\033[1;32m[INFO ]The compilation is complete!!!\033[0m" echo "\033[1;32m************************************************\033[0m" echo ;; esac
3.4 添加调试代码 添加完三星加密引导方式后,应该就可以编译u-boot
,然后在开发板中启动u-boot
了,但是有一个问题,就是,对于这块开发板来说外设并不跟三星的origen
评估板一样,我们无法判断到此为止的u-boot
能否在开发板正常启动,这个时候我们就需要添加一段调试代码,可以在u-boot
源码中添加一段使板子上的LED点亮的程序来指示我们的u-boot
已经开始运行了。这一部分的修改也可以查看这里:feat:创建VScode工程并添加调试代码 · sumumm/u-boot@6b8ce64 (github.com)
修改arch/arm/cpu/armv7/start.S
我们找到如下语句:
1 2 3 4 5 6 7 8 9 reset: bl save_boot_params /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0
在134
行(如果u-boot
版本一样的话)也就是上边找到的语句的最后一行的下一行添加以下内容:
1 2 3 4 5 6 7 8 9 /* 点亮 LED */ ldr r0, =0x11000c40 ldr r1, [r0] bic r1, r1, #0xf0000000 orr r1, r1, #0x10000000 str r1, [r0] ldr r0, =0x11000c44 mov r1, #0xff str r1, [r0]
3.5 编译u-boot
我们已经编写了u-boot
编译脚本,所以这里直接通过脚本编译即可:
1 2 sudo chmod 777 qidaink_make.sh ./qidaink_make.sh
编译完成后,我们按照之前的镜像制作方式将移植后的u-boot
下载到SD
开中,然后开发板从SD
卡启动,若移植正确的话,我们将看到一个LED
被点亮,不出意外的话,会发现隔一段时间就会灭掉然后再亮,刚开始以为是移植失败,后来发现是因为u-boot
默认打开了看门狗,而后边又没有正常喂狗,导致开发板复位了,所以这是正常现象。
4. 串口移植 前边我们会发现,即便移植u-boot
完成了,但是依然不适配我们的开发板,我们还需要移植一下串口的驱动,详细的文件修改情况可以查看这里:feat:修改串口驱动 · sumumm/u-boot@6b8a6c5 (github.com)
4.1 修改相关文件 对于串口的移植,我们只需要修改一个文件即可:board/samsung/fs4412/lowlevel_init.S
我们找到如下语句:
在该语句后边添加以下内容:
我们找到如下语句:
在该语句后边添加以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 # if 1 ldr r0, =0x1002330c ldr r1, [r0] orr r1, r1, #0x300 str r1, [r0] ldr r0, =0x11000c08 ldr r1, =0x0 str r1, [r0] /* Clear MASK_WDT_RESET_REQUEST */ ldr r0, =0x1002040c ldr r1, =0x00 str r1, [r0] # endif
我们找到如下语句:
1 2 3 4 5 6 7 8 uart_asm_init: /* setup UART0-UART3 GPIOs (part1) */ mov r0, r7 ldr r1, =EXYNOS4_GPIO_A0_CON_VAL str r1, [r0, #EXYNOS4_GPIO_A0_CON_OFFSET] ldr r1, =EXYNOS4_GPIO_A1_CON_VAL str r1, [r0, #EXYNOS4_GPIO_A1_CON_OFFSET]
在该部分语句最后一句后边添加以下内容:
1 2 3 4 5 6 7 ldr r0, =0x10030000 ldr r1, =0x666666 ldr r2, =CLK_SRC_PERIL0_OFFSET str r1, [r0, r2] ldr r1, =0x777777 ldr r2, =CLK_DIV_PERIL0_OFFSET str r1, [r0, r2]
我们找到如下语句:
将其修改为以下内容:
1 2 3 # if 0 bl tzpc_init # endif
4.2 编译u-boot
我们直接通过编译脚本进行编译:
编译完成后将生成的u-boot-fs4412.bin
制作成可在开发板运行的镜像,下载到SD
卡进行测试,若有如下提示,则证明串口移植成功:
5. 网卡移植 虽然可以通过终端输入命令,但此时的u-boot
还不能使用ping
、tftp
等命令,原因在于命令都是操作网络的,而u-boot
源码中网卡的相关配置与我们当前的板子不匹配,所以还要对网卡进行移植。详细的文件修改情况可以看这里:feat:修改网卡驱动 · sumumm/u-boot@0165b21 (github.com)
5.1 修改相关文件 5.1.1 网络初始化
修改board/samsung/fs4412/fs4412.c
(1)我们找到如下语句:
1 struct exynos4_gpio_part2 *gpio2 ;
在后边添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #ifdef CONFIG_DRIVER_DM9000 #define EXYNOS4412_SROMC_BASE 0X12570000 #define DM9000_Tacs (0x1) #define DM9000_Tcos (0x1) #define DM9000_Tacc (0x5) #define DM9000_Tcoh (0x1) #define DM9000_Tah (0xC) #define DM9000_Tacp (0x9) #define DM9000_PMC (0x1) struct exynos_sromc { unsigned int bw; unsigned int bc[6 ]; }; void exynos_config_sromc (u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) { unsigned int tmp; struct exynos_sromc *srom = (struct exynos_sromc *)(EXYNOS4412_SROMC_BASE); tmp = srom->bw; tmp &= ~(0xF << (srom_bank * 4 )); tmp |= srom_bw_conf; srom->bw = tmp; srom->bc[srom_bank] = srom_bc_conf; } static void dm9000aep_pre_init (void ) { unsigned int tmp; unsigned char smc_bank_num = 1 ; unsigned int smc_bw_conf=0 ; unsigned int smc_bc_conf=0 ; writel(0x00220020 , 0x11000000 + 0x120 ); writel(0x00002222 , 0x11000000 + 0x140 ); writel(0x22222222 , 0x11000000 + 0x180 ); writel(0x0000FFFF , 0x11000000 + 0x188 ); writel(0x22222222 , 0x11000000 + 0x1C0 ); writel(0x0000FFFF , 0x11000000 + 0x1C8 ); writel(0x22222222 , 0x11000000 + 0x1E0 ); writel(0x0000FFFF , 0x11000000 + 0x1E8 ); smc_bw_conf &= ~(0xf <<4 ); smc_bw_conf |= (1 <<7 ) | (1 <<6 ) | (1 <<5 ) | (1 <<4 ); smc_bc_conf = ((DM9000_Tacs << 28 ) | (DM9000_Tcos << 24 ) | (DM9000_Tacc << 16 ) | (DM9000_Tcoh << 12 ) | (DM9000_Tah << 8 ) | (DM9000_Tacp << 4 ) | (DM9000_PMC)); exynos_config_sromc(smc_bank_num,smc_bw_conf,smc_bc_conf); } #endif
(2)我们再找到如下语句:
1 gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100 UL);
在语句后边添加以下内容:
1 2 3 #ifdef CONFIG_DRIVER_DM9000 dm9000aep_pre_init(); #endif
(3)在整个文件尾部添加如下内容:
1 2 3 4 5 6 7 8 9 10 #ifdef CONFIG_CMD_NET int board_eth_init (bd_t *bis) { int rc = 0 ; #ifdef CONFIG_DRIVER_DM9000 rc = dm9000_initialize(bis); #endif return rc; } #endif
5.1.2 网络配置修改
修改include/configs/fs4412.h
文件
(1)我们找到如下语句:
将其修改为如下内容:
(2)我们找到如下语句:
将其修改为如下内容:
(3)我们找到如下语句(也就是文件末尾):
在其前边添加以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #ifdef CONFIG_CMD_NET #define CONFIG_NET_MULTI #define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_BASE 0x05000000 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE + 4) #define CONFIG_DM9000_USE_16BIT #define CONFIG_DM9000_NO_SROM 1 #define CONFIG_ETHADDR 11:22:33:44:55:66 #define CONFIG_IPADDR 192.168.10.102 #define CONFIG_SERVERIP 192.168.10.101 #define CONFIG_GATEWAYIP 192.168.10.1 #define CONFIG_NETMASK 255.255.255.0 #endif
5.2 编译u-boot
我们直接通过编译脚本进行编译:
编译完成后将生成的u-boot-fs4412.bin
制作成可在开发板运行的镜像,下载到SD
卡进行测试,我们再SecureCRT
中执行以下命令:
1 2 fs4412 # ping 192.168.10.101 fs4412 # ping 192.168.10.100
若有以下提示,则证明网卡移植成功:
6. eMMC
移植 我们在启动开发板的时候,会看到这样的提示:
若是这里eMMC
可以正常读取的话,这里应该是会显示容量大小,而不是这样显示,所以我这里我们还需要对eMMC
进行移植。详细的文件更改情况可以查看这里:feat:修改eMMC驱动 · sumumm/u-boot@e747fb7 (github.com)
6.1 文件准备 这里我们需要准备一些相关的移植文件到工程中:
arch/arm/cpu/armv7/exynos/
1 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/movi.c arch/arm/cpu/armv7/exynos/
1 2 3 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/cmd_movi.c common/ mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/cmd_mmc.c common/ mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/cmd_mmc_fdisk.c common/
1 2 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/mmc.c drivers/mmc/ mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/s5p_mshc.c drivers/mmc/
1 2 3 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/mmc.h include/ mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/movi.h include/ mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/s5p_mshc.h include/
6.2 修改相关文件 6.2.1 eMMC
初始化
arch/arm/cpu/armv7/exynos/Makefile
我们将movi.c
拷贝到了u-boot
源码的arch/arm/cpu/armv7/exynos/
目录下,添加的新文件也要编译,所以对应的Makefile
也要修改。
我们找到如下语句:
1 COBJS += clock.o power.o soc.o system.o pinmux.o
将其修改为以下内容:
1 COBJS += clock.o power.o soc.o system.o pinmux.o movi.o
修改板级文件board/samsung/fs4412/fs4412.c
(1)我们找到如下语句:
1 #include <asm/arch/mmc.h>
在语句后边添加以下内容:
1 2 #include <asm/arch/clk.h> #include "origen_setup.h"
(2)我们再找到如下内容:
1 #ifdef CONFIG_GENERIC_MMC
然后在该语句后边添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 u32 sclk_mmc4; #define __REGMY(x) (*((volatile u32 *)(x))) #define CLK_SRC_FSYS __REGMY(EXYNOS4_CLOCK_BASE + CLK_SRC_FSYS_OFFSET) #define CLK_DIV_FSYS3 __REGMY(EXYNOS4_CLOCK_BASE + CLK_DIV_FSYS3_OFFSET) int emmc_init () { u32 tmp; u32 clock; u32 i; tmp = CLK_SRC_FSYS & ~(0x000f0000 ); CLK_SRC_FSYS = tmp | 0x00060000 ; tmp = CLK_DIV_FSYS3 & ~(0x0000ff0f ); clock = get_pll_clk(MPLL)/1000000 ; for (i=0 ; i<=0xf ; i++) { sclk_mmc4=(clock/(i+1 )); if (sclk_mmc4 <= 160 ) { CLK_DIV_FSYS3 = tmp | (i<<0 ); break ; } } emmcdbg("[mjdbg] sclk_mmc4:%d MHZ; mmc_ratio: %d\n" ,sclk_mmc4,i); sclk_mmc4 *= 1000000 ; writel(readl(0x11000048 )&~(0xf ),0x11000048 ); writel(readl(0x11000040 )&~(0xff ),0x11000040 ); writel(readl(0x11000048 )&~(3 <<4 ),0x11000048 ); writel(readl(0x11000044 )&~(1 <<2 ),0x11000044 ); writel(readl(0x11000040 )&~(0xf <<8 )|(1 <<8 ),0x11000040 ); udelay(100 *1000 ); writel(readl(0x11000044 )|(1 <<2 ),0x11000044 ); writel(0x03333133 , 0x11000040 ); writel(0x00003FF0 , 0x11000048 ); writel(0x00002AAA , 0x1100004C ); #ifdef CONFIG_EMMC_8Bit writel(0x04444000 , 0x11000060 ); writel(0x00003FC0 , 0x11000068 ); writel(0x00002AAA , 0x1100006C ); #endif #ifdef USE_MMC4 smdk_s5p_mshc_init(); #endif }
(3)我们找到board_mmc_init
函数,并将函数体内原来的代码删掉,修改为以下内容:
1 2 3 4 5 6 7 8 int board_mmc_init (bd_t *bis) { int i, err; #ifdef CONFIG_EMMC err = emmc_init(); #endif return err; }
(4)我们在文件末尾添加以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #ifdef CONFIG_BOARD_LATE_INIT #include <movi.h> int chk_bootdev (void ) { char run_cmd[100 ]; struct mmc *mmc ; int boot_dev = 0 ; int cmp_off = 0x10 ; ulong start_blk, blkcnt; mmc = find_mmc_device(0 ); if (mmc == NULL ) { printf ("There is no eMMC card, Booting device is SD card\n" ); boot_dev = 1 ; return boot_dev; } start_blk = (24 *1024 /MOVI_BLKSIZE); blkcnt = 0x10 ; sprintf (run_cmd,"emmc open 0" ); run_command(run_cmd, 0 ); sprintf (run_cmd,"mmc read 0 %lx %lx %lx" ,CFG_PHY_KERNEL_BASE,start_blk,blkcnt); run_command(run_cmd, 0 ); sprintf (run_cmd,"emmc close 0" ); run_command(run_cmd, 0 ); return 0 ; } int board_late_init (void ) { int boot_dev =0 ; char boot_cmd[100 ]; boot_dev = chk_bootdev(); if (!boot_dev) { printf ("\n\nChecking Boot Mode ... EMMC4.41\n" ); } return 0 ; } #endif
6.2.2 添加eMMC
命令
我们拷贝了cmd_movi.c
、cmd_mmc.c
、cmd_mmc_fdisk.c
拷贝到u-boot
源码的common/
目录下,新添加的文件需要参加编译,需要修改对应的Makefile
:
我们找到如下语句:
1 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
在语句后边添加以下内容:
1 2 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc_fdisk.o COBJS-$(CONFIG_CMD_MOVINAND) += cmd_movi.o
我们前边还拷贝了mmc.c
、s5p_mshc.c
拷贝到u-boot
源码的drivers/mmc/
目录下,所以对应的Makefile
需要修改。
我们找到如下语句:
1 COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
在后边添加以下内容:
1 COBJS-$(CONFIG_S5P_MSHC) += s5p_mshc.o
6.2.3 eMMC
配置
我们找到如下语句,也就是文件末尾:
在前边添加以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 # define CONFIG_EVT1 1 /* EVT1 */ # ifdef CONFIG_EVT1 # define CONFIG_EMMC44_CH4 //eMMC44_CH4 (OMPIN[5:1] = 4) # ifdef CONFIG_SDMMC_CH2 # define CONFIG_S3C_HSMMC # undef DEBUG_S3C_HSMMC # define USE_MMC2 # endif # ifdef CONFIG_EMMC44_CH4 # define CONFIG_S5P_MSHC # define CONFIG_EMMC 1 # define USE_MMC4 /* #define CONFIG_EMMC_8Bit */ # define CONFIG_EMMC_EMERGENCY /*#define emmcdbg(fmt,args...) printf(fmt ,##args) */ # define emmcdbg(fmt ,args...) # endif # endif /*end CONFIG_EVT1*/ # define CONFIG_CMD_MOVINAND # define CONFIG_CLK_1000_400_200 # define CFG_PHY_UBOOT_BASE CONFIG_SYS_SDRAM_BASE + 0x3e00000 # define CFG_PHY_KERNEL_BASE CONFIG_SYS_SDRAM_BASE + 0x8000 # define BOOT_MMCSD 0x3 # define BOOT_EMMC43 0x6 # define BOOT_EMMC441 0x7 # define CONFIG_BOARD_LATE_INIT
6.3 编译u-boot
我们直接通过编译脚本进行编译:
编译完成后将生成的u-boot-fs4412.bin
制作成可在开发板运行的镜像,下载到SD
卡进行测试,若有如下提示,则证明eMMC
移植成功:
7. 电源管理移植 u-boot
源码中对电源管理芯片的配置与fs4412
板子不匹配,后续有可能会导致内核启动卡死,这里还需要对电源管理芯片相关的代码进行修改和配置。详细的文件修改可以看这里:feat:修改电源管理驱动 · sumumm/u-boot@98cb639 (github.com)
7.1 文件准备 这里我们需要准备一些相关的移植文件到工程中:
1 mv /mnt/hgfs/Sharedfiles/test/u-boot-2013.01移植相关文件/movi.c arch/arm/cpu/armv7/exynos/
7.2 修改相关文件
drivers/power/pmic/Makefile
我们拷贝了pmic_s5m8767.c
到u-boot
源码的drivers/power/pmic/
目录下,新文件需要参与编译,所以需要修改Makefile
。
我们找到如下语句:
1 COBJS-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
然后在该语句后边添加以下内容:
1 COBJS-$(CONFIG_POWER_S5M8767) += pmic_s5m8767.o
我们还需要将添加的函数在相关的头文件中进行声明,我们找到如下语句:
1 int pmic_set_output (struct pmic *p, u32 reg, int ldo, int on) ;
在该语句后添加如下内容:
1 void pmic_s5m8767_init (void ) ;
修改配置文件include/configs/fs4412.h
我们找到如下语句,也就是文件末尾:
我们在该语句前边添加以下内容:
1 #define CONFIG_POWER_S5M8767
修改板级文件board/samsung/fs4412/fs4412.c
我们找到board_init
函数的如下语句:
1 2 3 #ifdef CONFIG_DRIVER_DM9000 dm9000aep_pre_init(); #endif
我们在最后一句后边添加以下内容:
1 2 3 #ifdef CONFIG_POWER_S5M8767 pmic_s5m8767_init(); #endif
我们找到如下语句:
1 COBJS-$(CONFIG_POWER) += power_core.o
然后将该语句修改为:
修改架构文件arch/arm/cpu/armv7/s5p-common/cpu_info.c
我们找到如下语句:
1 #include <asm/arch/clk.h>
在该语句后添加以下内容:
7.3 编译u-boot
我们直接通过编译脚本进行编译:
编译完成后将生成的u-boot-fs4412.bin
制作成可在开发板运行的镜像,下载到SD
卡进行测试,若有如下提示(我记得在移植之前是不显示这个的),则证明电源管理移植成功:
三、其他修改 1. 编译脚本 编译完u-boot
后,需要生成可在开发板裸机运行的镜像文件,我们可以咋子编译脚本中进行修改,这样我们执行脚本就可以生成相应的镜像文件吗,而不需要再输入那么长一段命令了。
点击查看修改后的编译脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 # !/bin/sh # ===================================================== # Copyright © hk. 2022-2025. All rights reserved. # File name: qidaink_make.sh # Author : qidaink # Date : 2022-08-19 # Version : # Description: # Others : CROSS_COMPILE -- 当前使用的编译器 # Log : # ====================================================== # # ===================相关参数定义========================= CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}') # 参与编译的内核数量获取 BOARD_NAME="fs4412" # 硬件平台,后续以 origen 评估板为模板 MAKE_PARAM="ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-" # 交叉编译器 sec_path="CodeSign4SecureBoot/" # 三星加密引导方式路径 ROOT_DIR=$(pwd) # 顶层(当前)目录路径 CUR_DIR=${ROOT_DIR##*/} # ===================配置与编译=========================== case "$1" in clean) # 清除编译过程中产生的中间文件而不清除加密文件 echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]make ${MAKE_PARAM} clean \033[0m" echo "\033[1;33m************************************************\033[0m" make ${MAKE_PARAM} mrproper ;; image) # 制作镜像文件 echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]Creating an Image File... \033[0m" echo "\033[1;33m************************************************\033[0m" sudo dd if=/dev/zero of=zero.bin count=1 # 制作一个512Bytes的空镜像 sudo dd if=/dev/zero of=clear.bin count=2048 # 制作一个1M的空镜像 # 判断 u-boot-fs4412.bin 文件是否存在 if [ ! -e u-boot-fs4412.bin ] then echo echo "\033[1;31m************************************************\033[0m" echo "\033[1;31m[ERROR]please get the u-boot-fs4412.bin first! \033[0m" echo "\033[1;31m************************************************\033[0m" return fi cat zero.bin u-boot-fs4412.bin > win-u-boot-fs4412.bin echo echo "\033[1;32m************************************************\033[0m" echo "\033[1;32m[INFO ]Image finished!!! \033[0m" echo "\033[1;32m************************************************\033[0m" ;; *) # 判断加密引导方式文件目录是否存在 if [ ! -d ${sec_path} ] then echo echo "\033[1;31m************************************************\033[0m" echo "\033[1;31m[ERROR]please get the CodeSign4SecureBoot first!\033[0m" echo "\033[1;31m************************************************\033[0m" return fi # 指定当前使用的硬件平台 make <BOARD_NAME>_config echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]Configuring the Project ... \033[0m" echo "\033[1;33m************************************************\033[0m" make ${MAKE_PARAM} ${BOARD_NAME}_config # 开始编译整个 uboot echo echo "\033[1;33m************************************************\033[0m" echo "\033[1;33m[INFO ]Building project in progress ... \033[0m" echo "\033[1;33m************************************************\033[0m" make V=1 ${MAKE_PARAM} -j${CPU_JOB_NUM} # 判断是否编译成功 if [ ! -f checksum_bl2_14k.bin ] then echo echo "\033[1;31m!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\033[0m" echo "\033[1;31m[ERROR]There are some error(s) while building uboot, please use command make to check.\033[0m" echo "\033[1;31m!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\033[0m" exit 0 fi # 三星加密引导方式相关操作,必须要有 cp -rf checksum_bl2_14k.bin ${sec_path} cp -rf u-boot.bin ${sec_path} rm checksum_bl2_14k.bin cd ${sec_path} cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-fs4412.bin mv u-boot-fs4412.bin ${ROOT_DIR} rm checksum_bl2_14k.bin rm u-boot.bin # 编译完成提示已经完成 echo echo "\033[1;32m************************************************\033[0m" echo "\033[1;32m[INFO ]The compilation is complete!!!\033[0m" echo "\033[1;32m************************************************\033[0m" echo ;; esac
这样,我们每次编译完毕后,可以在终端执行:
这样便会生成我们需要的win-u-boot-fs4412.bin
文件啦。
2. 板子名称 我们上边已经将u-boot
进行移植,移植到了我们使用的fs4412
板子上,但是打印出来的提示信息中板子名称依然是原来的,如何修改呢?
board/samsung/fs4412/fs4412.c
我们找到如下语句:
1 2 3 4 5 6 7 #ifdef CONFIG_DISPLAY_BOARDINFO int checkboard (void ) { printf ("\nBoard: ORIGEN\n" ); return 0 ; } #endif
这个函数就是打印输出板子名称的,我们在这里将其修改为自己想要的板子名称就可以啦。