嵌入式X86主板装的是linux系统,能进BIOS,但是设置时间过短,会自动重启,这是什么原因?

iMX6Q系列作为明星产品深受大家的追捧,其性能强悍,使用稳定,多种显示支持,接口丰富。广泛适用于工控、医疗、多媒体、安防 、车载、金融、教学、电力、通讯、充电桩、智能家居、消费电子、手持设备、显示控制等领域。

但是想必大家也会关心一些使用和需求上的问题,这里小编找了一些问的比较多的问题,一起来看看是否有您所关注的问题吧。

Q1:工业级和商业级两种规格的开发板有什么区别呢?

A:工业级和商业级的区别主要体现在硬件上,比如工业级更能耐受高温和低温环境,适合复杂环境的使用。一般两种规格的板子主频不同,商业级可以达到1GHz,工业级只有800MHz,不过目前我们采用的是车规级芯片,主频也可以达到1GHz。这款车规级芯片在环境耐受和主频需求的满足上都有不错的表现。

Q2: 双核和四核核心板有什么区别呢?

A:双核和四核相比,双核核心板缓存低一些,四核是1MBL2缓存,双核是512KBL2缓存。双核缺少SATA接口。软件上双核和四核配置略有差异,因此生成的镜像会有区分,但是对功能的使用没有影响。在对核心板要求不是太高的情况下,可以考虑采用价格较低的双核核心板。

Q3: 我想使用内部RTC,如何使用呢?

A:软件上内部RTC已经配置好了,控制命令和外部的硬件RTC是一样的,只需要对照底板原理图在硬件上将空焊的电阻焊上就可以用了。以OK_MX6X_C底板为例,焊接如图所示电阻R58:

Q4: 如何修改时区,系统修改时区后时间为什么差了几小时?

A:我们可以通过使用时区文件修改时区,时区文件存放路径为/usr/share/zoneinfo/$主时区/$次时区,比如使用香港市区,在/etc下创建软连接ln -s

此外,/etc/default/rcS中设定了系统读取RTC芯片上的时间时按utc时间读,

当地时间是东八区,所以显示的当地时间会在RTC芯片时间上加8小时,需要修改成UTC=no解决该问题。

Q5:我想做双屏同显,可以实现吗?

A:目前支持同型号同分辨率的两个LVDS屏同时显示,相当于是从同一个口输出数据。如果需要使用其它屏幕做到双屏异显,也可以通过应用程序来实现。您只需要按照需求写对应的应用程序,就可以使屏幕显示出您想要的画面了。

Q6:我有一块不同分辨率的屏幕,在哪修改屏幕参数?

A:我们做了多种屏幕接口的支持。其中屏幕参数不在设备树文件中设置,我们需要在驱动中修改屏幕参数,比如LCD屏驱动:

另外修改默认屏幕和uboot传参是在:

我们还准备了具体的修改方法,您可以在我们的应用笔记资料中查看具体修改过程。

Q7: 如何把自己编译的镜像烧写到开发板呢?

A:USB烧写镜像存放路径为mfgtools\Profiles\Linux\OSFirmware\files\okmx6-c,将编译好的镜像替换到该目录下可烧写。制作的SD卡中有两个文件夹sdrun和target,其中sdrun中的文件是启动镜像,不需要更新,target目录下的是烧写到开发板的镜像,替换该目录下的镜像,之后按照正常烧写流程烧写就可以了。

Q8: 我想裁剪文件系统,可以从哪些方面入手呢?

A:文件系统的裁剪主要是裁剪不需要的服务、应用程序和库文件等,先确定自己不需要的内容,裁剪之前先判断是否会影响开发板的正常启动和运行,如果不确定可以先裁剪掉,验证一下是否会影响,如果影响了就还原回去。一般库文件在/usr/lib或/lib目录下,应用程序在/forlinx目录下,服务程序在/etc/init.d中

Q9: 如何让开发板开机自动运行应用程序?

A:一般运行的程序分两种,一种是做桌面使用,可以修改文件系统中的如下文件:/etc/matchbox/session,将matchbox-desktop &替换成要执行的程序,或者在这句后边加上要运行的程序,例如/forlinx/qtbin/ping &。另一种是只需要开机运行就可以,可以在/etc/rc.local中添加运行程序的命令,/forlinx/qtbin/ping &。注意一定要加 &使程序后台运行,否则开机打印信息会卡死,无法操作。

Q10: 我用ssh登录开发板总是失败怎么办?

A:一般ssh登录首先要验证网络是否有问题,比如电脑和开发板是否在同一网段,电脑和开发板能否ping通,网络连接有问题会直接报错连接失败。其次,ssh登录是需要密码的,如果开发板上没有给账户设置密码是不能登录的,需要通过passwd root给root用户添加密码或adduser username添加账户并设定密码。

上述解答是否解决了您心中的疑问呢,或者有哪些您关注的问题没有提到呢,欢迎私信我们,我们的团队将竭诚为您服务!

引言:本文简明扼要的介绍了嵌入式Linux的引导过程,X86体系的引导过程以及几种常见嵌入式处理器的引导过程,U-Boot的移植的基本步骤、常用命令如何使用。通过本文可以对嵌入式Linux的引导从概念到实际操作有一个总体清晰的认识

  • Bootloader(引导加载程序)本质上是一小段程序,其基本功能在于:

  • 从闪存存储,网络或其他类型的非易失性存储中加载应用程序二进制文件(通常是操作系统内核)。

  • 可能会对应用程序二进制文件进行解压缩

除此基本功能之外,大多数Bootloader(引导加载程序)实现了Shell命令集以执行不同操作。

  • 从存储或网络中加载数据,内存检查,硬件诊断和测试等

  • x86处理器通常安装在在一块包含BIOS程序的非易失性存储器主板上。

  • 在基于BIOS的旧x86平台上:BIOS负责基本的硬件初始化和从非易失性存储中加载一小段代码。

  • 这段代码通常是第一阶段的引导程序bootloader,它将加载完整的引导程序bootloader本身。

  • bootloader可以解析文件系统,因此内核映象可以直接从普通文件系统中加载。

  • 此顺序与现代基于EFI的系统不同。

  • GNU GRUB(GRand UnifiedBootloader简称“GRUB”)是一个来自GNU项目的多操作系统启动程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数。

在X86架构的机器中,Linux、BSD 或其它Unix类的操作系统中GRUB、LILO 是大家最为常用,应该说是主流。

  • syslinux是一个功能强大的引导加载程序,而且兼容各种介质。它的目的是简化首次安装Linux的时间,并建立修护或其它特殊用途的启动盘。它的安装很简单,一旦安装syslinux好之后,sysLinux启动盘就可以引导各种基于DOS的工具,以及MS-DOS/Windows或者任何其它操作系统。不仅支持采用BIOS结构的主板,而且从6.0版也开始支持采用EFI结构的新型主板。

  • CPU上电后,CPU开始在固定地址入口执行代码

  • CPU没有提供其他引导机制

  • 硬件设计必须确保已连接存储芯片(如NOR闪存芯片)这样就可以在CPU启动的地址访问它并执行指令

  • 第一级引导程序必须在此地址编程在该存储芯片中(如NOR)

  • NOR是强制性的,因为它允许随机访问,NAND不允许

注:这种方案已不常用,因为需要NOR FLASH

  • CPU在ROM中具有集成的引导代码。如:AT91 CPU上的BootROM,OMAP上的“ ROM代码”,等等。具体细节取决于CPU体系结构

  • 此引导代码能够将第一级引导加载程序从存储设备加载到内部SRAM(因为DRAM尚未初始化)。 存储设备通常可以是:MMC,NAND,SPI闪存,UART(通过串行线传输数据)等等。

  • 第一阶段的引导程序:  由于硬件限制,尺寸有限(SRAM比较贵),  由CPU供应商或社区项目提供

  • 此第一阶段引导程序必须初始化DRAM和其他硬件设备,并将第二阶段的引导程序加载到RAM

  • 因为本文专注嵌入式领域,故接下来将描述几种常见的嵌入式处理器的引导过程。

  • RomBoot:尝试从各种设备中找到有效的引导映像存储源,然后将其加载到SRAM中(DRAM还未初始化)。大小限制为4 KB,无法进行用户互动标准启动模式。

  • AT91Bootstrap:从SRAM运行。初始化DRAM,NAND或SPI控制器,并将辅助引导程序加载到RAM并启动它,此阶段没有用户互动的可能。

  • U-Boot:从RAM运行。初始化其他一些硬件设备(网络,USB等)。从存储或加载内核映像网络到RAM并启动它。此阶段Shell命令可以使用。

  • Linux内核:从RAM运行。完全接管系统(引导加载程序bootloader不再存在)。

  • ROM代码:尝试从各种方法中找到有效的引导映像存储源,并将其加载到SRAM或RAM中(RAM可以是由ROM代码通过配置标头初始化)。尺寸限制为<64 KB。没有用户互动的可能。

  • X-Loader或U-Boot SPL:从SRAM运行。初始化DRAM,NAND或MMC控制器,并加载辅助将引导程序加载到RAM中并启动它。没有用户互动的可能。文件名为MLO。

  • U-Boot:从RAM运行。初始化其他一些硬件设备(网络,USB等)。从存储或加载内核映像网络到RAM并启动它。具有提供的命令的Shell。该文件一般名为u-boot.bin或u-boot.img。

  • Linux内核:从RAM运行。完全接管系统(引导程序不再存在)。

  • ROM代码:尝试从各种方法中找到有效的引导影像

  • 存储源,并将其加载到RAM中。RAM配置为在特定于CPU的标头中进行了描述,该标头已添加到引导加载程序中图片。

  • U-Boot:从RAM运行。初始化其他一些硬件设备(网络,USB等)。从存储或加载内核映像网络到RAM并启动它。具有提供的命令的Shell。文件名为u-boot.kwb。

  • Linux内核:从RAM运行。完全接管系统(引导程序不再存在)。

本文将重点介绍通用部分,即主要的引导加载程序重要功能。有几种开源的通用引导加载程序。以下是最受欢迎的:

如今已成为事实上的标准。我们将详细研究它。

  • Barebox,与体系结构无关的引导程序,是U-Boot的后继产品。它尚不具备U-Boot的硬件支持。U-Boot改善了非常感谢这位竞争对手。

还有很多其他开源或专有的引导程序,通常特定于架构。如RedBoot,Yaboot,PMON等

U-Boot是一个典型的免费软件项目

  • Git存储库中提供了最新的开发源代码:

  • 围绕开放的邮件列表进行开发和讨论,http://lists.denx.de/pipermail/u-boot/自2008年底开始,它遵循固定间隔的发布时间表。两个几个月,发布了新版本。版本名为YYYY.MM。

从网站获取源代码并解压缩。configs/目录为每个受支持的板包含一个配置文件,定义CPU类型,外围设备及其配置,存储器映射,应在其中编译的U-Boot功能等。

并非所有电路板都已转换为新的配置系统。硬件供应商提供的较旧的U-Boot版本可能尚未使用此新版本配置系统。

  • 必须先配置U-Boot,然后再进行编译

  • 确保交叉编译器在PATH中可用

  • 主要结果是一个u-boot.bin文件,它是U-Boot映像。取决于您的特定平台上,可能还有其他专用映像:u-boot.img

通常必须将U-Boot安装在闪存中才能由硬件执行。取决于硬件,U-Boot的安装以不同的方式完成:

  • CPU提供了某种特定的引导监视器,您可以使用特定的协议通过串行端口或USB与之进行通信 

  • 从固定媒体(NAND)引导之前,CPU首先在可移动媒体(MMC)上引导。在这种情况下,请从MMC引导以刷新新版本

  • U-Boot已经安装,可以用来发布新版本的U-Boot。但是请注意:如果新版本的U-Boot无法正常工作,则该主板将无法使用

  • 该评估板提供了一个JTAG接口,该接口允许远程写入闪存,而无需在该评估板上运行任何系统。如果引导加载程序不起作用,它还可以挽救一块板。

通过串行控制台将目标连接到主机。接通电路板电源。在串行控制台上,您将看到类似以下内容:

U-Boot Shell提供了一组命令。本文将研究最重要的内容,请参阅文档以获取完整参考或help命令。

具体的命令集取决于U-Boot配置

  • help命令,将列出该配置的所有命令,help command,将列出具体命令的使用帮助

  • tftp,将文件从网络加载到RAM

  • ping,用于测试网络的物理连通性

  • boot,运行默认的启动命令,存储在bootcmd中

  • ,启动加载到RAM中给定地址的内核映像
  • loadb,加载,加载,将文件从串行线加载到RAM

  • usb,用于初始化和控制USB子系统,主要用于USB存储USB钥匙等设备

  • mmc,用于初始化和控制MMC子系统,用于SD和microSD卡

  • nand,以擦除,读取和写入NAND闪存中的内容

  • md,用于显示内存内容。对检查加载到内存中的内容或查看硬件寄存器很有用。

  • mm,用于修改存储内容。出于测试目的,直接修改硬件寄存器常常在调试阶段很有用。  

  • U-Boot可以通过环境变量进行配置

    1.一些特定的环境变量会影响不同命令的行为

    2.可以添加自定义环境变量,并在脚本中使用

  • 在U-Boot启动时将环境变量从闪存加载到RAM,可以对其进行修改并保存回闪存以实现持久性

  • 闪存(或MMC存储器)中有一个专用位置来存储U-Boot环境,该位置在电路板配置文件中定义

  • saveenv将环境的当前状态保存在闪存中

重要的U-Boot环境变量:

  • bootcmd,指定可配置延迟(bootdelay)后如果引导过程未中断,U-Boot将在引导时自动执行的命令

  • bootargs,包含传递给Linux内核的参数,稍后介绍

  • serverip,U-Boot将与网络相关命令联系的服务器的IP地址

  • netmask,用于与服务器联系的网络掩码

 为实现复杂的启动,环境变量可以包含小脚本,以执行多个命令并测试命令结果。

  • 脚本对于自动启动或升级过程很有用

  • 可使用链接多个命令,使用分号操作符;

U-Boot主要用于加载和引导内核映像,但是它也允许更改内核映像和存储在闪存中的根文件系统。必须在目标和开发工作站之间交换文件。

  • 如果目标设备具有以太网连接,并且U-Boot包含用于以太网芯片的驱动程序,则通过网络。这是最快,最有效的解决方案。

  • 如果U-Boot在使用的平台支持USB控制器,则可以通过U盘

  • 如果U-Boot在使用的平台支持MMC控制器,则可以通过SD卡或microSD卡

  • 通过串口,但一般效率较低

  • 将文件通过TFTP网络从开发工作站(Host)传输到目标机(Target)上的U-Boot。是一种普通文件传输协议,类似于FTP,但是没有身份验证并且采用UDP传输层协议

  • 开发工作站上需要配置TFTP服务器,可参照下列步骤进行配置

    3.tftp-hpa软件包中提供了TFTP客户端,可用于测试

  • TFTP服务器是否搭建成功 TFTP客户端已集成到U-Boot中,通过以下步骤进行配置测试

  Linux 内核 。特定于嵌入式板子的定制内核以及内核的启动参数。
  引导加载程序是系统加电后运行的第一段软件代码。
  回忆一下 PC 的体系结构我们可以知道,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的OS Boot Loader(比如,LILO 和GRUB 等)一起组成。BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 Boot Loader 读到系统的 RAM 中,然后将控制权交给 OS Boot Loader。Boot Loader 的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 Boot Loader 来完成。比如在一个基于 ARM7TDMI core 的嵌入式系统中,系统在上电或复位时通常都从地址0x 处开始执行,而在这个地址处安排的通常就是系统的 Boot Loader 程序。

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

  每种不同的 CPU 体系结构都有不同的 Boot Loader。有些 Boot Loader 也支持多种体系结构的 CPU,比如 U-Boot 就同时支持 ARM 体系结构和MIPS 体系结构。除了依赖于CPU 的体系结构外,BootLoader 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 Boot Loader 程序也能运行在另一块板子上,通常也都需要修改Boot Loader 的源程序。

  系统加电或复位后,所有的 CPU 通常都从某个由 CPU 制造商预先安排的地址上取指令。比如,基于 ARM7TDMI core 的 CPU 在复位时通常都从地址 0x 取它的第一条指令。而基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM 或 FLASH 等)被映射到这个预先安排的地址上。因此在系统加电后,CPU

  主机和目标机之间一般通过串口建立连接,Boot Loader 软件在执行时通常会通过串口来进行 I/O,比如:输出打印信息到串口,从串口读取用户控制字符等。

具体完成哪些任务将在下面讨论。

5. BootLoader 与主机之间进行文件传输所用的通信设备及协议
  最常见的情况就是,目标机上的 Boot Loader 通过串口与主机之间进行文件传输,传输协议通常是 xmodem/ymodem/zmodem 协议中的一种。但是,串口传输的速度是有限的,因此通过以太网连接并借助 TFTP 协议来下载文件是个更好的选择。在讨论了 BootLoader 的上述概念后,下面我们来具体看看 BootLoader 的应该完成哪些任务。

  在继续本节的讨论之前,首先我们做一个假定,那就是:假定内核映像与根文件系统映像都被加载到 RAM 中运行。之所以提出这样一个假设前提是因为,在嵌入式系统中内核映像与根文件系统映像也可以直接在 ROM 或 Flash 这样的固态存储设备中直接运行。但这种做法无疑是以运行速度的牺牲为代价的。
  从操作系统的角度看,Boot Loader 的总目标就是正确地调用内核来执行。另外,由于 Boot Loader 的实现依赖于 CPU 的体系结构,因此大多数 Boot Loader 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。
  而 stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。

  初始化本阶段要使用到的硬件设备。
  将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。
  为内核设置启动参数。
3.1.1基本的硬件初始化
  这是 Boot Loader 一开始就执行的操作,其目的是为 stage2 的执行以及随后的 kernel 的执行准备好一些基本的硬件环境。它通常包括以下步骤(以执行的先后顺序):

  屏蔽所有的中断。为中断提供服务通常是 OS 设备驱动程序的责任,因此在 BootLoader 的执行全过程中可以不必响  应任何中断。中断屏蔽可以通过写CPU 的中断屏蔽寄存器或状态寄存器(比如ARM 的 CPSR 寄存器)来完成。
  设置 CPU 的速度和时钟频率。
  RAM 初始化。包括正确地设置系统的内存控制器的功能寄存器以及各内存库控制寄存器等。
  初始化 LED。典型地,通过 GPIO 来驱动 LED,其目的是表明系统的状态是 OK 还是 Error。如果板子上没有 LED,那么也可以通过初始化 UART 向串口打印 Boot Loader 的 Logo 字符信息来完成这一点。
  为了获得更快的执行速度,通常把 stage2 加载到 RAM 空间中来执行,因此必须为加载Boot Loader 的 stage2 准备好一段可用的 RAM 空间范围。由于 stage2 通常是 C 语言执行代码,因此在考虑空间大小时,除了 stage2 可执行映象的大小外,还必须把堆栈空间也考虑进来。此外,空间大小最好是 memory page 大小(通常是 4KB)的倍数。一般而言,1M的 RAM 空间已经足够了。具体的地址范围可以任意安排,比如 blob 就将它的 stage2 可执行映像安排到从系统 RAM 起始地址 0xc0200000 开始的1M空间内执行。
另外,还必须确保所安排的地址范围的的确确是可读写的 RAM 空间,因此,必须对你所安排的地址范围进行测试。
  具体的测试方法可以采用类似于 blob 的方法,也即:以 memory page 为被测试单位,测试每个 memory page 开始的两个字是否是可读写的。为了后面叙述的方便,我们记这个检测算法为:test_mempage,其具体步骤如下:

  先保存 memory page 一开始两个字的内容。
  向这两个字中写入任意的数字。比如:向第一个字写入 0x55,第 2 个字写入 0xaa。
  然后,立即将这两个字的内容读回。显然,我们读到的内容应该分别是 0x55 和 0xaa。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 RAM 空间。
  再向这两个字中写入任意的数字。比如:向第一个字写入 0xaa,第 2 个字中写入0x55。
然后,立即将这两个字的内容立即读回。显然,我们读到的内容应该分别是 0xaa和 0x55。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 RAM空间。
  恢复这两个字的原始内容。测试完毕。
  为了得到一段干净的 RAM 空间范围,我们也可以将所安排的 RAM 空间范围进行清零操作。

  拷贝时要确定两点:
(1) stage2 的可执行映象在固态存储设备的存放起始地址和终止地址;

  堆栈指针的设置是为了执行 C 语言代码作好准备。通常我们可以把 sp 的值设置为(stage2_end-4),也即在 3.1.2 节所安排的那个 1MB 的 RAM 空间的最顶端(堆栈向下生长)。
  此外,在设置堆栈指针 sp 之前,也可以关闭 led 灯,以提示用户我们准备跳转到 stage2。
  经过上述这些执行步骤后,系统的物理内存布局应该如下图2所示。

  在上述一切都就绪后,就可以跳转到 Boot Loader 的 stage2 去执行了。
  比如,在 ARM 系统中,这可以通过修改 PC 寄存器为合适的地址来实现。

  正如前面所说,stage2 的代码通常用 C 语言来实现,以便于实现更复杂的功能和取得更好的代码可读性和可移植性。
但是与普通 C 语言应用程序不同的是,在编译和链接boot loader 这样的程序时,我们不能使用 glibc 库中的任何支持函数。其原因是显而易见的。这就给我们带来一个问题,那就是从那里跳转进 main() 函数呢?直接把 main() 函数的起始地址作为整个 stage2 执行映像的入口点或许是最直接的想法。但是这样做有两个缺点:
1)无法通过main() 函数传递函数参数;
2)无法处理 main() 函数返回的情况。
一种更为巧妙的方法是利用 trampoline(弹簧床)的概念。也即,用汇编语言写一段trampoline 小程序,并将这段 trampoline 小程序来作为 stage2 可执行映象的执行入口点。然后我们可以在 trampoline 汇编小程序中用 CPU 跳转指令跳入 main() 函数中去执行;而当 main() 函数返回时,CPU 执行路径显然再次回到我们的

可以看出,当 main() 函数返回后,我们又用一条跳转指令重新执行 trampoline 程序,当然也就重新执行 main() 函数,这也就是 trampoline(弹簧床)一词的意思所在。

3.2.1初始化本阶段要使用到的硬件设备
(1)初始化至少一个串口,以便和终端用户进行 I/O 输出信息;
(2)初始化计时器等。
  在初始化这些设备之前,也可以重新把 LED 灯点亮,以表明我们已经进入 main() 函数执行。
  设备初始化完成后,可以输出一些打印信息,程序名字字符串、版本号等。

  所谓内存映射就是指在整个 4GB 物理地址空间中有哪些地址范围被分配用来寻址系统的RAM 单元。
预留的全部 RAM 地址空间。也就是说,具体的嵌入式系统往往只把 CPU 预留的全部 RAM 地址空间中的一部分映射到 RAM 单元上,而让剩下的那部分预留 RAM 地址空间处于未使用状态。
  由于上述这个事实,因此 Boot Loader 的 stage2 必须在它想干点什么 (比如,将存储在 flash 上的内核映像读到 RAM 空间中) 之前检测整个系统的内存映射情况,也即它必须知道CPU 预留的全部 RAM 地址空间中的哪些被真正映射到 RAM 地址单元,哪些是处于 "unused" 状态的。

3.2.3 加载内核映像和根文件系统映像
(1)规划内存占用的布局

  内核映像所占用的内存范围;
  根文件系统所占用的内存范围。
  在规划内存占用的布局时,主要考虑基地址和映像的大小两个方面。
  对于内核映像,一般将其拷贝到从(MEM_START+0x8000) 这个基地址开始的大约1MB大小的内存范围内(嵌入式 Linux 的内核一般都不超过 1MB)。为什么要把从 MEM_START 到MEM_START+0x8000 这段 32KB 大小的内存空出来呢?这是因为 Linux 内核要在这段内存中放置一些全局数据结构,如:启动参数和内核页表等信息。
  而对于根文件系统映像,则一般将其拷贝到 MEM_START+0x 开始的地方。如果用 Ramdisk 作为根文件系统映像,则其解压后的大小一般是1MB。

3.2.4 设置内核的启动参数
  应该说,在将内核映像和根文件系统映像拷贝到 RAM 空间中后,就可以准备启动 Linux 内核了。
  但是在调用内核之前,应该作一步准备工作,即:设置 Linux 内核的启动参数。
  Linux 2.4.x 以后的内核都期望以标记列表(tagged list)的形式来传递启动参数。启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。

注意,内核的根文件系统所在的设备ID就是在这里设置的。

  Boot Loader 调用 Linux 内核的方法是直接跳转到内核的第一条指令处,
  也即直接跳转到 MEM_START+0x8000 地址处。在跳转时,下列条件要满足:

  在 boot loader 程序的设计与实现中,没有什么能够比从串口终端正确地收到打印信息能更令人激动了。此外,向串口终端打印信息也是一个非常重要而又有效的调试手段。但是,我们经常会碰到串口终端显示乱码或根本没有显示的问题。造成这个问题主要有两种原因:

  boot loader 对串口的初始化设置不正确。
  运行在 host 端的终端仿真程序对串口的设置不正确,这包括:波特率、奇偶校验、数据位和停止位等方面的设置。
  此外,有时也会碰到这样的问题,那就是:在 boot loader 的运行过程中我们可以正确地向串口终端输出信息,但当 boot loader 启动内核后却无法看到内核的启动输出信息。对这一问题的原因可以从以下几个方面来考虑:

  首先请确认你的内核在编译时配置了对串口终端的支持,并配置了正确的串口驱动程序。
你的 boot loader 对串口的初始化设置可能会和内核对串口的初始化设置不一致。此外,对于诸如 s3c44b0x 这样的 CPU,CPU 时钟频率的设置也会影响串口,因此如果boot loader 和内核对其 CPU 时钟频率的设置不一致,也会使串口终端无法正确显示信息。
  最后,还要确认 boot loader 所用的内核基地址必须和内核映像在编译时所用的运行基地址一致,尤其是对于 uClinux 而言。假设你的内核映像在编译时用的基地址是0xc0008000,但你的 boot loader 却将它加载到 0xc0010000 处去执行,那么内核映像当然不能正确地执行了。

我要回帖

更多关于 嵌入式为什么要学linux 的文章

 

随机推荐