转载至https://blog.csdn.net/u014213012/article/details/51005283/?ticket=ST-80377-euHpECUqgclaJtULJcS7-passport.csdn.net
基于S3c2416 http://www.industech.com.cn
(uboot-1.3.4)
一:明白uboot怎么到sd卡的原理概述:
1:首先明白开发板从sd卡的什么部分读取引导安装程序-原理类似:
(1)BL0:是指S5PV210的iROM中固化的启动代码
作用:初始化系统时钟,设置看门狗,初始化堆和栈,加载BL1
(2)BL1:是批在iRAM自动从外扩存储器(nand/sd/usb)中拷贝的uboot.bin二进制文件的头最大16K代码
作用:初始化RAM,关闭Cache,设置栈,加载BL2
(3)BL2:是指在代码重定向后在内存中执行的uboot的完整代码
作用:初始化其它外设,加载OS内核
(4)三者之间的关系:(Interal ROM固化代码)BL0将BL1(bootloader的前16KB–BL1)加载到iRAM;BL1然后在iRAM中运行将BL2(剩下的bootloader)加载到SDRAM;BL2加载内核,把OS在SDRAM中运行起来,最终OS是运行在SDRAM(内存)中的。
-------------------------------针对S3c2416uboot-------------------
2.S3c2416内嵌IROM(BL0)读取sd卡的后16扇区(8k)的代码到IRAM(BL1),BL1读取256k(512扇区)的uboot到SDRAM中,从而启动u-boot-movi.bin引导程序
BootLoader一般分为两个阶段启动:第一阶段使用汇编来实现,它完成一些依赖于CPU体系结构的初始化,并调节器用第二阶段代码;第二阶段通常用C语言来实现。
第一阶段:
硬件设备初始化;(board/samsung/smdk2416/lowlevel_init.S,包括点亮测试灯,关闭看门狗、关闭main和sub中的中断、初始化系统时钟、初始化串口、初始化NandFlash,初始化MMU)为加载Bootloader的第二阶段代码准备RAM空间; 复制Bootloader 的第二阶段代码到RAM空间中;(在汇编start.S 调用 void movi_bl2_copy(void))设置好栈; 跳转到第二阶段代码的C入口点。(在/cpu/s3c24xx/start.S中,通过ldr pc, _start_armboot调用lib_arm/board.c中的void start_armboot (void)进入第二阶段)
第二阶段:
初始化本阶段要使用到的硬件设备;检测系统内存映射(memolry map);将内核映象和根文件系统映象从Flash上读到RAM空间中;为内核设置启动参数;
3.sd卡的结构图
MicroSD卡系统镜像布局
名字 起始地址 用途
mbr 0 MicroSD卡镜像的第一个启动分区
gpt 0x200 gtb分区表
environment 0x5000 uboot环境变量
bootloader 0x200200 第一个启动阶段boottraps (bootloader.bin)
uboot 0x300000 uboot启动加载程序(u-boot-dtb.img)
misc 0x800000 fat分区,包括kernel、initramfs、kernel配置文件、uEnv.txt等等(misc.img)
rootfs 0x3800000 文件系统(rootfs.img)
二:配置编译uboot1.3.4
1.修改一、SD起动首先要修改/include/configs/smdk2416.h 头文件:在365行左右,按如下修改:
//#define CONFIG_BOOT_NAND
#define CONFIG_BOOT_MOVINAND
说明:
CONFIG_BOOT_NANA是nandFlash启动方式,在此处要注释掉,因为我们要从SD卡启动,相应的IG_BOOT_MOVINAND项要打开。
2.然后回到uboot根目录,(清除->配置(参照Makefile)-编译)
3.sudo make distclean; make smdk2416_config;make all
4.编译生成u-boot.bin,因为BL0读取的是后8K可以我们需要对u-boot.bin进行分割(256K+8K)使用shell脚本
#!/bin/bash //格式
#
# This script will create a u-boot binary for movinand/mmc boot //注释
#
# padding to 512k the u-boot.bin
rm -f u-boot-movi.bin
cat u-boot.bin >> u-boot-2x.bin //拷贝两份u-boot.bin因为u-boot.bin(220k)
cat u-boot.bin >> u-boot-2x.bin
#cat u-boot.bin >> u-boot-2x.bin
split -d -a 1 -b 256k u-boot-2x.bin u-boot-512k.bin //分割大小256k,-d(数字作为后缀),(-a,length)后缀的长度
# spiliting u-boot for BL1 (8kb)
split -d -a 2 -b 8k u-boot.bin u-boot-8k.bin//同理
# creating empty env space (16kb)
dd if=/dev/zero of=empty.env bs=16384 count=1 2> /dev/null
# merging the bl1 and env with padded 512k binary
#cat empty.env >> u-boot-512k.bin0
cat u-boot-8k.bin00 >> u-boot-512k.bin0 8k(引导)
cp u-boot-8k.bin00 bootstrap.bin
# renaming and change mode
mv u-boot-512k.bin0 u-boot-movi.bin
chmod 777 u-boot-movi.bin
# removing temp files
rm -f u-boot-8k*
rm -f u-boot-512k*
rm -f u-boot-2x.bin
rm -f empty.env
得到u-boot-movi.bin(可以查看 cpu/s3c24xx/movi.c)推荐工具ctags
5.补充使用Ctags (参考)
http://baike.baidu.com/link?url=eI_AdxBmPIIN11KM2iIEVWUn1UfAYsvh157KUBMY_RjSJzwGjAyxL0hZw7QFIWmdfKNSc0boCG-9pqzWm-fhAq
5.1安装:安装到ctags官网,下载源码,解压后
$ ./configure
$ make
$ sudo make install
如果你使用的是Ubuntu系统(Debian),那么可以使用如下命令直接安装:sudo apt-get install ctags
5.2生成索引文件
在源码目录下执行
KaTeX parse error: Expected 'EOF', got '#' at position 130: …s文件中包括这些对象的列表:用#̲define定义的宏枚举型变量…ctags –R * ($为Linux系统Shell提示符,这个命令上面已经有所介绍)–第一步就需要做的
2. $ vi –t tag (请把tag替换为您欲查找的变量或函数名)
3.:ts(ts助记字:tagslist, “:”开头的命令为VI中命令行模式命令)
4.:tp(tp助记字:tagspreview)—此命令不常用,可以不用记
5.:tn(tn助记字:tagsnext) —此命令不常用,可以不用记
6.Ctrl+ ]跳到光标所在函数或者结构体的定义处
7.Ctrl+ T返回查找或跳转
“
v
i
–
t
t
a
g
”
:
在
运
行
v
i
m
的
时
候
加
上
“
−
t
”
参
数
,
例
如
:
[
/
u
s
r
/
s
r
c
]
vi –t tag” :在运行vim的时候加上“-t”参数,例如:[/usr/src]
vi–ttag”:在运行vim的时候加上“−t”参数,例如:[/usr/src]vim -tmain这个命令将打开定义“main”(变量或函数或其它)的文件,并把光标定位到这一行。如果这个变量或函数有多处定义,
在VI命令行模式 “:ts”命令就能列出一个列表供用户选择。
“:tp”为上一个tag标记文件,
“:tn”为下一个tag标记文件。
当然,若当前tags文件中用户所查找的变量或函数名只有一个,“:tp,:tn”命令不可用。
(最方便的方法是把光标移到变量名或函数名上,然后按下“Ctrl+]”,这样就能直接跳到这个变量或函数定义的源文件中,并把光标定位到这一行。用“Ctrl+T”可以退回原来的地方。即使用户使用了N次“Ctrl+]”查找了N个变量,按N次“Ctrl+t”也能回到最初打开的文件,它会按原路返回 。
注意:运行vim的时候,必须在“tags”文件所在的目录下运行。否则,运行vim的时候还要用“:set tags=”命令设定“tags”文件的路径,这样vim才能找到“tags”文件。在完成编码时,可以手工删掉tags文件(帚把不到,灰尘不会自己跑掉_)。*
当提示找不到,可能是系统函数可以按shift+k;
三:使用dd命令烧写Linux系统到sd卡
1.我们通过u-boot-1.3.4/cpu/s3c24xx/movi.c知道
这个函数是 BL1之后跳转进入BL2的入口
void movi_bl2_copy(void)
{
#ifdef XP_TOOL //因为我们是sd卡所以编译前要注释这个XP_TOOL
CopyMovitoMem(MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);
#else
CopyMovitoMem(MOVI_LAST_BLKPOS - ((256+8)*2), ((256)2), (uint )BL2_BASE, MOVI_INIT_REQUIRED);
#endif
}
MOVI_LAST_BLKPOS:include/movi.h
#define MOVI_LAST_BLKPOS (MOVI_TOTAL_BLKCNT - (eFUSE_SIZE / MOVI_BLKSIZE))
MOVI_TOTAL_BLKCNT:扇区总数目可以在 cat /sys/class/block/size得到也可以使用 sudo fdisk -l得到,在程序中movi_total_blkcnt指向一个地址
eFUSE_SIZE :保留扇区的大小,
MOVI_BLKSIZE:一个扇区的大小(521bytes)
MOVI_BL2_POS:读取bl2在sd卡的起始位置
MOVI_BL2_BLKCNT:一次写多大
(uint )BL2_BASE, :读取BL2到sSDRAM的起始位置
2.使用dd命令(使用脚本)
1.第一步格式化SD卡并分区:
O
n
p
1
20480
1024000
n
p
2
1228800
t
1
c
a
1
w
EOF
sudo mkfs.vfat -F 32 -n “boot” ${1}1
sudo mkfs.ext2 -j -L “file” ${1}2
sudo fsck.vfat ${1}1
sudo fsck.ext2 ${1}2
#!/bin/sh //格式脚本shell
sudo umount ${1} //先卸载 ${1}代表传入脚本的第一个参数类似 ./mk_sd.sh /dev/sdb $1就是/dev/sdb (->代表sdb1 ,sdb2通配符)
sudo fdisk $1 <<EOF fdisk磁盘分配命令;命令 <<EOF 命令 EOF(命令作为参数,这里就是 fdisk /dev/sdb ,<<EOF之后的都是命令参数)可以输入sudo fdisk /dev/sdb 之后m查看命令参数
o //DOS分区
n //新建分区
p
1//分区号
20480 //起始地址
1024000//最终地址
n//
p //
2 //
1228800
t // 改变系统ID
1 //一号
c //w95系统分区
a //aboot(tags)
1
w //保存退出
EOF
sudo mkfs.vfat -F 32 -n “boot” ${1}1 //对分区进行格式化 FAT32系统 磁盘名-n /dev/sdb1
sudo mkfs.ext2 -j -L “file” ${1}2 //对分区进行EXT2格式化 -L磁盘标签file/dev/sdb2
sudo fsck.vfat ${1}1 //检查修复文件系统
sudo fsck.ext2 ${1}2 //检查修复文件系统
2.烧写(使用脚本)
#!/bin/sh //格式
if [ $2 = zImage ] // if语句 if与[]要有空格,表达式与[]之间要有空格,[]与then在同一行要有分号;且没空格
then
var_num=3200000 // 这是内核镜像在sd卡布局位置,可以根据开发板的用户手册
elif [ $2 = uramdisk ] //否则elif 文件系统
then //
var_num=3500000 //同理
elif [ $2 = “u-boot.bin” ] //
Then //
var_num=3800000 //
elif [ $2 = “u-boot-movi.bin” ] //引导程序sd卡启动的
Then //
fstr=echo $1 | cut -d \/ -f 3
// 获取shell脚本的第一个参数的后面的sdb cut -d / 检测分段符我这里的是/需要加入\转意字符,-f number 是裁取第几段
/dev/sdb 1/2/3第三段
var=
(
s
u
d
o
c
a
t
/
s
y
s
/
c
l
a
s
s
/
b
l
o
c
k
/
(sudo cat /sys/class/block/
(sudocat/sys/class/block/fstr/size) //获取上面的总扇区数$(变量)取值
var=expr $var + 0
// 字符串转化为数学型
var=expr $var - 530
//进行运算减去bootloader的大小和两个保留扇区的大小就是写入sd卡的扇区位置
var_num=$var //
else
echo "error"
exit 1
fi
sudo dd if=$2 of=
1
s
e
e
k
=
1 seek=
1seek=var_num //烧写命令 dd ,if=输入文件,of=输出设备,seek=从输出设备的多少扇区处才开始复制
sync //
~
3.dd命令:
Dd:使用dd这个linux命令可以创建一定大小文件。
linux创建文件命令:dd命令
把指定的输入文件拷贝到指定的输出文件中,并且在拷贝的过程中可以进行格式转换。语法:
CODE:[Copy to clipboard]dd 〔选项〕
QUOTE:
if =输入文件(或设备名称)。
of =输出文件(或设备名称)。
ibs = bytes 一次读取bytes字节,即读入缓冲区的字节数。
skip = blocks 跳过读入缓冲区开头的ibsblocks块。
obs = bytes 一次写入bytes字节,即写 入缓冲区的字节数。
bs = bytes 同时设置读/写缓冲区的字节数(等于设置obs和obs)。
cbs = bytes 一次转换bytes字节。
count = blocks 只拷贝输入的blocks块。
conv = ASCII 把EBCDIC码转换为ASCII码。
四:插入sd卡到s3c2416开发板