/******************************************************************/
PC 由bios 引导操作系统windows 识别C D盘 操作应用程序
嵌入式系统 由bootloader 引导Linux内核 挂接根文件系统 运行应用程序bootloader最终目的:启动内核
bootloader有很多种 用的比较多的是 u-boot
u-boot功能:
从flash中读出内核
初始化SDRAM
初始化时钟
初始化看门狗
初始化串口
为了开发方便:写flash 网卡 usb功能
启动内核
u-boot:复杂一点的单片机程序u-boot
输入help可以打印u-boot的所有命令
输入? + 命令 打印命令用法
输入menu进入菜单
输入print 打印出来环境变量
输入 set 设置环境变量
输入 save 保存
输入 grep " " 搜素内容
不同命令之间可以用;隔开
readme:关于u-boot的说明操作过程:
解压缩 打补丁 patch文件:
打补丁说明 忽略---补丁文件说明的第一个参数 -p1
-表示原来的代码
+修改后的代码 patch命令:
patch -p1 < ../u-boot-1.16_jz2440.patch 配置 make 100ask24x0_config
编译 make
分析配置过程:
#makeconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
# $1 $2 $3 $4 $5 $6 makeconfig:
$# 表示参数的个数
$( ) 定义什么
echo 打印 执行什么
: 依赖于谁
> 表示新建一个文件
>> 表示追加一个文件
ln -s asm-arm asm 建立一个asm链接文件指向asm-arm
ln -s arch-s3c24x0 asm-arm/arch 建立一个asm-arm/arch链接文件指向arch-s3c24x0
ln -s proc-armv asm-arm/proc 建立一个asm-arm/proc链接文件指向proc-armv分析编译过程:
OBJS = cpu/arm920t/start.o
...
LIBS += board/100ask24x0/lib100ask24x0.a
...
make命令的最后面就是一个连接命令Makefile分析 结论:
运行的第一个文件是 cpu/arm920t/start.S
连接地址:board/1 00ask24x0/u-boot.lds + 0x33F80000
start.S:
u-boot-1:
set svc32
关看门狗
屏蔽中断
sdram初始化
设置栈
时钟
重定位 flash => sdram
清bss段 初始化为0的变量
u-boot-2:
调用c函数 strat_armboot
flash_init();
nand_init();
环境变量:
默认的
flash上保存的
主循环mainloop();
启动内核:
s = getenv("bootcmd");
run_command(s);
u-boot界面:
readline();
run_command();
u-boot的命令实现:
命令结构体:
struct cmd_tbl_s{
name;
maxargs;
repeatable;
(*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *uasge;
#ifdef CFG_LONGHELP
char *help;
#endif
#ifdef CONFIG_AUTO_COMPLETE
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
find_cmd();
启动内核:
nand read.jffs2 0x30007FC0 kernel;
从内核中读出内核 从哪里读(kernel 分区) 放到哪里去(0x30007FC0)?
linux下的flash没有分区
bootloader env kernel root 在源码配置文件里面写死的
kernel 分区:
起始地址:0x00060000 长度:0x00200000
flash上面存的内核为Uimage 包含头部和真正的内核
头部里面有加载地址和入口地址
根据头部移动到合适的地方
启动:do_boot_linux();
uboot告诉内核一些参数
在某个地址按照某种格式保存数据 格式称为TAG
start_tag
memory_tag
commandline_tag
end_tag
跳到入口地址 启动内核 thekernel();
/******************************************************************/
从零开始写一个bootloader:最简单的bootloader编写步骤:
1,初始化硬件:关看门狗 设置时钟 设置SDRAM 初始化NAND FLASH
2, 把内核从NAND FLASH读到SDRAM
如果bootloader比较大 要重定位 把bootloader本身的代码从flash复制到链接地址
3,设置要传给内核的参数 tag
4,跳到入口地址处执行
汇编指令:
ldr:
伪指令 如果操作数比较长的时候
mov:
伪指令 传递参数
str:
存储参数
adr:
伪指令
add:
增加
cmp:
比较
bne:
跳转
bl:
相对跳转
sub:
执行减法 内核启动时 要设置串口
把bootloader的代码拷贝到SDRAM里面执行:
判断是从nor flash启动还是从nand flash 启动
nor flash的特点是0地址不能写 不能像内 存一样写
nand flash 的0地址可以写
设置参数
改进:
提高CPU主频
使用ICATCH 指令CATCH DCATCH使用的前提是开MMU
/******************************************************************/
移植一个最新的U-boot 分析启动过程:
安装最新u-boot
编译
pie 链接的时候加上pie会生成位置无关码 不管位置在哪都能正确执行
......
重定位代码:
nor flash复制到sdram里面之后 全局变量用新的地址访问
以前的程序是链接地址是0,访问全局变量,调用函数时是使"基于0地址编译得到的地址"
现在把程序复制到了SDRAM 需要修改代码 把"基于0地址编译得到的地址"改为新地址
程序里面的有些地址在链接时不能确定 要到运行时才能确定:fixabs
...... 创建单板:
cd board/samung/
cp smdk2410 smdk2410 -rf
cd ../../include/configs/
cp smdk2410.h smdk2440.h
修改boards.cfg:
仿照
smdk2410 arm arm920t - samung s3c24x0
添加
smdk2440 arm arm920t - samung s3c24x0
烧写看结果:无任何反应
修改u-boot支持时钟和SDRAM
发现不足: U-boot里面先以60MHZ的时钟计算参数来设置内存控制器但是MPLL还没有进行设置
处理措施: 把MPLL的设置放到start.S里面 取消board_early_init_f里对MPLL的设置
编译出来的u-boot非常大 可以先烧写主光盘里面的u-boot来烧写新的u-boot
usb 1 30000000 //下载新的u-boot
protect off all
erase 0 7ffff
cp.b 30000000 0 80000
乱码问题: 查看串口波特率设置 发现设置波特率函数里面没有定义CONFIG_S3C2440
#define CONFIG_S3C2440
看Makefile //NAND_CONFIG 串口正常输出
修改u-boot支持NAND启动:
上电的时候用NAND读函数把代码移动到SDRAM里面去
原来的代码在链接时加了"-pie"选项,使得u-boot里面多了"*(.rel*)", "*(.dynsym)"
使得程序非常的大,不利于程序从NAND FLASH上面启动(重定位之前的代码应该少于4K)
去掉 "pie"选项
参考毕业班第一课来修改代码,支持NAND FLASH
把init.c放入到board/Samsung/smdk2440目录 修改Makefile
修改CONFIG_SYS_TEXT_BASE为0x33f80000
修改start.S
修改board_init_f,把relocate_code去掉
修改链接脚本 把start.S init.s lowlevel.s 等文件放在前面
修改Makefile
修改u-boot支持NOR FLASH启动:
NOR FLASH就和内存一样 好多函数已经写好了
修改drivers/mtd/jedec_flash.c 加上新的型号
#define CONFIG_SYS_MAX_FLASH_SECT(128)
修改重定位时留下的BUG
修改u-boot支持DM9000启动:
设置内存控制器 时序
确定访问地址
eth_initialize
board_eth_init
cs8900_initialize
*** ERROR: 'ethaddr' not set
set ipaddr 192.168.1.17
set ethaddr 00:0c:29:4d:e4:f4
至此可以ping通开发板
启动windows上面的tftp工具
set serverip 192.16.1.3
tftp 30000000 uImage
修改u-boot支持NAND FLASH:
修改: include/configs/smdk2440.h #define CONFIG_CMD_NAND
把drivers/mtd/nand/s3c2410_nand.c 复制为 s3c2440_nand.c
分析过程:
nand_init
nand_init_chip
board_nand_init
设置nand_chip结构体,提供底层的操作函数
nand_scan
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip;
chip->cmdfunc = nand_command;
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_command() //既可以用来发命令 也可以用来发地址
chip->cmd_ctrl
s3c2440_hwcontrol
chip->cmdfunc(mtd, NAND_CMD_READTD, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
修改u-boot支持烧写yaffs映像 及 制作补丁:
烧写jffs2:
tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 5b89a8
set bootargs console=ttysacd root=/dev/mtdblock3 rootfstye=jffs2
烧写YAFFS:
tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.yaffs 30000000 260000
更新u-boot:
tftp 30000000 u-boot_new.bin; protect off all; erase 0 3ffff; cp.b 30000000 0 40000
制作补丁文件并且打补丁:
make disclean
ls
rm u-boot.lds
rm ^c
mv u-boot-2012.04.01 u-boot-2012.04.01_100ask
tar xjf u-boot-2012.04.01.tar.bz2
difff -urN u-boot-2012.04.01 u-boot-2012.04.01_100ask > u-boot-2012.04.01_100ask.patch
cd u-boot-2012.04.01/
patch -p1 << ../u-boot-2012.04.01_100ask.patch
make smdk2440_config
make
生成 u-boot.bin
u-boot之裁剪和修改默认参数:
环境参数存在flash上面 要设置一下
去掉不需要的东西