您的位置:控制工程论坛网论坛 » 自动化软件 » 嵌入式设备上的 Linux 系统开发 (2)

szzunzheng

szzunzheng   |   当前状态:离线

总积分:180  2024年可用积分:0

注册时间: 2007-06-06

最后登录时间: 2009-10-12

空间 发短消息加为好友

嵌入式设备上的 Linux 系统开发 (2)

szzunzheng  发表于 2007/11/11 19:50:33      938 查看 2 回复  [上一主题]  [下一主题]

手机阅读

LMA 是装入模块地址;它表示将要装入内核的目标虚拟内存中的地址。TEXTADDR 是内核的虚拟起始地址,并且在 arch/<target>/ 下的 Makefile 中指定它的值。这个地址必须与引导装载程序使用的地址相匹配。 
一旦引导装载程序将内核复制到闪存或 DRAM 中,内核就被重新定位到 TEXTADDR — 它通常在 DRAM 中。然后,引导装载程序将控制转给这个地址,以便内核能开始执行。
参数传递和内核引导
stext 是内核入口点,这意味着在内核引导时将首先执行这一节下的代码。它通常用汇编语言编写,并且通常它在 arch/<target>/ 内核目录下。这个代码设置内核页面目录、创建身份内核映射、标识体系结构和处理器以及执行分支 start_kernel(初始化系统的主例程)。
start_kernel 调用 setup_arch 作为执行的第一步,在其中完成特定于体系结构的设置。这包括初始化硬件寄存器、标识根设备和系统中可用的 DRAM 和闪存的数量、指定系统中可用页面的数目、文件系统大小等等。所有这些信息都以参数形式从引导装载程序传递到内核。
将参数从引导装载程序传递到内核有两种方法:parameter_structure 和标记列表。在这两种方法中,不赞成使用参数结构,因为它强加了限制:指定在内存中,每个参数必须位于 param_struct 中的特定偏移量处。最新的内核期望参数作为标记列表的格式来传递,并将参数转化为已标记格式。param_struct 定义在 include/asm/setup.h 中。它的一些重要字段是:
清单 3. 样本参数结构 struct param_struct  { 
  unsigned long page_size;     /* 0:  Size of the page  */ 
  unsigned long nr_pages;      /* 4:  Number of pages in the system */ 
  unsigned long ramdisk        /* 8: ramdisk size */ 
  unsigned long rootdev;       /* 16: Number representing the root device */ 
  unsigned long initrd_start;  /* 64: starting address of initial ramdisk */
                                      /* This can be either in flash/dram */ 
  unsigned long initrd_size;   /* 68: size of initial ramdisk */ 
 }
请注意:这些数表示定义字段的参数结构中的偏移量。这意味着如果引导装载程序将参数结构放置在地址 0xc0000100,那么 rootdev 参数将放置在 0xc0000100 + 16,initrd_start 将放置在 0xc0000100 + 64 等等 — 否则,内核将在解释正确的参数时遇到困难。
正如上面提到的,因为从引导装载程序到内核的参数传递会有一些约束条件,所以大多数 2.4.x 系列内核期望参数以已标记的列表格式传递。在已标记的列表中,每个标记由标识被传递参数的 tag_header 以及其后的参数值组成。标记列表中标记的常规格式可以如下所示:
清单 4. 样本标记格式。内核通过 <ATAG_TAGNAME> 头来标识每个标记。 #define <aTAG_TAGNAME>  <Some Magic number> 
 struct <tag_tagname> { 
         u32 <tag_param>; 
         u32 <tag_param>; 
 }; 
 /* Example tag for passing memory information */ 
 #define ATAG_MEM        0x54410002  /* Magic number */ 
 struct tag_mem32 { 
         u32     size;               /* size of memory */ 
         u32     start;              /* physical start address of memory*/ 
 }; 
setup_arch 还需要对闪存存储库、系统寄存器和其它特定设备执行内存映射。一旦完成了特定于体系结构的设置,控制就返回到初始化系统其余部分的 start_kernel 函数。这些附加的初始化任务包含:
设置陷阱 
初始化中断 
初始化计时器 
初始化控制台 
调用 mem_init,它计算各种区域、高内存区等内的页面数量 
初始化 slab 分配器并为 VFS、缓冲区高速缓存等创建 slab 高速缓存 
建立各种文件系统,如 proc、ext2 和 JFFS2 
创建 kernel_thread,它执行文件系统中的 init 命令并显示 lign 提示符。 如果在 /bin、/sbin 或 /etc 中没有 init 程序,那么内核将执行文件系统的 /bin 中的 shell。
设备驱动程序
嵌入式系统通常有许多设备用于与用户交互,象触摸屏、小键盘、滚动轮、传感器、RA232 接口、LCD 等等。除了这些设备外,还有许多其它专用设备,包括闪存、USB、GSM 等。内核通过所有这些设备各自的设备驱动程序来控制它们,包括 GUI 用户应用程序也通过访问这些驱动程序来访问设备。本节着重讨论通常几乎在每个嵌入式环境中都会使用的一些重要设备的设备驱动程序。
帧缓冲区驱动程序
这是最重要的驱动程序之一,因为通过这个驱动程序才能使系统屏幕显示内容。帧缓冲区驱动程序通常有三层。最底层是基本控制台驱动程序 drivers/char/console.c,它提供了文本控制台常规接口的一部分。通过使用控制台驱动程序函数,我们能将文本打印到屏幕上 — 但图形或动画还不能(这样做需要使用视频模式功能,通常出现在中间层,也就是 drivers/video/fbcon.c 中)。这个第二层驱动程序提供了视频模式中绘图的常规接口。
帧缓冲区是显卡上的内存,需要将它内存映射到用户空间以便可以将图形和文本能写到这个内存段上:然后这个信息将反映到屏幕上。帧缓冲区支持提高了绘图的速度和整体性能。这也是顶层驱动程序引人注意之处:顶层是非常特定于硬件的驱动程序,它需要支持显卡不同的硬件方面 — 象启用/禁用显卡控制器、深度和模式的支持以及调色板等。所有这三层都相互依赖以实现正确的视频功能。与帧缓冲区有关的设备是 /dev/fb0(主设备号 29,次设备号 0)。
输入设备驱动程序
可触摸板是用于嵌入式设备的最基本的用户交互设备之一 — 小键盘、传感器和滚动轮也包含在许多不同设备中以用于不同的用途。
触摸板设备的主要功能是随时报告用户的触摸,并标识触摸的坐标。这通常在每次发生触摸时,通过生成一个中断来实现。
然后,这个设备驱动程序的角色是每当出现中断时就查询触摸屏控制器,并请求控制器发送触摸的坐标。一旦驱动程序接收到坐标,它就将有关触摸和任何可用数据的信号发送给用户应用程序,并将数据发送给应用程序(如果可能的话)。然后用户应用程序根据它的需要处理数据。
几乎所有输入设备 — 包括小键盘 — 都以类似原理工作。
闪存 MTD 驱动程序
MTD 设备是象闪存芯片、小型闪存卡、记忆棒等之类的设备,它们在嵌入式设备中的使用正在不断增长。
MTD 驱动程序是在 Linux 下专门为嵌入式环境开发的新的一类驱动程序。相对于常规块设备驱动程序,使用 MTD 驱动程序的主要优点在于 MTD 驱动程序是专门为基于闪存的设备所设计的,所以它们通常有更好的支持、更好的管理和基于扇区的擦除和读写操作的更好的接口。Linux 下的 MTD 驱动程序接口被划分为两类模块:用户模块和硬件模块。
用户模块
这些模块提供从用户空间直接使用的接口:原始字符访问、原始块访问、FTL(闪存转换层,Flash Transition Layer — 用在闪存上的一种文件系统)和 JFS(即日志文件系统,Journaled File System — 在闪存上直接提供文件系统而不是模拟块设备)。用于闪存的 JFS 的当前版本是 JFFS2(稍后将在本文中描述)。
硬件模块
这些模块提供对内存设备的物理访问,但并不直接使用它们。通过上述的用户模块来访问它们。这些模块提供了在闪存上读、擦除和写操作的实际例程。
MTD 驱动程序设置
为了访问特定的闪存设备并将文件系统置于其上,需要将 MTD 子系统编译到内核中。这包括选择适当的 MTD 硬件和用户模块。当前,MTD 子系统支持为数众多的闪存设备 — 并且有越来越多的驱动程序正被添加进来以用于不同的闪存芯片。
1楼 0 0 回复
总共 , 当前 /