嵌入式中的移植是什么意思,移植系统呢

与其他操作系统相比,Linux最大的特点就是它是一个遵循GPL的操作系统,我们可以自由地使用、修改和扩展它。
正是因为这个特点,Linux受到了越来越多的人的青睐。
因此,一个经常被讨论的问题就出现了,那就是Linux系统的移植。
对于操作系统来说,这种移植通常是跨平台的、与硬件相关的,即硬件系统结构甚至CPU都不同。
我们来看看移植Linux系统时需要做什么。
1、Linux系统移植的两个主要部分对于系统移植来说,Linux系统实际上由两个相对独立的部分组成,即内核部分和系统部分。
通常启动Linux系统的过程是这样的:不与任何操作系统关联的引导加载程序将Linux内核的一部分传输到内存中,并手动将Linux内核中的第一行代码签入内存中。
加载程序的工作完成后,Linux会将自身剩余的所有部分加载到内存中(如果有的话,取决于硬件平台),初始化所有设备并在内存中设置所需的数据。
与进程、设备、内存等相关)。
至此,Linux内核已经完成工作,内核已经检查了所有的硬件设备。
至于这些硬件设备的操作和使用,就轮到系统部分上台了。
内核加载根设备并启动init守护进程init守护进程加载文件系统,配置网络、服务进程、终端等。
根据配置文件。
终端初始化后,我们将看到系统欢迎界面。
总结一下:(1)内核部分初始化并控制所有硬件设备(严格来说不是全部,而是大部分),为内存管理、进程管理、设备读写等做好一切准备。
(2)系统部分加载必要的设备并配置各种环境,以便用户可以使用整个系统。
2、系统移植所需的环境在进一步描述之前,我们必须提到系统移植所需的环境。
首先,需要新版本的gcc。
对于准备移植系统的程序员来说,他需要了解它有多“新”。
对于跨平台编译,gcc可能是最好的选择。
另外,Linux内核支持许多gcc特有的功能,也是必须的。
如果你已经使用过gcc并且练习过很多次,那么只需要进一步巩固跨平台编译操作即可。
有两种编译环境可供选择:非目标平台上的Linux或者目标平台上的非Linux系统,如果你的开发平台不是很具体你一定能找到可以使用的gcc。
其次,编译链接库是必需的,并且必须是目标平台的编译链接库。
这通常是一个无聊、乏味且没有成就感的过程。
如果幸运的话,将会有一个现成的链接库可用。
否则,你必须用gcc自己构建它。
最后,您需要目标平台的所有文档,越多越好。
如果有一个环境一定的支持/模拟,Loader(加载器)是最好的。
这些可以帮助您减少迁移过程中在琐碎问题上浪费的时间。
3、移植Linux系统下面我们从内核和系统两个方面来阐述移植中的要点。
(1)内存移植Linux系统采用相对不灵活的单内核机制,但这完全不影响Linux系统的平台独立性和可扩展性。
Linux用两种方法来解决这些问题,一是非常干净整洁,一点也不笨重,二是非常清晰易懂。
将硬件绑定代码和硬件无关代码分开,这样上层代码永远不必担心低层代码使用了什么代码以及操作是如何执行的。
无论是在x86还是Alpha平台上分配一块内存对于高级代码来说都没有区别。
硬件相关部分的代码并不多,只占总代码的一小部分。
因此,改变硬件平台并没有真正的负担。
另一方面,Linux利用内核机制很好地解决了扩展问题。
当你不需要的时候,可以把它放在抽屉里。
Linux内核可以看作由五个功能部分组成:进程管理(包括调试和通信)、内存管理、设备管理、虚拟文件系统、网络。
它们之间存在复杂的调用关系,但幸运的是,在移植过程中它们不会受到太大影响,因为Linux内核良好的分层结构将硬件相关的代码分开。
什么是与硬件相关的,什么是无关的?以进程管理为例,在所有平台的Linux中,进程的时间轮换调度算法都是相同的,并且是平台无关的,而用于进程之间切换的实现在针对该平台编写的不同CPU上是不同的,是平台相关的。
上述五个部分的顺序并不是任意的,从前到后,它们代表了它们与硬件设备的关联程度。
前端越高,越低,两个虚拟文件系统和网络几乎是平台无关的。
因此,系统移植时,需要改动的就是进程管理、内存管理、设备管理等独立部分的代码,即硬件相关部分的代码。
在Linux代码树下,这段代码全部在arch目录下。
如果Linux内核已经支持您的目标平台,那么您很幸运,因为您没有太多工作要做。
只要你的构建环境正确,你只需要配置和编译就可以得到目标代码。
否则,系统会要求您输入或修改一些代码。
只需编辑平台相关部分的代码即可。
但需要对目标平台有透彻的了解,主要是CPU。
在Linux代码树下,可以看到这部分的典型代码量为:大约20000行C代码和大约2000行汇编(C代码通常包含很多伪汇编指令,所以实际上纯C代码需要少很多),这部分负载不可低估。
它涵盖了大多数设备的低级操作,包括IRQ、内存页表、快速表等问题,浮点处理、时钟、多处理器同步等。
通常,端口编程意味着您必须使用C语言重写。
这就是为什么目标平台的文档极其重要。
代码量最多的部分是核心直接调用的主要支撑部分。
这段代码位于arch/xxx/kernel下(xxx是平台名称)。
这段代码重写了内核需要调用的所有函数。
因为接口函数是固定的,所以更像是为硬件平台编写API。
不同系统平台的区别主要有以下几个方面:底层进程管理代码:从硬件系统角度来看,进程管理就是CPU管理。
这在不同的硬件平台上差异很大。
CPU中使用的寄存器结构不同,上下文切换、就地保存和恢复以及堆栈处理的方法也不同。
一般来说,所有CPU功能和状态不一定对Linux有意义。
在实施过程中,必须在较低的开发成本和更好的系统性能之间进行权衡。
*BIOSInterfaceCode:这个名称似乎不正确,因为它遵循PC的通用名称。
但只要不引起混乱,我们就会这样称呼它。
在通用平台上,操作系统通常有一个基本的输入和输出系统,在PC上是BIOS,在SPARC上是PROM。
大多数情况下,Linux并不依赖于基本I/O系统,但在某些系统上,Linux必须通过基本I/O系统来获取重要的设备参数。
在迁移过程中,这部分代码通常需要完全重写。
*时钟、中断等板载设备支持代码:即使在同一个CPU平台上,也会有不同的板载外设,尤其是在异构CPU平台上。
不同的系统配置需要不同的初始化代码。
一个典型的例子是MIPS平台,只要看一下arch/mips/的代码,并与其他系统进行比较即可。
因为MIPS平台是OEM厂商使用最多的,并且多用于嵌入式领域(相对于其他CPU)。
即使是同一颗MIPS芯片,也是由不同厂家封装、搭载不同芯片的。
因此,必须为这些不同的MIPS平台编写不同的代码。
*特殊结构代码:如多处理器支持等。
其实每种类型的CPU都很特别,众所周知,x86平台上的每个人都知道x86系列CPU著名的实模式和虚拟模式的区别,但是在SPARC平台上根本没有这样的概念。
这有很大的不同:PC上的Linux一旦获得控制权就开始进入虚拟模式,而SPARC机器没有此代码。
比如对电源管理的支持更是五花八门,不同的CPU有不同的实现方法(具体的电源管理方法甚至厂家都标明了)。
在这种情况下,如果不删除电源管理支持,则必须重写代码。
代码量也很少,但不可忽视的部分是arch/xxx/mm/下的内存管理部分。
所有特定于平台的内存管理代码都位于此处。
这部分代码完成了内存的初始化以及各种内存结构的设置与内存管理相关的数据。
Linux采用基于页管理的虚拟存储技术,而CPU的发展趋势是:为了提高性能,所有进行内存管理的功能单元都集成到CPU中。
因此,内存管理成为了一项非常依赖CPU的任务。
同时,内存管理的效率也是最影响系统性能的因素之一。
内存可以说是计算机系统中访问最频繁的设备,如果每次内存访问都需要多一个时钟周期,那么就会将系统性能降低到难以忍受的程度。
在Linux系统上,跨平台内存管理代码的变化速度是惊人的,可以说是最大的变化。
不同的CPU有不同的内存管理方式,同一个CPU也会有不同的内存管理方式。
Linux是从32位硬件平台发展而来的操作系统,但现在也有几种64位平台。
在64位平台上,可用内存范围增加到原来的232倍,而且差异几乎不可见。
考虑到这段代码的重要性和复杂性,这里的移植工作非常仔细。
有些平台甚至使用更保守的内存管理。
例如,SPARC平台上的页面大小可以是不同大小的,为了简单和可靠,SPARC版本的Linux仅使用8K页面模式。
这种情况直到2.4版本才得到改善。
除了上面提到的之外,还有一些代码需要考虑,但它们相对较小。
比如对浮点运算的支持。
最完美的做法是对FPU进行编程,让硬件完成浮点运算。
但在某些时候,浮点并不重要,甚至CPU根本不支持浮点。
这个时候你就可以根据自己的需要来选择了。
关于内核移植的讨论到此结束。
其实有几个移植任务需要同时考虑,但是很难说这属于内核范畴还是驱动范畴,比如对显示设备的支持就和内核有很大关系。
但逻辑上它不属于细胞核,必须移植。
因此这里不予讨论。
(2)系统移植核心移植完成后,可以说已经完成了大部分的移植工作。
即当内核编译成功,加载到目标平台并正常启动,并出现类似VFS:Can\mountrootfilesystem的命令时,就意味着可以开始移植系统的工作了。
系统迁移实际上是一个最小的系统重建过程。
许多Linux爱好者都有构建Linux系统救援盘的经验。
不同的是,你需要使用目标平台上的二进制代码来生成这个最小系统。
包括:init、libc库、驱动模块、必要的应用程序和系统配置脚本。
这些任务完成后,移植工作将进入关节矫正阶段。
移植一部分系统比较简单的方法是,首先在开发平台上部署最小系统,保证这个最小系统能够正常运行。
在开发平台上正常工作。
这样就避免了最小系统本身的逻辑错误所带来的问题。
由于许多应用程序在一个最小的系统中一起工作,有时问题不是出现在代码本身,而是出现在系统的逻辑结构中。
Linux系统移植工作至少应该包括以上内容,除此之外,还有一些隐形的开发工作也不容忽视,比如特定设备的驱动程序、内核调试的远程调试作业等。
此外,对于相同的移植工作,满足最低功能集的移植和完美的移植之间存在明显的差异。
移植到16位也不同于移植到64位。
移植过程中遇到的一个常见问题是测试运行过程中的卡顿或崩溃。
当你移植系统的一部分时,处理起来比较容易,因为错误的根源很容易找到,但当你移植核心时,就真的很头疼了。
虽然可以通过串口调试执行内核,但在多任务情况下,存在很多无法重现的现象。
例如,在初始化之初,很多设备无法确定自己的状态,甚至串口也没有初始化。
对于这种情况没有好的解决办法。
一个好的开发/仿真平台非常重要。
硬件平台厂商的专业支持也很重要。
另外重要的一点是Linux本身是一个基于GPL的操作系统。

i.MX6ULL嵌入式Linux开发3-Kernel移植

本文将逐步介绍Linux内核迁移过程。
首先,可以从官方网站(kernel.org/)获取Linux内核的介绍。
NXP从Linux官方网站下载特定版本,然后移植到自己的CPU上,确保测试成功后,才会开放给NXPCPU开发者。
开发者下载NXP提供的Linux源代码并进行移植以满足自己产品的需求。
本文使用NXP提供的Linux源代码,文件名为:linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2。
接下来,Ubuntu操作系统中需要安装某些库,例如lzop和ncurses库,以支持内核编译。
在Ubuntu环境中创建一个文件夹,将下载的Linux内核压缩包放入其中并解压。
解压完成后,通过创建一个名为build.sh的新脚本文件来运行构建过程。
在脚本中输入相应的命令赋予脚本可执行权限,运行即可自动启动编译过程。
编译好的Linux内核会产生一个zImage文件,它是Linux镜像文件。
同时会在arch/arm/boot/dts目录下生成多个.dtb文件。
此.dtb文件是设备树文件。
vmlinux、Image、zImage和uImage的区别在于,vmlinux是编译生成的原始内核文件,zImage是gzip压缩的Image文件,uImage是旧版本uboot专用的镜像文件,较少使用。
现在。
Linux内核编译过程中会生成一系列文件,具体结构如下。
编译完成后,会在arch/arm/boot目录下生成一个zImage文件,在arch/arm/boot/dts目录下会生成多个.dtb文件。
接下来,将编译好的zImage和imx6ull-14x14-evk.dtb复制到Ubuntu的tftp目录下,通过uboottftp命令下载到开发板。
在uboot中设置bootargs环境变量后,通过命令下载zImage和imx6ull-14x14-evk.dtb到开发板并启动。
如果根文件系统在引导过程中没有出现错误,则需要在bootargs中指定根文件系统路径。
如果不指定或者路径设置错误,Linux内核启动后会出现类似的错误信息,最终导致内核崩溃。
要了解更多关于Linux内核的信息,可以参考官方开发板设置,将自己的开发板添加到Linux内核中。
这包括复制imx_v7_mfg_defconfig文件的副本并将其重命名为您自己的开发板名称;修改Makefile并添加对新设备树文件的引用创建build_myboard.sh脚本并编写编译zImage和imx6ull-myboard.dtb文件的指令以完成Linux内核定制。