创客exynos-fs4412系统移植-(uboot,内核,文件系统)

fs4412系统移植学习笔记

环境:

  1. ubuntu 14.04 发行版
  2. FS4412 实验平台
  3. 交叉编译工具:arm-none-linux-gnueabi-
  4. gcc: 4.8.5

目录

(A) uboot移植

一 uboot源码结构概括

使用uboot引导启动Linux是Linux嵌入式开发中最常使用的方式
  • uboot源码下载
    http://www.denx.de/wiki/U-Boot/
    本次移植使用u-boot-2013.01版本
  • 为什么使用uboot
    • 代码结构清晰
    • 支持丰富的处理器与开发板,易于移植
    • 支持丰富的用户命令
    • 支持丰富的网络协议
    • 支持丰富的文件系统
    • 支持丰富的设备驱动
    • 更新活跃、用户较多、资料丰富
    • 开放源代码
    • 较高的稳定性
    • 不具有通用性(不同的处理器、开发板uboot不可通用)

源码结构

u-boot-2013.01版本源码结构
u-boot-2013.01源码

平台相关代码

即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改

目录功能
arch与CPU架构相关的源代码
board与开发板相关的源代码,包含各种官方评估板对应的源码
平台无关代码
目录功能
api应用接口
common对磁盘设备的支持
disk对磁盘设备的支持
drivers设备驱动代码
fs对文件系统的支持
include头文件
lib
net对网络协议的支持
post上电自检程序
配置文件,帮助文档,示例程序,帮助等
目录功能
README说明文档
doc帮助文档
Makefile编译管理
CREDITS开发者
COPYING版权
examples示例程序
tools工具

二 uboot配置与编译

1. fs4412平台配置

1.1 下载uboot源码

在uboot官网下载uboot源码(u-boot-2013.01.tar.bz2)
ftp://ftp.denx.de/pub/u-boot/

1.2 解压uboot源码

拷贝uboot源码到工作目录下,解压并进入顶层目录

$ tar  xvf  u-boot-2013.01.tar.bz2
$ cd  u-boot-2013.01/
1.3指定交叉编译工具信息

打开Makefile,在Makefile中指定要使用的处理器架构及交叉编译工具

ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif

修改为如下内容,然后保存退出

ifeq (arm,arm)
CROSS_COMPILE ?= arm-none-linux-gnueabi-
endif
1.4 添加Board信息

在uboot源码中选择samsung公司的origen开发板对其进行修改,以适配fs4412开发板
a - 复制origen开发板源码目录复制为fs4412

$ cp  -rf  board/samsung/origen/  board/samsung/fs4412
$ mv  board/samsung/fs4412/origen.c  board/samsung/fs4412/fs4412.c

修改fs4412目录下Makefile内容:
将:

ifndef CONFIG_SPL_BUILD
COBJS	+= origen.o
endif

修改为如下内容,然后保存退出

ifndef CONFIG_SPL_BUILD
COBJS	+= fs4412.o
endif

b - 拷贝origen相关的头文件并重命名

cp  include/configs/origen.h  include/configs/fs4412.h

修改fs4412.h信息:
将:

#define CONFIG_SYS_PROMPT		"ORIGEN # "

#define CONFIG_IDENT_STRING		" for ORIGEN"

修改为:

#define CONFIG_SYS_PROMPT		"fs4412 # "

#define CONFIG_IDENT_STRING		" for fs4412"

c - 打开uboot源码顶层目录下的boards.cfg
在:

origen			     arm	 armv7	     origen		 samsung	exynos

后添加fs4412信息,然后保存退出:

fs4412			     arm	 armv7	     fs4412		 samsung	exynos
1.5 编译uboot

到此为止就可以指定Board信息了,在uboot顶层目录执行:

$ make  fs4412_config

编译uboot

$ make

编译完成后会在源码顶层目录下生成u-boot.bin文件,但该文件还不能在我们的开发板 上运行,因为以上操作我们只是把origen相关的文件的名字改成了fs4412,使uboot能 识别fs4412开发板,但文件中的代码还是origen的,和我们的开发板不匹配,所以我 们还需要进一步进行修改和配置

2. 添加三星加密引导方式

考虑芯片启动的安全性,Exynos4412需要三星提供的初始引导加密后我们的u-boot才 能被引导运行,所以我们需要在uboot源码中添加三星提供的加密处理代码

2.1 添加三星加密引导方式文件

将资料中“移植相关文件”下的
sdfuse_q
CodeSign4SecureBoot
目录拷贝到uboot源 码的顶层目录下 *这之后不要执行make clean或make distclean,这会将加密文件清除)

因为添加的加密文件也要编译,所以对应的Makefile也要修改
在:

$(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.1 添加调试代码

很多时候我们不确定uboot是否已经在板子上运行,所以我们在uboot源码中添加一段 代码使板子上的LED点亮,这样如果看到LED亮的话就表示uboot已经在运行了

打开uboot启动后的第一段代码

$ vi  arch/arm/cpu/armv7/start.S

在第134行后添加如下代码(即点亮LED2),然后保存退出

	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.2 添加编译脚本

使用make命令编译时只链接uboot源码中的相关代码,而我们添加的初始引导加密的代码不会被连接到u-boot.bin中,所以这里我们自己编写编译脚本build.sh,这个脚本中除了对uboot源码进行配置和编译外还将初始引导加密代码链接到了u-boot.bin上, 最终生成一个完成的uboot镜像u-boot-fs4412.bin

将资料中“移植相关文件”下的build.sh拷贝到uboot源码的顶层目录下

给编译脚本添加可执行权限

$ chmod  777  build.sh	
3.3 编译uboot

通过脚本编译uboot源码

$ ./build.sh

编译完成后在源码的顶层目录下会生成“u-boot-fs4412.bin”

4. 实现串口输出

虽然uboot已经能在开发板上加载运行,但是此时的uboot还不能在终端上打印信息, 原因在于uboot源码中对UART的配置与我们实际的硬件不匹配

4.1 修改UART源码
$ vi  board/samsung/fs4412/lowlevel_init.S

lowlevel_init:

后添加如下内容(初始化临时栈)

	ldr  sp,=0x02060000

beq	wakeup_reset

后添加如下内容(关闭看门狗)

#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

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]

后添加如下内容(UART初始化)

	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]

注释掉

bl uart_asm_init
后的一条语句,然后保存退出
#if 0
	bl tzpc_init
#endif
4.2 编译uboot

通过脚本编译uboot源码

$ ./build.sh

三 SD卡启动盘制作

3.1 bin文件制作

烧写工具默认从 0 扇区开始烧写,这里我们自己在 uboot 之前放一个 512 字节的空镜像
a. 将资料中“u-boot 镜像”中的 u-boot-fs4412.bin 拷贝到工作目录下
b. 在终端输入如下命令,制作一个 512 字节的空镜像

$ sudo dd if=/dev/zero of=zero.bin count=1

显示如下信息,则表示制作成功
在这里插入图片描述
c. 执行如下命令,将 uboot 追加到 zero.bin 之后生成 sd-u-boot-fs4412.bin

$ cat zero.bin u-boot-fs4412.bin > sd-u-boot-fs4412.bin

d. 再执行如下命令,制作一个 1M 的空镜像(用于擦除 SD 卡中原有的数据)

$ sudo dd if=/dev/zero of=clear.bin count=2048

3.2 烧写bin文件到SD卡

我使用的烧录工具是图形化的Etcher
下载Etcher工具,解压得到Appimage文件,双击执行
在这里插入图片描述
a. 烧写擦除镜像(clear.bin)
选择Etcher界面中的Flash from file,选择好要烧写的clear.bin
如果选择时工作目录下看不到bin文件,可以将右下角的格式筛选改为ALL
在这里插入图片描述
选择好后会提示一个警告信息,选择Continue继续
在这里插入图片描述
然后点击Select target选择要烧录的设备
在这里插入图片描述
选择好要烧写的SD卡,点击Select继续,注意不要选错
写卡千万条,安全第一条,选卡不规范,数据两行泪
在这里插入图片描述
点击Flash!开始烧写SD卡!
在这里插入图片描述
因为 clear.bin 为空镜像,所以写入后 SD 卡中的前 2048 个扇区中的数据被擦除
b. 烧写sd-u-boot-fs4412.bin到SD卡
重复烧写clear.bin的步骤将sd-u-boot-fs4412.bin到SD卡

3.3 测试uboot

将 SD 卡插入开发板的卡槽,调整拨码开关为 SD 卡启动,查看 uboot 是否能正常启动
注:uboot 正常启动后 LED2 灯会点亮且终端上也会打印 uboot 相关的信息

四 网卡移植

以上步骤完成后,uboot测试的点灯和uart功能正常,也可以通过终端输入命令,此时的uboot还不能使用ping、tftp等命令,原因在于 命令都是操作网络的,而uboot源码中网卡的相关配置与我们当前的板子不匹配,所以 我们还要对网卡进行移植

4.1 修改网络初始化代码

$ vi  board/samsung/fs4412/fs4412.c

struct exynos4_gpio_part2 *gpio2;

后添加如下内容

#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);

	/* 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

gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);

后添加如下内容

#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

4.2 修改网络配置代码

$ vi  include/configs/fs4412.h

#undef CONFIG_CMD_PING

修改为

#define CONFIG_CMD_PING

再将

#undef CONFIG_CMD_NET

修改为

#define CONFIG_CMD_NET

在文件末尾

#endif	/* __CONFIG_H */

前添加如下内容,然后保存退出

#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.9.200
#define CONFIG_SERVERIP	192.168.9.120
#define CONFIG_GATEWAYIP	192.168.9.1
#define CONFIG_NETMASK	255.255.255.0
#endif

4.3 编译与测试uboot

通过脚本编译uboot源码

$ ./build.sh

参照之前的实验将生成的u-boot-fs4412.bin烧写到SD卡中,开发板选择SD卡启动, 然后上电查看现象;设置好相关的环境变量,使用网线连接开发板与开发主机,使用 ping命令连接ubuntu,若显示“host xxx.xxx.xxx.xxx is alive”则表示网卡移植成功

五 EMMC移植

因为uboot源码中对EMMC的配置与我们的板子不匹配,这里还需要对EMMC相关的代码进行修改和配置

5.1 修改EMMC初始化代码

将资料中“移植相关文件”下的movi.c拷贝到uboot源码的arch/arm/cpu/armv7/exynos/ 目录下

因为添加的新文件也要编译,所以对应的Makefile也要修改

$ vi  arch/arm/cpu/armv7/exynos/Makefile

COBJS	+= clock.o power.o soc.o system.o pinmux.o

修改为如下内容,然后保存退出

COBJS	+= clock.o power.o soc.o system.o pinmux.o movi.o

修改板级文件

$ vi  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 
}

board_mmc_init函数中的内容修改为(之前的内容删除即可)如下内容

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);

	/* switch mmc to normal paritition */
	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

5.2 添加EMMC命令

将资料中“移植相关文件”下的cmd_movi.ccmd_mmc.ccmd_mmc_fdisk.c拷贝到uboot 源码的common/目录下
因为添加的新文件也要编译,所以对应的Makefile也要修改

$ vi  common/Makefile

COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o

后添加如下内容,然后保存退出

COBJS-$(CONFIG_CMD_MMC) += cmd_mmc_fdisk.o
COBJS-$(CONFIG_CMD_MOVINAND) += cmd_movi.o

将资料中“移植相关文件”下的mmc.hmovi.hs5p_mshc.h拷贝到uboot源码的include/ 目录下

将资料中“移植相关文件”下的mmc.cs5p_mshc.c拷贝到uboot源码的drivers/mmc/ 目录下

因为添加的新文件也要编译,所以对应的Makefile也要修改

$ vi  drivers/mmc/Makefile 

COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o

后添加如下内容,然后保存退出

COBJS-$(CONFIG_S5P_MSHC) += s5p_mshc.o

5.3 修改EMMC配置代码

$ vi  include/configs/fs4412.h

在文件的末尾

#endif	/* __CONFIG_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...)
#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

5.4编译与测试uboot

通过脚本编译uboot源码

$ ./build.sh

参照之前的实验将生成的u-boot-fs4412.bin烧写到SD卡中,开发板选择SD卡启动, 然后上电查看现象;若显示EMMC的相关信息则表示EMMC移植成功

六 电源管理移植

因为uboot源码中对电源管理芯片的配置与我们的板子不匹配,后续有可能会导致内核 启动卡死,这里还需要对电源管理芯片相关的代码进行修改和配置

6.1 修改电源管理相关代码

将资料中“移植相关文件”下的pmic_s5m8767.c拷贝到uboot源码的drivers/power/pmic/ 目录下

因为添加的新文件也要编译,所以对应的Makefile也要修改

$ vi  drivers/power/pmic/Makefile

COBJS-$(CONFIG_POWER_MAX77686) += pmic_max77686.o

后添加如下内容,然后保存退出

COBJS-$(CONFIG_POWER_S5M8767) += pmic_s5m8767.o

将添加的函数在头文件中声明

$ vi  include/power/pmic.h

int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on);

后添加如下内容,然后保存退出

void pmic_s5m8767_init(void);

修改配置文件

$ vi  include/configs/fs4412.h

在文件末尾

#endif	/* __CONFIG_H */

前添加如下内容,然后保存退出

#define CONFIG_POWER_S5M8767

修改板级文件

$ vi  board/samsung/fs4412/fs4412.c

board_init函数中

#ifdef CONFIG_DRIVER_DM9000
	dm9000aep_pre_init();
#endif

后添加如下内容,然后保存退出

#ifdef CONFIG_POWER_S5M8767
	pmic_s5m8767_init();
#endif

注释原有的代码

$ vi  drivers/power/Makefile

COBJS-$(CONFIG_POWER) += power_core.o

修改为(即注释掉)

#COBJS-$(CONFIG_POWER) += power_core.o

修改架构文件

$ vi  arch/arm/cpu/armv7/s5p-common/cpu_info.c

#include <asm/arch/clk.h>

后添加如下内容,然后保存退出

#include <power/pmic.h>

6.2 编译与测试uboot

通过脚本编译uboot源码

$ ./build.sh

参照之前的实验将生成的u-boot-fs4412.bin烧写到SD卡中,开发板选择SD卡启动,然后上电查看现象
至此,uboot移植完成

(B) Linux内核移植

一 Linux源码下载(linux-3.14.tar.xz)

https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/

拷贝内核源码包到 ubuntu 的家目录下,解压并进入其顶层目录

$ tar xvf linux-3.14.tar.xz
$ cd linux-3.14

二 平台配置

1. 平台配置

1.1 指定编译器

源码并不知道我们的处理器架构及交叉编译工具是什么,我们自己在 Makefile 中指定

$ vi Makefile

ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)

修改为以下内容(注意后边不要有多余空格),然后保存退出

ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi-
1.2 指定使用的处理器
$ make exynos_defconfig

显示如下信息表示配置成功
在这里插入图片描述

2. uart配置

2.1 配置工具
$ make menuconfig

若出现图形库错误,执行如下命令安装,然后重新执行 make menuconfig 即可

$ sudo apt-get install libncurses5-dev
2.2 修改输出串口

将‘System Type’菜单下的‘S3C UART…’修改为 2(即使用 UART2)

System Type --->
	(2) S3C UART to use for low-level messages

设置完成后通过方向键选择‘Save’保存即可,然后选择‘Exit’退出该配置界面

三 网卡驱动移植

1. 选配网卡

1、 在内核源码的顶层目录下执行如下命令,修改内核配置

$ make menuconfig

给内核选配DM9000网卡驱动,然后选择“Save”保存

Device Drivers --->
	[*] Network device support --->
		[*] Ethernet driver support --->
			<*> DM9000 support

2. 配置NFS

因为内核要使用 NFS 去挂载根文件系统,而 NFS 是基于 TCP 协议实现的,所以这里需要选配 TCP 相关的网络协议(部分功能默认已经选配),然后选择“Save”保存

[*] Networking support --->
	Networking options --->
		<*> Packet socket
		<*> Unix domain sockets
		[*] TCP/IP networking
		[*] IP: kernel level autoconfiguration

因为内核要使用 NFS 去挂载根文件系统,所以需要给内核选配 NFS 客户端及相关功能

File systems --->
	[*] Network File Systems --->
		<*> NFS client support
		<*> NFS client support for NFS version 3 (NEW)
		[*] NFS client support for the NFSv3 ACL protocol extension
		[*] Root file system on NFS

设置完成后通过方向键选择‘Save’保存即可,然后选择‘Exit’退出该配置界面

3. 编译内核

$ make uImage

第一次在 ubuntu 上编译 Linux 内核会提示缺少一个mkimage 命令,该命令可在 uboot 源码中 u-boot-2013.01/tools/目录下获取(必须是编译后的 uboot),将该命令拷贝到 ubuntu 的/usr/bin 目录下即可正确编译内核

$ sudo cp u-boot-2013.01/tools/mkimage /usr/bin/

给该命令添加可执行权限

$ sudo chmod 777 /usr/bin/mkimage

完成后回到内核的顶层目录下重新编译内核即可

( C ) 设备树移植

内核源码中并没有 fs4412 平台的设备树文件,这里我们从源码支持的平台中找一个硬件与我们最类似的,在其基础上进行修改

一 平台配置

这里我参考的是 samsung 公司的 origen拷贝 origen 的设备树并将其重命名

$ cp arch/arm/boot/dts/exynos4412-origen.dts arch/arm/boot/dts/exynos4412-fs4412.dts

因为添加的设备树文件也要编译,所以对应的 Makefile 也要修改

$ vi arch/arm/boot/dts/Makefile

exynos4412-origen.dtb \

后添加如下内容,然后保存退出

exynos4412-fs4412.dtb \

回到源码的顶层目录下编译设备树

$ make dtbs

二 修改配置

1 修改网卡配置

在设备树中添加网卡的硬件信息

$ vi arch/arm/boot/dts/exynos4412-fs4412.dts

在文件的末尾,最后一个花括号前添加如下内容(即要写在根节点之内)

srom-cs1@5000000 {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	reg = <0x5000000 0x1000000>;
	ranges;
	
	ethernet@5000000 {
		compatible = "davicom,dm9000";
		reg = <0x5000000 0x2 0x5000004 0x2>;
		interrupt-parent = <&gpx0>;
		interrupts = <6 4>;
		davicom,no-eeprom;
		mac-address = [00 0a 2d a6 55 a2];
	};
};

2 修改时钟配置

忽略无用的时钟
$ vi drivers/clk/clk.c

static bool clk_ignore_unused;

修改为以下内容,然后保存退出

static bool clk_ignore_unused=true;

3 修改EMMC相关配置

$ vi drivers/mmc/core/mmc.c

if (card->ext_csd.rev > 7) {
	pr_err("%s: unrecognised EXT_CSD revision %d\n",mmc_hostname(card->host), card->ext_csd.rev);
	err = -EINVAL;
	goto out;
}

修改为以下内容,然后保存退出

#if 0
	if (card->ext_csd.rev > 7) {
#else
	if (card->ext_csd.rev > 8) {
#endif
	pr_err("%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev);
	err = -EINVAL;
	goto out;
}

三 编译与测试

1 编译内核和设备树

$ make uImage
$ make dtbs

2 测试内核和设备树

将编译生成的内核和设备树拷贝到 tftp 的工作目录

$ sudo cp arch/arm/boot/uImage /tftpboot
$ sudo cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
$ sudo chmod 777 /tftpboot/*

重启 tftp 和 nfs 服务器

$ sudo service tftpd-hpa restart
$ sudo service nfs-kernel-server restart

重启开发板查看现象,如图所示,此时 Linux 内核已经能通过 NFS 去挂载根文件系统
在终端下执行‘ls’命令我们就能看到根文件系统中的内容

( D ) 根文件系统移植

一 busybox工具

在 busybox 官网下载 busybox 源码(这里我们下载 busybox-1.22.1.tar.bz2)
https://busybox.net/downloads/
拷贝 busybox 源码包到 ubuntu 的家目录下,解压并进入其顶层目录

$ tar xvf busybox-1.22.1.tar.bz2
$ cd busybox-1.22.1/

二 配置根文件系统

1 进入 busybox 配置界面

与 Linux 内核配置方法一样

$ make menuconfig

在这里插入图片描述

2 配置busybox

参考如下信息配置 busybox

Busybox Settings --->
	Build Options --->
		[*] Build BusyBox as a static binary (no shared libs)
		[ ] Build with Large File Support (for accessing files > 2 GB)
		(arm-none-linux-gnueabi-) Cross Compiler prefix

配置完成后通过方向键选择‘Exit’退出,并保存配置信息

3 编译与安装busybox

编译busybox

$ make

编译完成后在源码的顶层目录下会生成 busybox 文件
安装 busybox

$ make install

安装完成后在源码的顶层目录下会生成_install目录

4 移植根文件

4.1 查看文件

进入到安装目录下查看生成的文件

$ cd _install/
$ ls

如下图所示,在安装目录下生成了根文件系统中所需的 shell 命令文件
在这里插入图片描述

4.2 拷贝库文件

将交叉编译工具链中的库文件拷贝到_install 目录下

$ cp /home/linux/Linux_4412/toolchain/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/ . -a

这样在安装目录下就有了根文件系统中所需的库文件

4.3 删除库文件中的静态库
$ sudo rm lib/*.a

删除共享库中的符号表(需要在 root 用户下操作)

$ du -mh lib
$ sudo su
$ /home/linux/Linux_4412/toolchain/gcc-4.6.4/bin/arm-none-linux-gnueabi-strip lib/*
$ exit
4.4 拷贝etc目录

将资料中“移植相关文件”下的etc目录(配置文件)拷贝到当前目录下

4.5 给 etc/init.d/下的 rcS 脚本添加可执行权限
$ chmod +x etc/init.d/rcS
4.6 创建其他目录
$ mkdir dev mnt proc root sys tmp var

如下图所示,至此我们就构建好了自己的根文件系统

4.7 拷贝根文件系统

删除原来的根文件系统

$ sudo rm -rf /opt/4412/rootfs/*

将自己制作的根文件系统拷贝到 NFS 的工作目录下测试

$ sudo cp -rf ./* /opt/4412/rootfs
  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值