嵌入式开发基础(2)
一、目标板
在开发机(运行桌面Linux系统)和目标板(嵌入式开发板)之间:
首先通过RS-232串口线进行连接,其次通过以太网连接线进行连接。
通过RS-232串口线进行连接,使用串口通信工具,最常用的是Minicom工具,它对于所有的桌面Linux发布包都有效。
目标板的启动:
1)目标板电源启动,bootloader立即得到处理器的控制。
执行底层硬件初始化,包括:处理器和内存设置、串口UART控制初始化、以太网控制器初始化等。
U-Boot载入
2)引导内核
U-Boot初始化硬件、串口以太网接口,然后U-Boot载入和引导Linux内核。
所有的bootloader都有一个载入和执行操作系统映像的命令。如:
tftpboot 200000 uImage-440ep
tftpboot命令指示U-Boot使用TFTP协议、通过网络载入内核映像uImage-440ep。此情况下,内核映像一般是存储在开发主机上。
3)bootm命令的使用
bootm命令指示U-Boot引导内核。假定内核正确配置,则引导Linux内核的结果是在目标板上提示控制台命令。如:
amcc login: <<< This is a Linux kernel console command prompt
要注意:bootm命令是U-Boot的“丧钟”,使用此命令后,Linux内核将获得控制权,bootloader停止并退出。bootloader要获得控制权的方法是重新启动目标板。
余下的引导信息将由Linux内核产生。U-Boot停止,Linux内核映像接管控制。
4)内核初始化
Linux内核开始执行时,它输出大量的状态信息。比如:
--------------------------------------
...
Looking up port of RPC 100003/2 on 192.168.0.9
Looking up port of RPC 100005/1 on 192.168.0.9
VFS: Mounted root (nfs filesystem).
Freeing init memory: 232K
INIT: version 2.78 booting
...
coyote login:
--------------------------------------
这些信息一般不低于100行。
根文件系统包括应用程序、系统库、建立GNU/Linux系统的工具。
5)第一个用户空间的进程:init
二、嵌入式存储器
大多数Linux嵌入式系统的存储需求为4MB~256MB,但目前有增加到G的趋势。
Flash存储器可通过软件控制写入和擦写,且Flash的写入和擦写速度在不断提高。
典型的Flash存储芯片,数据以0或1按位写入,但是擦写则按块整块擦写。故块经常被称为擦写块。
典型的Flash存储器设备包含许多擦写块,例如4MB的Flash芯片可包含64个擦写快,每个块为64KB。
要修改存储在Flash内存的数据,被修改数据所在的整块都将被擦写,即使只修改1个字节,整块先被擦写,再重写。
与硬盘的扇区相比,Flash的块尺寸相对要大很多。比如说,典型的高性能硬盘的扇区大小一般为512或1024字节。
Flash存储器的写速度比硬盘慢了很多,通常更新数据的时间是硬盘的很多倍。
Flash存储器的另一个限制是Flash存储器单元的写使用期限。尽管Flash的写使用期限次数相当大,每个块100k次,但是一个糟糕的算法可能很快就产生一个坏块。
NAND Flash设备通过提供更小的块尺寸,改进了传统NOR Flash的局限性,使得写速度更快,Flash阵列的使用更富有效率。
NOR Flash设备与微处理器的接口与许多微处理器外设相似,即它们通过一个并行数据和地址总线直接连接到微处理器的数据/地址总线。Flash阵列的每个字节或字都可以随机方式单独寻址。
NAND与之相反,NAND设备通过复杂的接口连续访问,NAND设备操作模式类似于传统硬件驱动和相应控制器的模式。
总的来说,微处理器可直接访问NOR Flash存储器,代码在NOR Flash外执行。
Flash的使用
嵌入式系统设计者有多种方式安排和使用Flash存储器。最简单的系统,原始的二进制数据(通常是压缩的)被存储到Flash设备,当引导时,Flash存储的文件系统映像被读入到Linux的内存设备,作为映射并只在内存访问。
这是很好的设计选择,Flash数据很少需要更新。
Flash存储器安排的例子:
在Flash存储器阵列的顶部或底部时Bootloader和配置,紧接着Bootloader的是Linux内核映像,以及Ramdisk文件系统映像(它存储根文件系统)。代表性地是Linux内核和Ramdisk文件系统映像都是压缩的,Bootloader在引导周期处理解压缩任务。
目前最流行的Flash文件系统是使用JFFS2,它是在闪存上使用非常广泛的读/写文件系统。JFFS2有几个重要特征,目标是改进整体性能,增加Flash的使用寿命,减少因电源故障产生的数据丢失问题。
最新的JFFS2文件系统的重要改进包括改进的磨损平衡,压缩和解压缩数据到指定尺寸的Flash存储器,支持Linux硬连接等。
三、内存空间
所有嵌入式操作系统都把系统内存看作是单一的、扁平的地址空间,并以此进行管理。即微处理器的地址空间的范围从0到最大物理地址。
例如,微处理器有24位地址总线,它的最大内存为16MB。用16进制表示范围为:0x00000000~0x00ffffff。
典型的嵌入式系统内存地址表为:
FFFF_FFFF~FF00_0000 Flash存储器(16MB)
F000_0000 外设基地址
8000_0000 PCI总线地址
03FF_FFFF~0000_0000 DRAM(64MB的内存)
高性能微处理器包含了复杂的硬件引擎,称为MMU(存储管理单元)。MMU的目标是是操作系统能够高度管理和控制它分配的地址空间。此控制有两种基本形式:访问权限(Access Right)和内存转换(Memory Translation)。
访问权限:允许OS为指定任务对指定内存的访问权限进行分配。
内存转换:允许OS虚拟地址空间。
嵌入式风格的Hello World
#include <stdio.h>
int bss_var; /*未初始化的全局变量*/
int data_var=1; /*初始化的全局变量*/
int main(int argc, char **argv)
{
void *stack_var; /*在stack上的局部变量*/
stack_var = (void *)main;
printf("Hello, World! Main is executing at %p\n", stack_var);
printf("This address (%p) is in our stack frame\n", &stack_var);
/*bss节包含未初始化的数据*/
printf("This address (%p) is in our bss section\n", &bss_var);
/*数据节包含已初始化的数据*/
printf("This address (%p) is in our data section\n", &data_var);
return 0;
}
----------------
输出结果:
root@amcc:~# ./hello
Hello, World! Main is executing at 0x10000418
This address (0x7ff8ebb0) is in our stack frame
This address (0x10010a1c) is in our bss section
This address (0x10010a18) is in our data section
root@amcc:~#