前言:
本文章将详细介绍在一个裸板(ARM板)上移植并配置一个linux系统,其中包含uboot引导系统的制作与移植以及liunx的制作移植。博主用的是三星Exynos4412芯片和FS4412_CoreBoard_V2核心板,具体的其他板子会有差异。
相关资料链接:
链接:https://pan.baidu.com/s/1uv_N-8dQlZli4Bc2xfPbRg
提取码:xs66
前期准备:
由于篇幅原因,将不在详细介绍前期的一些准备工作。但是可以说一下具体有哪一些:1、需要有自己的一块板子。2、需要有一个U盘或者SD卡做一个启动盘,其中下载启动引导系统作为启动盘来提供基本的串口通讯功能。3、需要串口通讯工具(如Xshell、超级终端等)。4、还需要搭建板子和主机之间的tftp通讯(在SD卡可正常引导启动后进行),可参考:(19条消息) arm linux启动tftp服务器,ubuntu下配置TFTP服务器,用以ubuntu下烧写内核到ARM开发板..._weixin_39772352的博客-CSDN博客OK!到这一步,估计你已经准备的差不多了...^_^
一、系统引导(bootloader):
1.制作uboot.bin
到uboot.bin官网下载对板子和芯片的uboot.bin制作环境压缩包(Index of /pub/u-boot/)
修改makefile CROSS_COMPILE ?=arm-linux-(设置编译器为arm架构的)
用make distclean 打扫之前的编译环境
在borads.cfg找到对应板子,如qong,用make qong_config 制作配置(可以来两次)
make开始编译 制作uboot.bin
2.移动uboot.bin到板子
(uboot.bin 之前要链接 bl1和bl2 (cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u- boot.bin tzsw_SMDK4412_SCP_2GB.bin > u.bin))
复制到 tptf共享文件夹 cp u.bin /home/xs/tftp/(该步骤在网盘文件中有脚本可以执行)
启动板子 输入 tftp 41000000 u.bin
保存 movi write u-boot 41000000
异常处理:
1、灯闪烁:某种中断导致,直接切断电源模块的接收中断功能。
在arch->arm->cpu->对应cpu下的start.s set the cpu to SVC32 mode后加
/*设置ONO*/
ldr r1,=0x11000c00
ldr r2,[r1]
bic r2,r2,#0x00000F00
orr r2,r2,#0x00000100
str r2,[r1]
ldr r1,=0x11000c04
ldr r2,[r1]
bic r2,r2,#0x00000004
orr r2,r2,#0x00000004
str r2,[r1]
/*ONO end*/
2、串口通讯不成功:参数设置不对,没有确定输入时钟频率,故波特率不确定。
在对应板子的lowlevel_init.s中:
在 1:
/* for UART */
bl uart_asm_init
/*屏蔽这一行*/
@ bl tzpc_init
在uart_asm_init:
/*xs 修改*/
ldr r0, =EXYNOS4_CLOCK_BASE
/* UART[0:4] */
ldr r1, =CLK_SRC_PERIL0_VAL
ldr r2, =CLK_SRC_PERIL0_OFFSET
str r1, [r0, r2]
/* CLK_DIV_PERIL0: UART Clock Divisors */
ldr r1, =CLK_DIV_PERIL0_VAL
ldr r2, =CLK_DIV_PERIL0_OFFSET
str r1, [r0, r2]
/*uart时钟修改结束*/
备注:如果打算使用 tftp传输文件 那么就需要将网络功能打开 具体步骤如下:
1、增加命令:
fs4412.h中修改(打开宏开关) 板子名的.h文件
{
#define CONFIG_CMD_PING
#define CONFIG_CMD_NET
}
2、增加网络设备初始化
origen.c中增加
{
#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
return dm9000_initialize(bis);
}
#endif
}
fs4412.h中增加
{
#ifdef CONFIG_CMD_NET
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x05000000 /*DM9000基地址*/
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#define CONFIG_ETHADDR 11:22:33:44:55:66 /*MAC */
#define CONFIG_IPADDR 192.168.12.251 /*板子ip*/
#define CONFIG_SERVERIP 192.168.12.147 /*主机ip*/
#define CONFIG_GATEWAYIP 192.168.12.1 /*网段 */
#define CONFIG_NETMASK 255.255.255.0 /*掩码 */
#endif
}
3、增加SROM设置
在fs4412/origen.c 增加:
在board_init中增加:
{
#ifdef CONFIG_DRIVER_DM9000
dm9000aep_pre_init();
#endif
}
在fs4412/origen.c 增加:
{
#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];
};
/*
* 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
}
3.启动uboot
设置uboot启动参数(注意IP地址和其他参数的更改 我这里192.168.1.12是板子ip)
set bootargs root=/dev/ram rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.1.12
save
拨动拨码开关 上电 启动
二、内核移植(kernel)
uImage编译:
到linux官网下载制作kernel的压缩包(https://www.kernel.org/)
tar -xvf 压缩包名
修改makefile CROSS_COMPILE ?=arm-linux-(设置编译器为arm架构的)
看芯片是否支持,arch/arm(架构名)/configs/ -------->exynos_defconfig(三星的一个芯片配置文件)
如果不支持就换高版本的linux,或者找厂家
make exynos_defconfig(对应配置文件--可修改) :注意 这是对配置文件的加载写入,不过一般都不采取这种方式 ,一般用下一行方法
make menuconfig 可视化窗口配置配置文件 需要啥就选择(开DM9000的配置 在Device Drivers → Network device support → Ethernet driver support→ DM9000下)
上面开了DM9000配置文件后 需要在设备树源码文件(arch/arm/boot/dts/对应板子.dts)下挂载:
在 .dts文件下 增加:
#include <dt-bindings/interrupt-controller/irq.h>
在结尾增加:(注意 包含在大框架内 也就是最后还要有一个花括号)
/*新增网络*/
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 IRQ_TYPE_LEVEL_HIGH>;
davicom,no-eeprom;
};
};
tb编译:
确认板子是否匹配 arch/arm/boot/dts/ 没有 就找芯片相同的借鉴
修改Makefile 增加 你要编译的板子 .dtb 没有就借鉴 有就不管了
make dtbs 生成 .dtb文件
将这个文件 和uImage文件一起拷贝到tftp文件夹
2、根文件系统(rootfs)
网络文件系统 nfs:
ubuntu主机端:
安装:sudo apt-get install nfs-kernel-server
准备目录:在家目录下的任意目录创建一个rootfs文件夹 可以是空的(用于放我们自己的根文件系统) 或者是解 压的 rootfs.tgz
配置nfs:
sudo vi etc/exports
加一行 rootfs文件夹的路径 * (rw,sync,no_subtree_check,no_root_squash)
重启生效:
sudo /etc/init.d/nfs-kernel-server restart
板子客户端:
需要重新生成一个uImage文件;
→ Networking support → Networking options→ IP: kernel level autoconfiguration :先把自动IP打开
make menuconfig 找到nfs :
File systems → Network File Systems → NFS client support 和 Root file system on NFS(没开自动IP没有该选项) 选择需要
板子 uboot 需要更改为:
set bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000
set bootargs root=/dev/nfs nfsroot=192.168.1.11(你的主机址):/home/hqyj/hq/xs/sys/rootfs(你的rootfs路径),v3 rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.1.12(板子的地址)
save
己制作一个rootfs:
下载busybox压缩包(https://busybox.net/)
在家目录下的任意目录解压
在解压的目录下 make menuconfig 找到:Busybox Settings → Build Options → Build BusyBox as a static binary和(arm-linux-) Cross Compiler prefix (括号内是要填的交叉编译环境)
make 或者 make -j8
make install (你自己制作的rootfs就在 _install下产生了)
在_install 目录下创建 /proc /tmp /sys /dev 文件夹
然后 就需要lib文件(复制到_install下) 一般移植对应框架的 gun 下的lib 用 echo $PATH查找路径为/home/hqyj/Downloads/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi
最后 需要etc文件(复制到_install下) 这个包含启动和配置文件 inittab 文件是启动时调用的文件(可以在这里添加自启动软件) profile 是可以更改一些用户信息的
最后将自己_install下的所有文件移动到自己的rootfs 下 就可以了
rootfs相关文件:
rcS文件
#!/bin/sh
#This is the first script called by init process
/bin/mount -a ----》关联文件系统
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
inittab文件
#this is run first except when booting in single-user mode.
::sysinit:/etc/init.d/rcS
# /bin/sh invocations on selected ttys
# Start an "askfirst" shell on the console (whatever that may be)
::respawn:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
profile文件
#!/bin/sh
export HOSTNAME=xs
export USER=root
export HOME=root
#export PS1="\[\u@\h \W\]\$ "
#cd root
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH