Linux系统移植笔记

时间:2022-04-29 08:49:00

第一天:

        嵌入式系统
带微处理器的专用软硬件系统


内核子系统


内存管理

进程管理

网络协议

文件系统

设备管理

源码来源:
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目录下。