Linux用作嵌入式 *** 作系统

Linux用作嵌入式 *** 作系统,第1张

Linux as an Embedded Operating System Linux有用作嵌入式 *** 作系统的潜力吗?本文讨论了Linux的特点 健壮 性 局限以及最重要的一点 它的实时特性 近年来 PC硬件使用的增加是高端嵌入式系统最重要的发展之一 这种 趋势造成高端系统硬件造价的大大跌落 从而使那些以前由于使用非P C结构的嵌入式硬件价格过高而不能做的项目成为可行的 但是嵌入式 PC平台上可选择的软件并不像硬件那样有诱惑力 你可以选择DOS 有 众所周知的局限性 微软Windows 缺乏实时性能 或者某种高端实时 *** 作系统 昂贵 专用 大多是不可移植的 Linux *** 作系统提供了另 外的有吸引力的选择 并且没有上面那些缺陷 Linux先前只是狂热的 Unix迷们闲时专门在台式电脑上使用 后来发展成为必须认真对待的高 级的 稳定的 *** 作系统 最近的发展之一是引入了实时性能 从而使L inux完成了重要的转变 即从爱好者的玩具成为适合嵌入式系统设计者 的有价值的工具 当然 其实时性能还没有那些高端RTOS那么高级 并 且Linux永远不会适合需要最小化RAM和ROM的系统 但是 对很多应用 来说 Linux的优势胜过了不足 现在 大家都知道在嵌入式系统中使用PC硬件的好处 与很多专为嵌入 式市场设计的硬件比较 PC硬件是大规模生产的 容易获得并且便宜 为VME总线设计的接口板价格是PC总线的两倍多 比如模拟和数字I/O板 网络接口 图像采集与处理板等 随着高性能PCI总线应用的增加 吞吐量不再是影响使用PC平台的问题 但是 *** 作系统功能上已经发生革命性的变化 在要求硬件价格降低的同 时 高端嵌入式系统要求更多高级的功能 如图形用户界面和网络支持 很多高端RTOS供应商已经提供了这些功能 一般是作为花更高价钱才 能得到的可选件 微软Windows也有这些功能 却不具备大多数嵌入式 系统要求的实时性能 也许有人想以DOS为基础用单独的第三方工具拼 凑一个系统 但这种努力将是白费并且不存在对这种系统的技术支持 现在需要的是一个便宜 成熟并且提供高端嵌入式系统所必须特性的 *** 作系统 因此 Linux *** 作系统近来开始吸引大家的注意 许多台式PC用户被它 的特点和健壮性所吸引 并且获得它只需支付通过FTP下载的网络费用 Linux带有Unix用户熟悉的完善的开发工具 几乎所有的Unix系统和 应用软件都已移植到了Linux上 Linux还提供了TCP/IP网络协议以及I nternet客户和服务器软件 还有可选择多种窗口管理器的X Windows C C++ Java和其他语言的编译器也可得到 用户会发现这些比Windo ws提供的更成熟 更完善 更易于使用 许多公司至少会有一位Linux 的热衷者 当出现用Windows解决不了的问题时(比如设置一台PC为拨 号服务器)会说 瞧 我们要是用Linux 现在 讨论Bill Gates是否有所担心是有些杂志的一个话题 重要的是 不属于任何一家公司的Linux开始被台式电脑用户接受 其中许多人并 不能被认为是电脑迷 这一方面是因为Linux的成熟 另一方面也因为 这几年Internet的盛行 Linux用户遇到问题时可以通过Internet新闻 组和邮件列表向网上成千上万的在线用户请教 你遇到的问题别人以前 肯定碰到过 一般他们都乐于帮忙 根据我的经验 通常使用网络资源 能比依赖RTOS技术支持部门更快地解决问题 你可能需要从十几条新闻 组其他成员回答的相关信息中搜寻 但至少有一个回答应该是有用的 相比较而言 你从技术支持部门仅得到一个回答 如果是错的 你不得 不重新开始整个过程 另外 致力于提供Linux支持的公司也已经出现 给那些觉得传统的技术支持手段更舒服的用户一个选择 并且所有L inux是提供源代码的 这使最困难的问题也有办法解决 某些嵌入式系统设计者会发现Linux本来的样子就很有用 对于没有实 时要求的应用 或者有实时要求但可以用一定的硬件或协处理器满足的 应用 Linux提供了Windows和DOS之外的选择 但是那样的应用几乎没 有 因此 用Linux实现一个实时 *** 作系统才是真正需要的 并且为了 用它实现高端嵌入式应用已经做了充分的工作 总的来说 有两条途径 来实现实时Linux 在此称之为POSIX路线和低层路线 POSIX和Linux POSIX是标准化类Unix *** 作系统必须具有的特征和接口的运动 POSIX的 思想是为了促进为Unix编写的软件的可移植性 使Unix程序员的工作更 容易 有些实时性的扩展 象POSIX b或IEEE b已经加入到标准 中 这些扩展中包括一些工具 比如信号灯 内存锁定 时钟和计数器 消息队列以及优先级抢先调度 以POSIX为基础来标准化实时 *** 作系统已经受到指责 这个标准又大又 笨 包含了许多适合台式Unix工作站但无助于嵌入式系统的特征 因而 显得很臃肿 标准制定群体被工作站制造商控制 他们不愿对RTOS供应 商和用户让步 还有 POSIX系统调用反映了Unix系统调用的复杂和笨 重 在VxWorks或pSOS+中仅需一两个调用即可完成的 *** 作可能需要十几 个POSIX调用 Unix程序员已经习惯了这种麻烦事 但是嵌入式系统程 序员却觉得很难受 许多Linux开发者正在为了在Linux中实现POSIX b的特征工作 这个活 动已经初见成效并且仍在继续 POSIX内存锁定工具和决定调度算法的 函数已经实现 另外 计数器函数和POSIX b信号仍未完成 也许最糟 糕的是 对任何真正的RTOS都至关重要的信号灯和消息队列也未实现 定义于POSIX c(或IEEE C)中的POSIX线程保证会为POSIX路线 的Linux开发实现 一个进程内可以有多个线程 共享相同的地址空间 这很符合我们熟悉的嵌入式系统中任务的概念 Linux已经部分实现 了POSIX线程 虽然POSIX路线对实现一个实时Linux做了保证 当前和可预见的将来只 有 软 实时的应用能用POSIX b函数来实现 移植POSIX b函数到L inux上时要面对的根本问题是Linux的内核是不可抢先的 因此 要想 不对内核大动干戈而实现 硬 实时特性恐怕是不可能的 通向实时Linux的低层路线 Low level Approach to Real time Linux 比POSIX路线更有意思的是实现硬实时Linux的努力 其中最有前途的要 数新墨西哥技术学院的实时Linux(RT Linux)项目 注意到Linux是一 个为台式电脑用户设计的 *** 作系统 研究者们断定 要想把实时功能移 植到为分时设计的OS上是不会有好结果的 取而代之的是 他们在 *** 作 系统的下面实现了一个简单的实时内核 而Linux本身也仅作为那个内 核上的一个任务来运行 Linux运行的优先级最低 随时可以被更高优 先级的任务抢先 RT Linux的设计理念是 对Linux作最小的改动 仅提供为了实现实时 应用必不可少的东西 这样就使RT Linux比较容易移植到新版本的Lin ux上 同时 RT Linux依赖于Linux来提供所需的几乎所有服务 而RT Linux仅提供低层任务创建 安装中断服务例程 并为低层任务 ISR 和Linux进程之间的通信排队 这种设计的结果之一是 一个RT Linux应用可以看作有两个域 实时和 非实时 放在实时域的函数能满足其实时要求 但是它们必须比较简单 因为可用资源很受限制 另一方面 非实时功能可以利用整个Linux 资源 但不能有任何实时要求 两个域之间的通信工具已提供 但是使 用RT Linux之前 嵌入式系统设计者必须确保所有需要实现的功能适合 两个域之一 使用RT Linux并不能变戏法似的使已经存在的Linux功能 具有实时性 例如 假设设计者有一个串口的Linux驱动程序 当串口 接收一个字节序列之后 在一个固定时间内 由实时任务打开并口输出 一行 这个驱动程序不能用 因为在非实时域内你不知道什么时候串口 驱动程序会唤醒实时任务驱动并口完成工作 因此 串口和并口驱动都 必须在实时域内 这就要求重新设计串口驱动程序 RT Linux的任务处理工具是基本的 rt_task_init()用来创建并开始一 个任务 能指定堆栈的大小和优先级 Linux本身以一个最低优先级的 实时任务运行 rt_task_make_periodic()以一定间隔周期性地设置任 务运行 rt_task_wait()阻塞任务 使用简单的抢先调度运行任务 实时任务与Linux进程之间通信的主要方法是FIFO rtf_create()创建 一个一定大小的FIFO 用rtf_put()将数据送入FIFO 如果FIFO满则返 回一个错误 类似地 rtf_get()从FIFO中取出数据 如果FIFO空则返 回一个错误 FIFO最显著的应用是数据流 例如 在一个数据采集应用中 可以用r t_task_init()和rt_task_make_periodic()设置实时任务使其以固定的 间隔从I/O板采样 这个任务用rtf_put()将数据发送到Linux进程 该 Linux进程应该是一个循环 不断从FIFO读出数据 也许还要写数据到 磁盘 或者通过网络发送 或者显示在一个X窗口中 FIFO象一个缓冲 因此Linux进程不必非有实时性不可 实现数据流系统看起来成为RT Linux设计者的主要动机 但是FIFO机制 提供了一个实现信号灯的很好方法 两态信号灯可以通过创建一个大小 为 的FIFO来实现 V *** 作即为rtf_put() 数据内容无所谓 同时忽略 返回的错误 P *** 作为rtf_get() 计数信号灯可以通过创建大小足够容 纳所期望V *** 作个数的FIFO简单地实现 由此可见 FIFO机制提供了实 时应用中任务同步所需的大部分功能 当前的实现在RTOS用户习惯的某 些功能上仍有欠缺 比如优先级禁止(防止优先级反转)和任务安全删 除 但是仔细设计几乎总能避免这些问题 此外 虽然FIFO *** 作可以在 没有数据(读FIFO)或没有空间(写FIFO)时阻塞 语法却相当复杂 阻塞能力看来不是设计的重点 然而 至少有一个提供FIFO阻塞 *** 作简 单语法的努力正在进行 同时还实现了阻塞超时 这是许多嵌入式应用 的重要特征 RT Linux简单 开放的设计允许用户相当容易地实现类似 的附加功能 RT Linux的一个有趣的方面是设计者使Linux内核 lishixinzhi/Article/program/Oracle/201311/17916

在学习系统移植的相关知识,在学习和调试过程中,发现了很多问题,也解决了很多问题,但总是对于我们的开发结果有一种莫名其妙的感觉,纠其原因,主要对于我们的开发环境没有一个深刻的认识,有时候几个简单的命令就可以完成非常复杂的功能,可是我们有没有想过,为什么会有这样的效果?

如果没有去追问,只是机械地完成,并且看到实验效果,这样做其实并没有真正的掌握系统移植的本质。

在做每一个步骤的时候, 首先问问自己,为什么要这样做,然后再问问自己正在做什么? 搞明白这几个问题,我觉得就差不多了,以后不管更换什么平台,什么芯片,什么开发环境,你都不会迷糊,很快就会上手。对于嵌入式的学习方法,我个人方法就是:从宏观上把握(解决为什么的问题),微观上研究(解决正在做什么的问题),下面以自己学习的arm-cortex_a8开发板为目标,介绍下自己的学习方法和经验。

嵌入式Linux系统移植主要由四大部分组成:

一、搭建交叉开发环境

二、bootloader的选择和移植

三、kernel的配置、编译、和移植

四、根文件系统的制作

第一部分:搭建交叉开发环境

先介绍第一分部的内容:搭建交叉开发环境,首先必须得思考两个问题,什么是交叉环境? 为什么需要搭建交叉环境?

先回答第一个问题,在嵌入式开发中,交叉开发是很重要的一个概念,开发的第一个环节就是搭建环境,第一步不能完成,后面的步骤从无谈起,这里所说的交叉开发环境主要指的是:在开发主机上(通常是我的pc机)开发出能够在目标机(通常是我们的开发板)上运行的程序。嵌入式比较特殊的是不能在目标机上开发程序(狭义上来说),因为对于一个原始的开发板,在没有任何程序的情况下它根本都跑不起来,为了让它能够跑起来,我们还必须要借助pc机进行烧录程序等相关工作,开发板才能跑起来,这里的pc机就是我们说的开发主机,想想如果没有开发主机,我们的目标机基本上就是无法开发,这也就是电子行业的一句名言:搞电子,说白了,就是玩电脑!

然后回答第二个问题,为什么需要交叉开发环境?主要原因有以下几点:

原因 1: 嵌入式系统的硬件资源有很多限制,比如cpu主频相对较低,内存容量较小等,想想让几百MHZ主频的MCU去编译一个Linux kernel会让我们等的不耐烦,相对来说,pc机的速度更快,硬件资源更加丰富,因此利用pc机进行开发会提高开发效率。

原因2: 嵌入式系统MCU体系结构和指令集不同,因此需要安装交叉编译工具进行编译,这样编译的目标程序才能够在相应的平台上比如:ARM、MIPS、 POWEPC上正常运行。

交叉开发环境的硬件组成主要由以下几大部分

1.开发主机

2.目标机(开发板)

3.二者的链接介质,常用的主要有3种方式:(1)串口线 (2)USB线 (3)网线

对应的硬件介质,还必须要有相应的软件“介质”支持:

1.对于串口,通常用的有串口调试助手,putty工具等,工具很多,功能都差不多,会用一两款就可以;

2.对于USB线,当然必须要有USB的驱动才可以,一般芯片公司会提供,比如对于三星的芯片,USB下载主要由DNW软件来完成;

3.对于网线,则必须要有网络协议支持才可以, 常用的服务主要两个

第一:tftp服务:

主要用于实现文件的下载,比如开发调试的过程中,主要用tftp把要测试的bootloader、kernel和文件系统直接下载到内存中运行,而不需要预先烧录到Flash芯片中,一方面,在测试的过程中,往往需要频繁的下载,如果每次把这些要测试的文件都烧录到Flash中然后再运行也可以,但是缺点是:过程比较麻烦,而且Flash的擦写次数是有限的;另外一方面:测试的目的就是把这些目标文件加载到内存中直接运行就可以了,而tftp就刚好能够实现这样的功能,因此,更没有必要把这些文件都烧录到Flash中去。

第二: nfs服务:

主要用于实现网络文件的挂载,实际上是实现网络文件的共享,在开发的过程中,通常在系统移植的最后一步会制作文件系统,那么这是可以把制作好的文件系统放置在我们开发主机PC的相应位置,开发板通过nfs服务进行挂载,从而测试我们制作的文件系统是否正确,在整个过程中并不需要把文件系统烧录到Flash中去,而且挂载是自动进行挂载的,bootload启动后,kernel运行起来后会根据我们设置的启动参数进行自动挂载,因此,对于开发测试来讲,这种方式非常的方便,能够提高开发效率。

另外,还有一个名字叫 samba 的服务也比较重要,主要用于文件的共享,这里说的共享和nfs的文件共享不是同一个概念,nfs的共享是实现网络文件的共享,而samba实现的是开发主机上 Windows主机和Linux虚拟机之间的文件共享,是一种跨平台的文件共享 ,方便的实现文件的传输。

以上这几种开发的工具在嵌入式开发中是必备的工具,对于嵌入式开发的效率提高做出了伟大的贡献,因此,要对这几个工具熟练使用,这样你的开发效率会提高很多。等测试完成以后,就会把相应的目标文件烧录到Flash中去,也就是等发布产品的时候才做的事情,因此对于开发人员来说,所有的工作永远是测试。

通过前面的工作,我们已经准备好了交叉开发环境的硬件部分和一部分软件,最后还缺少交叉编译器,读者可能会有疑问,为什么要用交叉编译器?前面已经讲过,交叉开发环境必然会用到交叉编译工具,通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,开发主机PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。相对于交叉编译,平常做的编译叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。用来编译这种跨平台程序的编译器就叫交叉编译器,相对来说,用来做本地编译的工具就叫本地编译器。所以要生成在目标机上运行的程序,必须要用交叉编译工具链来完成。

这里又有一个问题,不就是一个交叉编译工具吗?为什么又叫交叉工具链呢?原因很简单,程序不能光编译一下就可以运行,还得进行汇编和链接等过程,同时还需要进行调试,对于一个很大工程,还需要进行工程管理等等,所以,这里 说的交叉编译工具是一个由 编译器、连接器和解释器 组成的综合开发环境,交叉编译工具链主要由binutils(主要包括汇编程序as和链接程序ld)、gcc(为GNU系统提供C编译器)和glibc(一些基本的C函数和其他函数的定义) 3个部分组成。有时为了减小libc库的大小,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。

那么,如何得到一个交叉工具链呢?是从网上下载一个“程序”然后安装就可以使用了吗?回答这个问题之前先思考这样一个问题,我们的交叉工具链顾名思义就是在PC机上编译出能够在我们目标开发平台比如ARM上运行的程序,这里就又有一个问题了,我们的ARM处理器型号非常多,难道有专门针对我们某一款的交叉工具链吗?若果有的话,可以想一想,这么多处理器平台,每个平台专门定制一个交叉工具链放在网络上,然后供大家去下载,想想可能需要找很久才能找到适合你的编译器,显然这种做法不太合理,且浪费资源!因此,要得到一个交叉工具链,就像我们移植一个Linux内核一样,我们只关心我们需要的东西,编译我们需要的东西在我们的平台上运行,不需要的东西我们不选择不编译,所以,交叉工具链的制作方法和系统移植有着很多相似的地方,也就是说,交叉开发工具是一个支持很多平台的工具集的集合(类似于Linux源码),然后我们只需从这些工具集中找出跟我们平台相关的工具就行了,那么如何才能找到跟我们的平台相关的工具,这就是涉及到一个如何制作交叉工具链的问题了。

通常构建交叉工具链有如下三种方法:

方法一 : 分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用下列的方法二构建交叉工具链。

方法二: 通过Crosstool-ng脚本工具来实现一次编译,生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。

方法三 : 直接通过网上下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的,没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名其妙的错误,建议读者慎用此方法。

crosstool-ng是一个脚本工具,可以制作出适合不同平台的交叉编译工具链,在进行制作之前要安装一下软件:

$ sudo apt-get install g++ libncurses5-dev bison flex texinfo automake libtool patch gcj cvs cvsd gawk

crosstool脚本工具可以在http://ymorin.is-a-geek.org/projects/crosstool下载到本地,然后解压,接下来就是进行安装配置了,这个配置优点类似内核的配置。主要的过程有以下几点:

1. 设定源码包路径和交叉编译器的安装路径

2. 修改交叉编译器针对的构架

3. 增加编译时的并行进程数,以增加运行效率,加快编译,因为这个编译会比较慢。

4. 关闭JAVA编译器 ,减少编译时间

5. 编译

6. 添加环境变量

7. 刷新环境变量。

8. 测试交叉工具链

到此,嵌入式Linux系统移植四大部分的第一部分工作全部完成,接下来可以进行后续的开发了。

第二部分:bootloader的选择和移植

01 Boot Loader 概念

就是在 *** 作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用 *** 作系统内核准备好正确的环境,他就是所谓的引导加载程序(Boot Loader)。

02 为什么系统移植之前要先移植BootLoader?

BootLoader的任务是引导 *** 作系统,所谓引导 *** 作系统,就是启动内核,让内核运行就是把内核加载到内存RAM中去运行,那先问两个问题:第一个问题,是谁把内核搬到内存中去运行?第二个问题:我们说的内存是SDRAM,大家都知道,这种内存和SRAM不同,最大的不同就是SRAM只要系统上电就可以运行,而SDRAM需要软件进行初始化才能运行,那么在把内核搬运到内存运行之前必须要先初始化内存吧,那么内存是由谁来初始化的呢?其实这两件事情都是由bootloader来干的,目的是为内核的运行准备好软硬件环境,没有bootloadr我们的系统当然不能跑起来。

03 bootloader的分类

首先更正一个错误的说法,很多人说bootloader就是U-boot,这种说法是错误的,确切来说是u-boot是bootloader的一种。也就是说bootloader具有很多种类,

由上图可以看出,不同的bootloader具有不同的使用范围,其中最令人瞩目的就是有一个叫U-Boot的bootloader,是一个通用的引导程序,而且同时支持X86、ARM和PowerPC等多种处理器架构。U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目,是由德国DENX小组开发的用于多种嵌入式CPU的bootloader程序,对于Linux的开发,德国的u-boot做出了巨大的贡献,而且是开源的。

u-boot具有以下特点:

① 开放源码;

② 支持多种嵌入式 *** 作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;

③ 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;

④ 较高的可靠性和稳定性;

⑤ 高度灵活的功能设置,适合U-Boot调试、 *** 作系统不同引导要求、产品发布等;

⑥ 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;

⑦ 较为丰富的开发调试文档与强大的网络技术支持;

其实,把u-boot可以理解为是一个小型的 *** 作系统。

04 u-boot的目录结构

* board 目标板相关文件,主要包含SDRAM、FLASH驱动;

* common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;

* cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;

* driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)

* doc U-Boot的说明文档;

* examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;

* include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;

* lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;

* net 与网络功能相关的文件目录,如bootp,nfs,tftp;

* post 上电自检文件目录。尚有待于进一步完善;

* rtc RTC驱动程序;

* tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;

05 u-boot的工作模式

U-Boot的工作模式有 启动加载模式和下载模式 。启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式 *** 作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。 下载模式 就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的SDRAM中运行,用户可以利用Bootloader提供的一些令接口来完成自己想要的 *** 作,这种模式主要用于测试和开发。

06 u-boot的启动过程

大多数BootLoader都分为stage1和stage2两大部分,U-boot也不例外。依赖于cpu体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

1、 stage1(start.s代码结构)

U-boot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下:

(1) 定义入口。由于一个可执行的image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在rom(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。

(2)设置异常向量(exception vector)。

(3)设置CPU的速度、时钟频率及中断控制寄存器。

(4)初始化内存控制器 。

(5)将rom中的程序复制到ram中。

(6)初始化堆栈 。

(7)转到ram中执行,该工作可使用指令ldrpc来完成。

2、 stage2(C语言代码部分)

lib_arm/board.c中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数主要完成如下 *** 作:

(1)调用一系列的初始化函数。

(2)初始化flash设备。

(3)初始化系统内存分配函数。

(4)如果目标系统拥有nand设备,则初始化nand设备。

(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写ip,c地址等。

(7)进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

07 基于cortex-a8的s5pc100bootloader启动过程分析

s5pc100支持两种启动方式,分别为USB启动方式和NandFlash启动方式:

1. S5PC100 USB启动过程

[1] A8 reset, 执行iROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到4对面),判断从哪里启动(USB)

[3] iROM中的程序会初始化USB,然后等待PC机下载程序

[4] 利用DNW程序,从PC机下载SDRAM的初始化程序到iRAM中运行,初始化SDRAM

[5] SDRAM初始化完毕,iROM中的程序继续接管A8, 然后等待PC下载程序(BootLoader)

[6] PC利用DNW下载BootLoader到SDRAM

[7] 在SDRAM中运行BootLoader

2. S5PC100 Nandflash启动过程

[1] A8 reset, 执行IROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到靠4那边),判断从哪里启动(Nandflash)

[3] iROM中的程序驱动Nandflash

[4] iROM中的程序会拷贝Nandflash前16k到iRAM

[5] 前16k的程序(BootLoader前半部分)初始化SDRAM,然后拷贝完整的BootLoader到SDRAM并运行

[6] BootLoader拷贝内核到SDRAM,并运行它

[7] 内核运行起来后,挂载rootfs,并且运行系统初始化脚本

08 u-boot移植(基于cortex_a8的s5pc100为例)

1.建立自己的平台

(1).下载源码包2010.03版本,比较稳定

(2).解压后添加我们自己的平台信息,以smdkc100为参考版,移植自己s5pc100的开发板

(3).修改相应目录的文件名,和相应目录的Makefile,指定交叉工具链。

(4).编译

(5).针对我们的平台进行相应的移植,主要包括修改SDRAM的运行地址,从0x20000000

(6).“开关”相应的宏定义

(7).添加Nand和网卡的驱动代码

(8).优化go命令

(9).重新编译 make distclean(彻底删除中间文件和配置文件) make s5pc100_config(配置我们的开发板) make(编译出我们的u-boot.bin镜像文件)

(10).设置环境变量,即启动参数,把编译好的u-boot下载到内存中运行,过程如下:

1. 配置开发板网络

ip地址配置:

$setenv ipaddr 192.168.0.6 配置ip地址到内存的环境变量

$saveenv 保存环境变量的值到nandflash的参数区

网络测试:

在开发开发板上ping虚拟机:

$ ping 192.168.0.157(虚拟机的ip地址)

如果网络测试失败,从下面几个方面检查网络:

1. 网线连接好

2. 开发板和虚拟机的ip地址是否配置在同一个网段

3. 虚拟机网络一定要采用桥接(VM--Setting-->option)

4. 连接开发板时,虚拟机需要设置成 静态ip地址

2. 在开发板上,配置tftp服务器(虚拟机)的ip地址

$setenv serverip 192.168.0.157(虚拟机的ip地址)

$saveenv

3. 拷贝u-boot.bin到/tftpboot(虚拟机上的目录)

4. 通过tftp下载u-boot.bin到开发板内存

$ tftp 20008000(内存地址即可) u-boot.bin(要下载的文件名)

如果上面的命令无法正常下载:

1. serverip配置是否正确

2. tftp服务启动失败,重启tftp服务

#sudo service tftpd-hpa restart

5. 烧写u-boot.bin到nandflash的0地址

$nand erase 0(起始地址) 40000(大小) 擦出nandflash 0 - 256k的区域

$nand write 20008000((缓存u-boot.bin的内存地址) 0(nandflash上u-boot的位置) 40000(烧写大小)

6. 切换开发板的启动方式到nandflash

1. 关闭开发板

2. 把SW1的开关4拨到4的那边

3. 启动开发板,它就从nandflash启动


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8494600.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-17
下一篇 2023-04-17

发表评论

登录后才能评论

评论列表(0条)

保存