毛德操《嵌入式系统》读书笔记。
接着第二篇说
1、
与通用计算机系统相比,嵌入式系统中内存的组成与布局更加多样。因为长采用不同质的存储器件,如ROM/RAM等
外设接口的寄存器,按内存统一编址。
2、ARM-Linux内核的代码不应该是专门针对某一种特定系统的,而应该让代码的主体能够适应各种不同的ARM处理器、各种不同的板卡设计的需要。为此就要把与具体系统有关的内容剥离出来,集中在一起,以便替换和更改。剥离出来的总枢纽就是前面提到的“机型描述块”,即machine_desc数据结构。源码如下:
struct machine_desc {
/*
* Note! The first four elements are used
* by assembler code in head-armv.S
*/
unsigned int nr; /* architecture number */
unsigned int phys_ram; /* start of physical ram */
unsigned int phys_io; /* start of physical io */
unsigned int io_pg_offst; /* byte offset for io
* page tabe entry */
const char *name; /* architecture name */
unsigned int param_offset; /* parameter page */
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned int reserve_lp0 :1; /* never has lp0 */
unsigned int reserve_lp1 :1; /* never has lp1 */
unsigned int reserve_lp2 :1; /* never has lp2 */
unsigned int soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,
struct param_struct *, char **,
struct meminfo *);
void (*map_io)(void);/* IO mapping function */
void (*init_irq)(void);
};
代码中为一些常见的机型提供了machine_desc数据结构,而通过条件编译选用具体机型的描述块。
例如:
MACHINE_START(ADSBITSY, "ADS Bitsy")
BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
FIXUP(fixup_adsbitsy)
MAPIO(adsbitsy_map_io)
INITIRQ(adsbitsy_init_irq)
MACHINE_END
这里通过许多宏操作的使用实现了一种描述语言,例如
/*
* Set of macros to define architecture features. This is built into
* a table by the linker.
*/
#define MACHINE_START(_type,_name) \
const struct machine_desc __mach_desc_##_type \
__attribute__((__section__(".arch.info"))) = { \
nr: MACH_TYPE_##_type, \
name: _name,
#define MAPIO(_func) \
map_io: _func,
#define INITIRQ(_func) \
init_irq: _func,
。。。
这样经过预处理,上列的描述块定义就变成了这样:
类似:
3、在此基础上,还需要有“映射描述块”作为补充,这是一个数据结构map_desc的数组,源码如下:
/*
* linux/include/asm-arm/map.h
*
* Copyright (C) 1999-2000 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Page table mapping constructs and function prototypes
*/
struct map_desc {
unsigned long virtual;
unsigned long physical;
unsigned long length;
int domain:4,
prot_read:1,
prot_write:1,
cacheable:1,
bufferable:1,
last:1;
};
每个map_desc数据结构描述了内存地址空间一个区间的映射,包括其虚拟地址、物理地址、区间的长度、所属的域、是否可读/可写、还有是否可以高速缓存、是否可以写缓冲。
例如:
static struct map_desc assabet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
{ 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
{ 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
/* f3000000 - neponset system registers */
/* f4000000 - neponset SA1111 registers */
LAST_DESC
};
物理地址的安排取决于具体机型的电路设计。如果设计了一种新的机型,其电路设计与现存的各种机型不同,那就得为之定义一个新的映射描述块。
那么,这些数据结构怎样发挥作用的呢?特别是,ARM-Linux内核怎样根据这些数据结构建立起地址映射呢?欲知后事如何,且听下回分解!