17年系统移植笔记

1.BL0是封装在SOC内部一个大小为64KB的iROM里;BL1是三星公司提供的一段加密的程序,BL0将BL1加载到SOC里的SRAM上运行,目的是初始化CPU;BL2是做板子的公司提供的,它也是被加载到SRAM里去运行用来初始化板子的。其中BL0是一段已经固化在SOC上的只读程序,BL1、BL2和u-boot合起来构成我们需要移植的u-boot-fs4412.bin

2. 命令行调试工具GDB可以调试 Linux内核空间的驱动 用户空间的应用程序

3.u-boot启动第一阶段程序在u-boot-2003-01目录下:arch/arm/cpu/armv7/start.S
4.从大方面来说,u-boot的启动分成两个阶段,第一个阶段主要的职责是准备初始化的环境,主要有以下几点:
  (1)设置异常向量表(CPU跳到reset中断向量处执行)
  (2)把CPU的工作模式设置为SVC32模式(管理模式)
  (3)关闭看门狗定时器(否则在u-boot启动过程中,CPU可能因为看门狗定时器超时而不断重启)
  (4)关闭中断、cache和MMU(cache在cpu中用来存放常用的数据和指令,cache开启的情况下,cpu首先在cache中寻找需要的指令或数据,cache中没有再从RAM获取,uboot启动的时候不管cache是否初始化都不会有cpu需要的数据,uboot用来实现简单的初始化和引导操作,关闭cache优化uboot性能。)
  (5)设置栈(栈是执行C程序的必要条件,因此在进入C语言实现的初始化代码前,需要通过汇编进行栈的初始化。ARM处理器的栈指针sp默认向下生长,因此只需将sp指针指向一段低地址没有被使用的内存,即可完成栈的设置。)
  (6)清除BSS段(在调用C代码之前,还需要由u-boot将BSS段中存放的未初始化全局变量、静态变量清零)
  (7)跳转到c语言中执行(第二阶段)
5.u-boot启动第二阶段在上一段建立好C语言运行环境的基础上,进行各种外设的初始化,比如说GPIO、串口、网口。第二个任务就是加载内核的代码到内存,跳到内核代码起始位置执行。

6.在工程文件比较多的目录下找文件:find . -name  | xargs grep -i <keyword>

7. U-Boot烧写地址:
          不同目标板,对U-Boot在FLASH中存放地址要求不尽相同。事实上,这是由处理器中断复位向量来决定的,与主板硬件相关,对MPC8xx主板来讲,就是由硬件配置字(HRCW)决定的。也就是说,U-Boot烧写具体位置是由硬件决定的,而不是程序设计来选择的。程序中相应U-Boot起始地址必须与硬件所确定的硬件复位向量相吻合;如RPXlite DW板的中断复位向量设置为0x00000100。因此, U-Boot 的BIN镜像文件必须烧写到FLASH的起始位置。事实上,大多数的PPC系列的处理器中断复位向量是0x00000100和0xfff00100。这也是一般所说的高位启动和低位启动的BOOT LOADER所在位置。可通过修改U-Boot源码<目标板>.h头文件中CFG_MONITOR_BASE 和board/<目标板>/config.mk中的TEXT_BASE的设置来与硬件配置相对应。

8.串口命令:boot = run 'bootcmd'
9.make -C net/:进入到net目录下执行里面的Makefile
10.uboot源码主目录下的System.map(符号表)里第二行定义了uboot运行地址为43e00000。所以我们通过eMMC启动再通过tftp将u-boot.bin下载到43e00000运行才可以。(有个问题就是u-boot-fs4412.bin的下载地址为什么是41000000)

1.内核和用户空间的应用程序使用不同的保护地址空间。每个用户空间的进程都使用自己的虚拟地址空间,内核则占用单独的地址空间,一般情况下,应用程序无法直接访问内核空间地址。因此,应用程序想要访问内核必须通过某种特殊的方式从用户空间切换到内核空间。这个特殊的方式称为系统调用。

2.ARM Linux的系统调用实现原理是采用swi软中断从用户态usr模式陷入内核态svc模式。

3.u-boot和kernel在编译之前都需要配置,u-boot的配置命令是make fs4412_config;kernel的配置命令是make menuconfig.(kernel里配置选项特别多)

4.执行make menuconfig命令时,配置工具首先分析体系结构对应的Kconfig文件生成一个菜单界面。

5.移植内核第一步要弄Kconfig配置文件,和其他移植一样要copy一个默认的配置文件再去改,默认的配置文件在arch/arm/config里面,华清选的是exynos_defconfig拷贝到内核主目录下改为.config(这个文件名是默认的,不能改成其他的)。或者在命令行输入make ARCH=arm exynos_defconfig也可以生成 .config
     可以看到 .config 定义很多以 config 开头的宏,宏等于 y 就说明这个选项需要编译进内核,因为移植的时候有些功能不需要。在其他文件中会判断这里面的宏是不是等于 y 来决定要不要编译进内核。

     当然上面生成的 .config 是默认的,我们移植的时候肯定会要修改其中的内容,那怎么修改呢?这里有 2 种方法:

     (1) 如果你对 .config 比较熟悉的话,直接进入修改(无非是该宏是不是等于 y

     (2) 命令行输入 make menuconfig 会导出一个菜单,在菜单里修哪些选项要编进内核。第一次使用这个命令会报错 :ncurse-devel ,说缺少一个库。需要下载一个库,在联网的情况下输入: sudo apt-get install libncurses5-dev

     menuconfig 里中括号用 y/n 来选择编不编译进内核;尖括号用 y/n/m 来选择( y 表示编译进内核, n 表示不编译进内核, m 表示编译进内核,当编译的最后结果不放进最后编译成的内核镜像文件 uImage ,它们单独编译成以 .ko 后缀结尾的文件,这些以 .ko 结尾的文件在内核启动后,再把这些加载,这样开机就会快点)其实上面这种可以直接按空格在 2 个或者 3 个选项中切换。

     有些时候 menuconfig 里选项太多了,我们可以按 / 就可以切换到搜索界面去搜索自己想要找的内容

     内核文件大多数目录下都有 Kconfig 文件,当我们在内核主目录下面在命令行输入 make menuconfig 命令时,系统会去读每个目录下面的 Kconfig 文件,然后再去把这个 menu 制造出来

     当你在 menu 里修改了东西并保存了,系统会自动更新 .config ,但是会备份一个之前的 .config .config.old


6. 在内核目录 Documentation/kbuild/kconfig-language.txt 下介绍了 Kconfig 的一些语法,文档只有 300 多行。该语法教你如何在 menuconfig 里添加选项。就是在内核目录的各个 Kconfig 文件里添加 Kconfig 语法来实现在 menuconfig 菜单里添加选项。
     有一个技巧教你怎么去照葫芦画瓢去编写一个 menuconfig 一个子菜单 : 进入 menu 选择一个子栏目,右键切换到 help 里可以在中间看到该子菜单是在内核哪个文件的 config 的多少行编写出来的,你再去哪行去看看 Kconfig 语法。

7.内核编译后删除包括.config等编译生成的文件命令:make mrproper(执行完该命令后要重新配置内核)

8.内核启动的入口程序:arch/arm/boot/compressed/head.S。因为内核uImage是压缩过的,所以在这个文件里要运行kernel需要进行内核自解压。

9. “哦,这个多的文件,我该如何去查看XX函数的实现!”相信这是很多朋友的抱怨。太多的文件导致我们无法去定位一个函数的实现或者一个宏定义的位置。显然对于 源码 阅读 和个人的学习都是非常不利的。多么希望有一个软件能够输入命令就能够精确的定位函数的位置。是的,现在有这么一个工具:ctags,它需要和vim编辑器配合使用,让源码阅读可以更加轻松。
    在Windows下我们可以通过sourceinsight去源码中查看某函数的实现,但是Linux系统里没有sourceinsight就需要ctags工具了。
    首先需要安装ctags:sudo apt-get install ctags
    其次要在主目录下生成tags文件:make tags
    最后选中函数名,按Ctrl+]可以跳到函数实现的地方;按Ctrl+t回到函数定义处。有些时候你按Ctrl+]想找到函数实现的地方时,可能会出现同名的2个地方都有此函数,ctags默认会跳到该函数第一个出现的地方,但这个地方有可能是函数声明的地方(有时vim下面出现"tag 1 of 2 or more"),这个时候我们需要输入":ts",它会把所有出现该函数的地方都列出来,你再输入1、2....

10.设备树文件在arch/arm/boot/dts里,里面每一个文件都代表一个板子设备。华清用的是里面的exynos4412-origen.dts改为exynos4412-fs4412.dts。

11.设备树里的compatible第一个参数表示主要支持的machine,第二个参数表示兼容的machine,用来表示每个设备的子节点也有这个属性,用来将驱动和设备绑定。比如:compatible = "davicom,dm9000"(字符串匹配)

12.网卡驱动设备树里的2行代码意思:
    interrupt-parent=<&gpx0>;//网卡需要中断来接收数据,中断产生后信号传到CPU的gpx0号管脚
    interrupts=<6 4>;//6表示具体用的是gpx0管脚的第六个管脚(gpx0-6);4表示触发方式(高电平有效),这些信息在kernel里的/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt

13.在设备树文件中添加了设备信息后,在主目录下执行编译命令:make dtbs

14.内核和驱动的调试:
    1)点灯法
    2)串口打印(用的最多)----->内核解压前用putstr打印输出;内核解压后用printk打印输出
    3)查看oops信息
    4)硬件调试器:BDI2000或其他JTAG工具

15.dmesg把所有的信息打印出来,包括printk的的所有级别信息

16.oops产生原因:
    ->内存访问越界
    ->野指针(指针定义时未初始化)

17. 野指针产生原因:
      1)指针变量未初始化 任何 指针变量 刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以, 指针变量 在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
       2)指针释放后未置空:当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。

18.oops信息要和Addr2line一起用:Addr2line是把地址变成对应的文件的行号(源码的位置)
   示例:arm-none-linux-gnueabi-addr2line -e vmlinux -f 0x0277d84(vmlinux是位压缩的内核源码)

19.kernel起来后系统会去运行1号进程:init进程

20.根文件系统的移植:
    1)通过BusyBox创建基本的命令(cd、chmod等):下载BusyBox,解压。执行make menuconfig。配置命令。交叉编译和安装(make,之后再make install,最后主目录下就出现_install目录了)
    2)创建基本的目录(进入到_install目录下执行mkdir lib etc var tmp dev sys proc)
    3)拷贝glibc动态库到_install/lib里。在rm _install/lib/*.a(删除静态库)和用绝对路径下的strip删除符号表。
    4)添加启动配置和脚本程序/etc/inittab  /etc/fstab  /etc/init.d/rcS
    5)。。。。。。。

21.什么是RamDisk:Ram:内存,Disk:磁盘,在Linux中可以将一部分内存当作硬盘分区来使用,称之为RamDisk。对于一 些经常被访问、并且不会被更改的文件,可以将它们通过RamDisk放在内存中,能够明显地提高系统性能。
    



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值