第一天:
嵌入式系统
带微处理器的专用软硬件系统
内核子系统
内存管理
进程管理
网络协议
文件系统
设备管理
源码来源:
1、原厂 (主芯片厂家) SDK
2、官网下载
系统移植的要点:
1、搭建交叉开发环境
2、bootloader 移植
3、kernel 移植
4、根文件系统 制作
交叉编译
体系架构 CPU主频不同 外设不同
GCC的编译步骤
1、预处理
2、编译
3、汇编
4、链接
解压:
tar -xvf 1.tar
单板:exynos fs4412
交叉工具链: arm-none-linux-gnueabi-
addr2line:
把地址转成文件名和行号 编译添加-g选项
addr2line 地址 -e 文件名 -f
objdump:
反汇编 功能也是调试时使用
strip: 丢弃目标文件中全部或者特定符号,减小文件体积
注:ko是不能使用strip的
交叉工具链安装步骤:
1、mkdir toolchain (/home/linux/toolchain)
2、tar -xvf gcc-4.6.4.tar.xz
3、/etc/bash.bashrc
4、export PATH=$PATH:/home/linux/toolchain/gcc-4.6.4/bin
5、source /etc/bash.bashrc
安装tftp服务
1、检测是否安装了tftp服务
dpkg -s tftpd-hpa
2、如果未安装,需要
sudo apt-get install tftpd-hpa tftp-hpa
3、修改配置文件 /etc/default/tftpd-hpa
# sudo vi /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-c -s -l"
4、sudo service tftpd-hpa restart
安装NFS服务
1、检测是否安装了NFS服务
dpkg -s nfs-kernel-server
2、如果未安装,需要
sudo apt-get install nfs-kernel-server
3、修改配置文件 /etc/exports
/source/rootfs *(rw,sync,no_root_squash,no_subtree_check)
nfs目录 *表示任意IP可以访问
4、sudo service nfs-kernel-server restart
showmount -e 显示当前配置的NFS路径
5、做测试
mount -t nfs 192.168.1.122:/source/rootfs /mnt
umount /mnt -f
第二天:
bootloader定义
硬件启动的引导程序
系统移植 首先移植的就是bootloader
bootloader操作模式
自启动模式
交互模式
bootloader基本功能
初始化硬件
自搬移
执行用户命令
加载内核
bootloader的第一阶段
初始化基本硬件(CPU DDR 串口 关看门狗)
自搬移
清BSS段和堆栈
bootloader的第二阶段
初始化本阶段的硬件(flash 网口)
读取环境变量
如果是自启动模式 直接加载内核
如果是交互模式 接收用户命令
bss段:存一些未初始化的变量 或者 全局变量
命令分类
环境设置、数据传输、存储器访问、加载运行
环境设置
printenv 打印环境变量
setenv 设置环境变量
saveenv 保存环境变量、
在设置环境变量时,需要进行删除,setenv 环境变量名称 空格; saveenv
ipaddr 板端ip地址
serverip 服务器端ip地址(虚拟机地址)
ethaddr MAC地址
在使用tftp命令之前 需要开启tftpd-hpa这个服务
tftp 命令下载文件到内存 (/tftpboot)
md 内存显示
md 0x41000000 默认显示 256
md 0x41000000 1 只显示1个字节内容
?/ help 显示所有命令
操作flash
NOR flash
protect on all 加写保护
protect off all 解写保护
erase all 擦除所有的
spi read/write
NAND
nand info 显示可用的NAND信息
nand device 0 显示或设备当前的NAND设备
nand bad 显示坏块信息
nand read/write 地址
nand read addr off size
nand write addr off size
nand erase [clean] [off size]
nand lock [status]
nand unlock [off size]
EMMC
movi read u-boot/kernel addr
movi write u-boot/kernel addr
bootargs
boot启动参数 是唯一传给内核的一组参数
bootcmd
启动内核
boot源码
配置文件---include/configs
设备树 3.10以后的内核版本 dtb
boot 编译
make xxx_config //fs4412_config
make
清除
make distclean
make mrproper
SD卡烧写
切换bash sh脚本
dpkg-reconfigure dash
boot启动流程
入口文件 start.S (arch/arm/cpu/armv7)
进入SVC模式
关MMU L1 cache
b lowlevel_init@ go setup pll,mux,memory
-----board/samsung/fs4412
关看门狗
串口初始化
main_loop()
第三天:
1、通过网络方式引导内核 根文件系统
setenv bootcmd 'tftp 41000000 uImage;tftp 42000000 fs4412.dtb;bootm 41000000 - 42000000'
其中bootm后面可以跟三个参数,第一个参数为内核的内存地址,
第二个参数是根文件系统的内存地址,
第三个参数是设备树的内存地址
其中后两个参数可省略
setenv bootargs 'root=/dev/nfs nfsroot=192.168.1.122:/source/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.1.233'
其中root表示根文件系统的启动方式,
nfsroot指定服务器IP及NFS服务目录
rw 可读可写
console是终端 此时我们设置的是串口2,波特率为115200
init代表着第一个运行的应用程序linuxrc 最后一个是板端IP地址
2、烧写到EMMC
tftp 41000000 uImage;movi write kernel 41000000 //烧写内核到EMMC
tftp 41000000 exynos4412-fs4412.dtb;movi write dtb 41000000 //烧写设备树到EMMC
tftp 41000000 ramdisk.img;movi write rootfs 41000000 300000 //烧写根文件系统到EMMC
setenv bootcmd ‘movi read kernel 41000000;movi read dtb 42000000;movi read rootfs 43000000 300000;bootm 41000000 43000000 42000000’
其中movi write/read 后参数 可以是u-boot/kernel/rootfs/dtb
3、UBOOT移植思想
1.架构选择 单板确定
arm exynos fs4412 参考 origen
2.交叉编译
uboot源码目录
交叉编译工具链
Makefile
ARCH = arm
CROSS_COMPILE = arm-none-linux-gnueabi-
3.boot的编译步骤
make xx_config
make
4.编译生成的镜像如何测试
内存地址如何确定?
System.map 查看boot的一个运行地址
0x43e00000 _start
tftp 0x43e00000 u-boot.bin
go 0x43e00000
5.如果串口无输出 串口驱动 或者使用点灯法来测试运行到哪里
6.网卡及外设是否正常工作 移植其它硬件设备的驱动
第四天:
一、kernel 子系统
进程管理 ------- ipc
内存管理 ------- mm
设备管理 ------- drivers
文件系统 ------- fs
网络协议 ------- net
二、内核的配置文件 arch/arm/configs
exynos fs4412------exynos_defconfig
三、内核的配置和编译
cp arch/arm/configs/exynos_defconfig .config
make menuconfig ---> .config
make uImage
四、make menuconfig
-----> Genernal setup
CROSS_COMPILE --->交叉编译工具链
kernel compression mode
----> 内核压缩模式
GZIP
LZMA
XZ ----> SQUANSHFS
<> 有三种状态: * 表示编译进内核
M 表示编译成模块
空表示不编译进内核
在.config 中 =y 表示编译进内核
=m 表示编译成模块
选配: 1、把配置文件拷贝到内核根目录下的.config
cp arch/arm/configs/exynos_defconfig .config
2、make menuconfig
<LOAD> --->功能是将.config导入
<SAVE> ---->保存
Kconfig
语法:
1、menu "Character devices"
一个名叫"Character devices"菜单
endmenu
2、config FS4412_LED
一个配置项
3、
tristate "FS4412 LED Driver Support"
tristate 三态
选择编译进内核
编译成模块
不编译
bool
两种模式
4、help
support led device on FS4412 develop board
帮助文档
5、depends on ARCH_EXYNOS4
依赖关系
内核编译:
make uImage
出现错误提示 缺少mkimage 需要将boot/tools/mkimage拷贝到/usr/bin/下面
编译生成文件: uImage 是在 arch/arm/boot
Image:是未压缩的内核映像文件
zImage: 经过Gzip压缩的内核映像文件
uImage: 在zImage的基础加了一个头部
Makefile
vmlinux 是真正的内核映像
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)
head-y := arch/arm/kernel/head$(MMUEXT).o ----> head.S
init-y := init/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
make uImage V=1 来查看入口
arm-none-linux-gnueabi-ld -EL -p --no-undefined -X --build-id -o vmlinux -T
/home/farsight/kernel/linux-3.14-fs4412/arch/arm/kernel/vmlinux.lds
arch/arm/kernel/head.o init/built-in.o --start-group usr/built-in.o
arch/arm/vfp/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o
arch/arm/common/built-in.o arch/arm/net/built-in.o arch/arm/crypto/built-in.o
arch/arm/firmware/built-in.o arch/arm/mach-exynos/built-in.o
arch/arm/plat-samsung/built-in.o kernel/built-in.o mm/built-in.o
fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o
lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o
net/built-in.o --end-group .tmp_kallsyms2.o
arch/arm/kernel/head.S
入口文件: head.S
启动流程:
1、判断处理器ID
2、解析boot参数
3、创建页表
4、内存映射转换
5、start_kernel(初始化各个硬件)
6、启动内核线程
7、执行第一个用户程序linuxrc
设备树
存放目录:arch/arm/boot/dts
编译方法: make dtbs 生成设备树文件
puts ------ 内核解压之前用
printascii ---- 终端初始化之前
printk--------- 终端初始化之后
打印级别:
//#define KERN_EMERG "<0>" /* system is unusable */
//#define KERN_ALERT "<1>” /* action must be taken immediately */
//#define KERN_CRIT "<2>" /* critical conditions */
//#define KERN_ERR "<3>" /* error conditions */
//#define KERN_WARNING "<4>" /* warning conditions */
//#define KERN_NOTICE "<5>" /* normal but significant condition */
//#define KERN_INFO "<6>" /* informational */
//#define KERN_DEBUG "<7>" /* debug-level messages
第五天:
根文件系统
1、目录结构
/dev 目录
设备分类: 字符设备 块设备 网络设备
crw-rw---- 1 root dialout 4, 86 Sep 18 05:07 ttyS22
char 字符设备
4 表示主设备号
86 表示次设备号
/bin /sbin /usr/bin /usr/sbin -----》busybox
可执行文件,工具
/lib 库文件
/etc
一些配置文件
/sys 是通过sysfs挂载生成
/proc 是通过proc挂载生成
/tmp tmpfs挂载生成 tmpfs临时文件系统 存在于内存中
/mnt 挂载目录
2、busybox
安装步骤:
make menuconfig # This creates a file called ".config"
make # This creates the "busybox" executable
make install # or make CONFIG_PREFIX=/path/from/root install
make menuconfig
在build option---->去修改交叉编译 CROSS_COMPILE
生成内容 /bin /sbin /usr/bin /usr/sbin linuxrc
/lib 来源? 在交叉编译工具链中
拷贝库文件存在软链接的情况下,需要使用-d 选项来拷贝
cp * ./rootfs -rdf
通过linuxrc是busybox的软链接,得知调用busybox的init.c
/etc/inittab 是调用的第一个脚本
inittab 内容 可从busybox源码中搜索帮助文档
格式Format for each entry: <id>:<runlevels>:<action>:<process>
id 设备id 通常会tty设备
runlevels 可忽略
action: 什么时机运行 sysinit, respawn, askfirst, wait, once,
restart, ctrlaltdel, and shutdown.
内容:
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
/etc/inittab 脚本会去调用 /etc/init.d/rcS脚本
/etc/init.d/rcS 内容是从busybox源码查找例子
具体内容:
#! /bin/sh
/bin/mount -a
echo "hello world"
其中/bin/mount -a 会去调用 fstab,在/etc目录下。