Uboot 版本:u-boot-2013.01
开发板:FS_4412 平台(Exynos4412,可以根据自己的板子修改,只要是4412的过程都是一样的)
一、建立自己的平台
1、下载源码
我们可以在下面这个网站上下载最新的和以前任一版本的uboot
ftp://ftp.denx.de/pub/u-boot/
这里我们使用的是u-boot-2013.01
2、解压uboot 源码并进入目录
3、指定交叉编译工具链
a -- 打开根目录下的Makefile
b -- 添加交叉编译工具链信息
4、指定产品CPU
我们产品用的CPU 是exynos 4412
查看u-boot 源码该CPU 是否已支持
U-boot 已支持,见arch/arm/cpu/armv7/exynos/
5、指定产品BOARD
找一个最类似的board 配置修改, 这里我们参考的是board/samsung/origen/
a -- 修改board/samsung/ 板级相关文件夹,复制 board/samsung/origen/,重命名为fs4412
b -- 修改board/samsung/fs4412/Makefile信息
修改 origen.o 为 fs4412.o
c -- 修改include/configs/fs4412.h配置文件
这里同样是先复制 inlcude/configs/origen.h,生成 inlcude/configs/fs4412.h
打开fs4412.h,修改以下文件:
将原来的#define CONFIG_SYS_PROMPT "ORIGEN #" 改成:
将原来的#define CONFIG_IDENT_STRING for ORIGEN 改成
d -- 配置boards.cfg
打开uboot根目录下的boards.cfg,在origen后新增
6、编译u-boot
$ make distclean
$ make fs4412_config (可以在inlcude/config.mk及include/config.h下看到配置好的信息)
$ make
编译完成后生成的u-boot.bin 就是可执行的镜像文件。
烧写uboot 命令:
tftp 41000000 u-boot.bin
movi write uboot 41000000
但是该文件还不能在我们板子上运行,我们需要对u-boot 源代码进行相应的修改。
二、实现能看到串口终端信息
1、确认第一条指令有运行到(点灯法)
a -- 在arch/arm/cpu/armv7/start.S 134 行后添加点灯程序
b -- 添加三星加密方式
exynos 需要三星提供的初始引导加密后,我们的u-boot,才能被引导运行
将sdfuse_q 目录拷贝到u-boot-2013.01 源码目录下
注:sdfuse_q 三星提供的加密处理
将CodeSign4SecureBoot 目录拷贝到u-boot-2013.01 源码目录下
注:CodeSign4SecureBoot 三星提供的安全启动方式
c -- 修改Makefile
$vim Makefile
修改实现sdfuse_q 的编译
在
下添加
注意是tab 键缩进的,否则makefile 编译报错
注意如果执行了make distclean 需重新拷贝CodeSign4SecureBoot
d -- 拷贝编译脚本
将 build.sh 拷贝到uboot 根目录下,并加上执行权限,并执行该脚本 注:build.sh 脚本方式完成自动添加加密方式,是自己编写的
编译生成所需文件u-boot_fs4412.bin
烧写新的u-boot_fs4412.bin
复位,发现灯有点亮,说明我们的u-boot 有运行到
附:build.sh脚本文件
#!/bin/sh sec_path="CodeSign4SecureBoot/" CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}') ROOT_DIR=$(pwd) CUR_DIR=${ROOT_DIR##*/} case "$1" in clean) echo make clean make mrproper ;; *) if [ ! -d $sec_path ] then echo "**********************************************" echo "[ERR]please get the CodeSign4SecureBoot first" echo "**********************************************" return fi make fs4412_config make -j$CPU_JOB_NUM if [ ! -f checksum_bl2_14k.bin ] then echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "There are some error(s) while building uboot, please use command make to check." echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 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 ;; esac
2、实现串口输出
修改lowlevel_init.S 文件
$vim board/samsung/fs4412/lowlevel_init.S
a -- 添加临时栈
在
lowlevel_init:
后添加
b -- 添加关闭看门狗代码
在
beq wakeup_reset
后添加
c -- 添加串口初始化代码
在uart_asm_init: 的
str r1, [r0, #EXYNOS4_GPIO_A1_CON_OFFSET]
后添加
注释掉trustzone 初始化
注释掉
bl uart_asm_init
下的
bl tzpc_init
重新编译u-boot
$ ./build.sh
烧写新的u-boot_fs4412.bin
复位会看到串口信息
三、网卡移植
1、添加网络初始化代码
$vim board/samsung/fs4412/fs4412.c
在struct exynos4_gpio_part2 *gpio2; 后添加
#ifdef CONFIG_DRIVER_DM9000 #define EXYNOS4412_SROMC_BASE 0X12570000 #define DM9000_Tacs (0x1) // 0clk address set-up #define DM9000_Tcos (0x1) // 4clk chip selection set-up #define DM9000_Tacc (0x5) // 14clk access cycle #define DM9000_Tcoh (0x1) // 1clk chip selection hold #define DM9000_Tah (0xC) // 4clk address holding time #define DM9000_Tacp (0x9) // 6clk page mode access cycle #define DM9000_PMC (0x1) // normal(1data)page mode configuration struct exynos_sromc { unsigned int bw; unsigned int bc[6]; }; /* * s5p_config_sromc() - select the proper SROMC Bank and configure the * band width control and bank control registers * srom_bank - SROM * srom_bw_conf - SMC Band witdh reg configuration value * srom_bc_conf - SMC Bank Control reg configuration value */ 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); /* Configure SMC_BW register to handle proper SROMC * bank */ tmp = srom->bw; tmp &= ~(0xF << (srom_bank * 4)); tmp |= srom_bw_conf; srom->bw = tmp; /* Configure SMC_BC * register */ 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; /* gpio configuration */ writel(0x00220020, 0x11000000 + 0x120); writel(0x00002222, 0x11000000 + 0x140); /* 16 Bit bus width */ 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
#ifdef CONFIG_DRIVER_DM9000 dm9000aep_pre_init(); #endif
在文件末尾添加
#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
$ vim include/configs/fs4412.h
修改
#undef CONFIG_CMD_PING
为
#def ine CONFIG_CMD_PING
修改
#undef CONFIG_CMD_NET
为
#def ine CONFIG_CMD_NET
在文件末尾
#endif /* __CONFIG_H */
前面添加
3、重新编译u-boot
$ ./build.sh
烧写新的u-boot_fs4412.bin
复位后
# ping 192.168.9.120
四、FLASH 移植(EMMC)
1、初始化EMMC
$cp movi.c arch/arm/cpu/armv7/exynos/
$vim arch/arm/cpu/armv7/exynos/Makefile
在pinmux.o 后添加movi.o
修改板级文件
$vim board/samsung/fs4412/fs4412.c
在
#include <asm/arch/mmc.h>
后面添加
#include <asm/arch/clk.h>
#include "origen_setup.h"
在
#ifdef CONFIG_GENERIC_MMC
后面添加
u32 sclk_mmc4; /*clock source for emmc controller*/ #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; /* setup_hsmmc_clock */ /* MMC4 clock src = SCLKMPLL */ tmp = CLK_SRC_FSYS & ~(0x000f0000); CLK_SRC_FSYS = tmp | 0x00060000; /* MMC4 clock div */ 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) //200 { CLK_DIV_FSYS3 = tmp | (i<<0); break; } } emmcdbg("[mjdbg] sclk_mmc4:%d MHZ; mmc_ratio: %d\n",sclk_mmc4,i); sclk_mmc4 *= 1000000; /* * MMC4 EMMC GPIO CONFIG * * GPK0[0] SD_4_CLK * GPK0[1] SD_4_CMD * GPK0[2] SD_4_CDn * GPK0[3:6] SD_4_DATA[0:3] */ writel(readl(0x11000048)&~(0xf),0x11000048); //SD_4_CLK/SD_4_CMD pull-down enable writel(readl(0x11000040)&~(0xff),0x11000040);//cdn set to be output writel(readl(0x11000048)&~(3<<4),0x11000048); //cdn pull-down disable writel(readl(0x11000044)&~(1<<2),0x11000044); //cdn output 0 to shutdown the emmc power writel(readl(0x11000040)&~(0xf<<8)|(1<<8),0x11000040);//cdn set to be output udelay(100*1000); writel(readl(0x11000044)|(1<<2),0x11000044); //cdn output 1 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 }
int board_mmc_init(bd_t *bis) { int i, err; #ifdef CONFIG_EMMC err = emmc_init(); #endif return err; }
#ifdef CONFIG_BOARD_LATE_INIT #include <movi.h> int chk_bootdev(void)//mj for boot device check { 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; }
2、添加相关命令
$ cp cmd_movi.c common/
$ cp cmd_mmc.c common/
$ cp cmd_mmc_fdisk.c common/
修改Makefile
$ vim common/Makefile
在
COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
后添加
COBJS-$(CONFIG_CMD_MMC) += cmd_mmc_fdisk.o
COBJS-$(CONFIG_CMD_MOVINAND) += cmd_movi.o
添加驱动
$ cp mmc.c drivers/mmc/
$ cp s5p_mshc.c drivers/mmc/
$ cp mmc.h include/
$ cp movi.h include/
$ cp s5p_mshc.h include/
修改Makefile
$vim drivers/mmc/Makefile
添加
COBJS-$(CONFIG_S5P_MSHC) += s5p_mshc.o
3、添加EMMC 相关配置
$vim include/configs/fs4412.h
添加
#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...) */ #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
$ ./build.sh
烧写新的u-boot_fs4412.bin
复位后
# mmcinfo