近年来,“嵌入式设备”对Linux的采用越来越多。
Linux标准拥有的许多功能都符合嵌入式产品的目的,这是最大的原因。
安装在嵌入式设备上的Linux通常被称为“嵌入式Linux”,并使用与传统PC上运行的Linux不同的表达式。
但是,Linux和嵌入式Linux没有明显的区别也是事实,在某种程度上环境完备的状态的话,特别是意识不到嵌入式Linux的软件开发可能。
但是,从环境整备没有实现的状态开始开发嵌入式Linux,必须把握嵌入式这个词的意思。
“交叉开发”,这是嵌入式开发的基本方法。
自助开发:开发环境和执行环境相同。
交叉开发:开发环境和执行环境不同。
也就是说,在PC世界中,使用Visual C++等开发PC应用程序的形式是自我开发。另一方面,交叉开发意味着在另一个设备(其他架构)上运行创建的可执行文件。
那么,为什么在嵌入式开发中交叉开发是基本方法呢?最大的原因是执行环境中的处理器(CPU)和操作系统是不同的。如你所知,Windows可执行文件不会在Linux上运行(操作系统不同)。即使在相同的Linux应用程序中,PC/AT兼容机的可执行文件也不会在Macintosh(编注)上运行(CPU不同)。在不同的环境中运行软件需要相应的工作。嵌入式设备使用各种CPU和操作系统,因此交叉开发势在必行。
Macintosh是苹果公司开发和销售的PC的品牌名称。
1984年第一台机器发布。通常被称为“Mac”。
另外,嵌入式设备的CPU功率和内存安装量等资源有限,很多情况下不可能像PC这样的开发方法。在可以使用相对较多资源的PC和工作站上开发,可以缩短编译时间,高效。
在嵌入式开发中,出现了PC软件开发中不常用的独特术语。在了解交叉开发的地方,也请记住其他的关键词。
指的是实际创建程序的PC。
指嵌入式设备。在交叉开发中运行创建的可执行文件的环境。
交叉编译器/汇编程序/链接器用于编译所创建的程序(主要以C语言等编写)为目标。
在用术语3中所示的工具编译程序时,需要交叉库。例如,如果您创建了hello.c,那么如果您认为其中使用的printf()本身是存储的,那么就很容易理解了。
如果您准确地描述交叉库,您将为目标操作系统提供两个交叉库和一个独立于OS的交叉库。存储在库中的许多函数都是通过结合操作系统的功能来实现的。要连接到OS本身的库和稍后将描述的引导加载器使用OS独立交叉库。
虽然实际创建的可执行文件将直接在目标上运行,但是如果有调试器来查明问题的原因,这是非常有用的。
除此之外,关于交叉开发的关键词有很多,经常使用的是上述的5个左右吧。
那么,让我们来看看实际嵌入式Linux的开发步骤。
首先要做的是开发引导加载程序来在目标上运行Linux本身。内置领域的引导加载程序相当于PC/AT兼容机的BIOS(编注)。
PC世界中使用的“引导加载程序”通常被写入MBR中,通常指的是BIOS调用的程序。LILO、GRUB、Windows的OS Loader等很有名。
引导加载程序的作用是随着设备的打开,从任意位置取出内核映像,并将其部署到目标内存中并运行。
我们没有安排这个“任何地方”,但大多数设备都使用闪存ROM等作为内存。
因此,为了维护等,除了原来的功能以外,还可以编入对ROM的程序写入功能等。
引导加载程序的实际开发主要是使用嵌入式软件开发专用设备的方法,例如电路模拟器(ICE)和JTAG模拟器。
以这种方式做的原因只是因为目标尚未实现软件,所以没有其他方法。
但是,从无状态开始开发引导加载程序的情况很少。
因为存在开源的引导加载程序,所以参考它们来开发是捷径。
另外,由于市售的单板计算机大多实现了引导加载功能,所以需要开发引导加载程序的只有自己制作目标板本身的情况。
在引导加载程序之后,它将是Linux的内核实现。
*注:
对于x86 CPU,用于控制设备的寄存器由端口号管理,并且可以通过读/写端口号来控制设备。
在其他CPU中,寄存器直接部署到内存中,因此通过读取和写入特定地址来实现设备控制。
这种内存分配有不同的情况,例如盲目(针对每个目标)确定,或者由内存管理机制软件式确定的情况下,等等。
注:printf()和printk()。
对于printf()和printk(),我想大多数人都理解它只是使用的地方和目的是不同的函数,但是很少有人知道它的内容完全不同。
printf()顾名思义,是为标准输出输出字符串的函数,是操作系统支持功能的一部分。
printk()与printf()完全不同,其函数的内容是直接操作硬件输出字符串的结构。
因为printk()用于在任何状态下显示字符串,并将其作为解决问题的线索。
也就是说,如果printk()需要OS(Linux),也就是说,如果内核本身没有开始操作,它就不能使用了,但是它会导致内核准备工作的消息消失。
因此,printk()根据需要直接控制硬件来显示字符串。
内核实现完成后,您将创建当前所需的驱动程序。
作为这个阶段的基本流程,这将是“尝试创建模块并尝试动作”的踏实工作的重复。
如果目标有可移动存储设备,建议您优先创建驱动程序。
我想如果你想起内核实现的故事,我会知道原因。
因为最初是只安装RAM盘,所以这样的话只需要一个模块的执行,
模块创建(文件创建)
↓↓。
RAM磁盘内容更改。
↓↓。
内核重新构建(带有RAM磁盘映像)。
↓↓。
目标重新启动(内核重新传输/执行)。
↓↓。
模块动作;模块动作。
这是一个非常长的步骤。如果您可以使用可移动存储,则只能实现模块的替换。
内核和模块的创建完成后,就是应用程序的开发。
关于这个也有各种各样的步骤。
基本上和模块开发一样,
制作。
↓↓。
转移到目标。
↓↓。
实行。
这就是说,这种方法大致分为以下两种类型
即使以上的开发工作结束了,也只是简单地做好了动作,要想完成的话,就是稍微快一点的状态。
这是因为这一点只是在原型机环境中运行,并不是在应该作为产品的状态下运行的。
那么,在什么样的状态下才能说完成了呢?
根据产品的不同,“完成”的定义千差万别,但最重要的是文件大小是否在规定范围内,应该运行的程序是否自动启动等。
文件大小非常重要,因为它会影响硬件的大小。
检查内核,每个模块,应用程序等文件大小以及磁盘的可用空间。
如果这些不在规定范围内,则更改程序的编译选项等,进行调整大小等作业。
这一次,描述了嵌入式Linux开发的整体情况。如有不足或错误,请告知我,谢谢。