系统移植第一天
[总体概述]
[1] BootLoader
1. 初始化硬件(启动操作系统需要用到的硬件)
2. 启动操作系统(内核)
[2] Kernel
裸机程序,管理整个计算机上的所有软件和硬件
文件管理
进程(任务)管理
内存管理
输入输出管理
网络管理
[3] 文件系统
装载了所有的应用程序,和整个计算机的数据,其实就是对数据的分类管理
[4] 图形系统(GUI)类库
友好的用户界面,和多媒体服务
[环境]
[1] 编译环境和运行环境不一样
CPU架构不一样
(PC)机器不是同一台, 运行在另一台不一样的设备
[1] 编译(gcc)
gcc hello.c -o hello.i -E 预处理
gcc hello.i -o hello.s -S 编译
gcc hello.s -o hello.o -c 汇编
gcc hello.o -o hello 链接
[2] 工具链(addr2line)
根据内存地址找到对应源代码的位置
gcc hello.c -o hello -g 取得带调试信息的一个ELF可执行程序
nm hello | grep main 在符号表中查找某个函数或静态变量的地址
addr2line 0x804840C(地址) -e hello(带调试参数的可执行程序) -f(对应源代码在哪个函数里面)
[3] 静态库制作
ar -rv hello.a hello.o(合并多个.o文件)
[4] 格式转换
objcopy --gap-fill=0xff(指定填充数据) -O binary(目标文件格式) hello(输入文件) hello.bin(输出文件) 转ELF格式的文件为Binary格式
[5] 反汇编
objdump -d hello(可执行文件) > hello.dis
[6] 阅读elf文件头
readelf -h hello 查看大小端、是否是elf格式的文件、可执行程序运行的操作系统
[7] 查看可执行程序需要的动态库
readelf -d hello
[8] 查看文件各段大小
size -A hello 详细 (sysv打印出可执行程序中各个段的大小及总大小)
size -B hello 简要(BSD)
[9] 查看文件中的字符串
strings hello 打印可见的C语言字符串
[10] 去掉文件的符号表
file hello 查看文件格式(是否strip过) ,看到输出最后有一个not stripped的标志
strip hello 去掉elf文件中所有的符号信息,只剩下指令和指令需要的数据
file hello
[交叉编译器安装]
[1] 拷贝可执行程序到系统中
[2] 添加可执行程序的路径到PATH
注意:
1. PATH变量中,指定了相同的路径或者不同的路径下,有相同名字的程序,以路径中第一个为准
2. 实验手册中的export PATH=$PATH:/home/linux/toolchain/bin中的linux是用户名
3. /etc/bash.bashrc 所有用户登录都会执行这个脚本
~/.bashrc 本用户登录时,才会执行的脚本
sudo arm-cortex_a8-linux-gnueabi-gcc hello.c -o hello (PATH是使用的root用户的环境变量)
[环境搭建]
[1] tftp
上传和下载一个文件
[2] nfs
通过socket连接,智能的拷贝需要的文件(在nfs服务器上)到本机(客户端)
[3] samba
s5pc100启动过程(从NANDFLASH启动过程)
[1] A8复位或者s5pc100复位,首先运行iRom程序
[2] iRom中的程序会从nandflash拷贝u-boot的前16k拷贝到SRAM
[3] 跳转u-boot的前16k运行,u-boot前16k的代码负责初始化DRAM
[4] DRAM初始化完成之后,把完整的u-boot拷贝到DRAM
[5] 跳转到DRAM里面执行完整版的u-boot
[6] u-boot负责初始化核心硬件(学习启动代码时总结), 然后拷贝kernel到DRAM
[7] 跳转到kernel启动代码运行
s5pc100启动过程(从USB启动过程)
[1] A8复位或者s5pc100复位,首先运行iRom程序
[2] iRom中的程序会初始化USB接口,然后等待主机发送运行的程序(DRAM初始化程序和u-boot)
[3] 主机首先发送DRAM初始化程序(USB Installer_DDR2.bin),然后s5pc100接收这个程序,放在iram中运行初始化DRAM
[4] 主机再发送u-boot.bin,u-boot.bin(完整版的u-boot)会被s5pc100放到DRAM中运行
[5] u-boot负责初始化核心硬件(学习启动代码时总结), 然后拷贝kernel到DRAM
[6] 跳转到kernel启动代码运行
常用BootLoader:
[1] grub x86机器用的比较多,非常成熟,有脚本控制grub的运行过程
[2] u-boot 通用性比较好,工程管理和代码比较混乱
[3] vivi 三星公司开发的一款Bootloader,用于arm芯片, 友善之臂有修改一个vivi成super vivi
u-boot常用命令:
printenv 打印所有的环境变量
printenv serverip
setenv ipaddr 192.168.1.201 设置环境变量的值(仅仅保存在内存)
savenv 把环境变量的值保存到flash
md[.b|.w|.l] 20000000 显示内存中的内容(后面的参数必须在0x20000000 - 0x30000000之间,因为我们的开发板内存在0x20000000 - 0x30000000地址之间)
mm 20000000 修改内存,并且内存地址会自动增加
nm 20000000 修改内存,并且内存地址簿会自动增加
mw.b 20000000 0 1000 内存,把0x20000000-0x20001000这块内存写成0
cp 20000000 20008000 1000 拷贝内存,从0x20000000 拷贝到20008000,拷贝了1000
cmp 20000000 20008000 1000 比较内存,0x20000000和0x20008000这两块内存
nand info 显示nandflash信息
nand device 显示nandflash的个数
nand bad 显示nandflash的坏块
实验二解释:
搭建u-boot烧写环境(nandflash中没有Bootloader只能通过USB启动),步骤如下:
1. 把JTAG线拔出
2. 接开发板的串口(com1)接到PC的串口
3. USB线连接好(开发板:miniUSB<-->PC: 机箱后的USB)
4. 开发板SW1开关4拨到4的对面,启动开发板
5. 开启开发板,PC会提示安装USB驱动(实验目录),安装成功后,会在设备管理器的通用串行总线控制器下面SEC SOC......
6. 打开串口终端
7. 运行实验目录下面的DNW,上面会提示USB OK
8. 修改配置(Configuration-->Options)
9. 设置DNW软件下,下载地址为0x2ff80000
10.下载USB Installer_DDR2(初始化内存)到开发板(USB Port-->Transmit-->transmit)
11.下载u-boot.bin(实验目录下), 下完需要很快切换到串口终端敲任意键
S5PC100的Nand Flash地址分布:
[1] 烧写u-boot.bin
1. 拷贝u-boot.bin到/tftpboot(虚拟机下)
2. 修改本机ip,命令如下:
printenv ipaddr(u-boot下的环境变量,保存本机ip地址)
setenv ipaddr 192.168.0.242(需要虚拟机的ip地址在同一网段)
saveenv 保存环境量值到flash
3. 测试网络
1. 用网线连接开发板和PC
2. 在开发板上使用ping命令ping虚拟机(虚拟机上ping开发板是不通)
ping 192.168.0.153(虚拟机的ip地址)
4. 设置tftp服务器的ip地址
setenv serverip 192.168.0.153(虚拟机的ip地址)
saveenv
5. 通过tftp下载u-boot.bin到开发板的内存
tftp 20008000(内存地址) u-boot.bin(文件名字,在虚拟机的/tftpboot)
如果出现错误:
1. 网络接通 如果一步一步下来,肯定已经通了
2. serverip ip地址是否设置正确
3. 在虚拟机重启tftp服务:
sudo service tftpd-hpa restart 在虚拟机上运行
6. 烧写u-boot.bin(在内存中)到nandflash
nand erase 0(在nandflash中的起始地址) 40000(存放u-boot的分区大小 256k)
nand write 20008000(u-boot.bin所在的内存地址) 0 40000
7. 关闭开发板,拨SW1的开关4到4那边,采用nandflash启动
8. 开启开发板,如果能正常看到u-boot提示表示成功
[2] 烧写zImage(内核)
1. 拷贝zImage到/tftpboot
2. 下载zImage到开发板内存
tftp 20008000(内存地址) zImage(要下载的文件)
3. 烧写zImage(内存中)到nandflash
nand erase 100000(在nandflash中的起始地址) 300000(存放内核的分区大小 3M)
nand write 20008000(zImage所在的内存地址) 100000 300000
[3] 烧写文件系统(rootfs.cramfs)
1. 拷贝rootfs.cramfs到/tftpboot(在虚拟机上)
2. 下载rootfs.cramfs到开发板内存
tftp 20008000(内存地址) rootfs.cramfs(要下载的文件)
3. 烧写rootfs.cramfs到nandflash
nand erase 400000(在nandflash中的起始地址) 400000(存放内核的分区大小 4M)
nand write 20008000(rootfs.cramfs所在的内存地址) 400000 400000
[4] 手动启动内核和文件系统
1. 设置内核启动参数
打印内核参数:
printenv bootargs(存放内核启动参数的环境变量)
setenv bootargs root=/dev/mtdblock2(存放文件系统的设备--nandflash第2个分区) init=/linuxrc(告诉linux系统启动的第一个程序为/linuxrc) console=ttySAC0,115200(指定控制台终端为串口,并且波特率为115200)
2. 手动启动内核
nand read 20008000(内存地址, 内核的启动地址) 100000(内核在nandflash上的位置) 300000(内核存放的分区大小) 读nandflash的内容到内存
go 20008000 启动内核
[5] 自动启动内核和文件系统
1. 设置启动命令到bootcmd环境变量
setenv bootcmd nand read 20008000 100000 300000\;go 20008000
saveenv
2. 重启开发板,让它自动启动