Chinaunix首页 | 论坛 | 博客
  • 博客访问: 195859
  • 博文数量: 71
  • 博客积分: 3000
  • 博客等级: 中校
  • 技术积分: 450
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-29 21:28
个人简介

思考人生、专注技术

文章分类

全部博文(71)

文章存档

2015年(1)

2009年(2)

2008年(11)

2007年(57)

我的朋友

分类: C/C++

2007-12-11 15:47:04

堆空间管理:
vivi中动态内存是通过函数void *mmalloc(unsigned long size)来分配的,调用此函数时,堆空间已经被初始化了,通过调用函数
int heap_init(void)
{
 return mmalloc_init((unsigned char *)(HEAP_BASE), HEAP_SIZE); 
}
将类型为
typedef struct blockhead_t {
 Int32 signature;
 Bool allocated;
 unsigned long size;
 struct blockhead_t *next;
 struct blockhead_t *prev;
} blockhead
的静态全局变量指针gHeapBase指向HEAP_BASE,即RAM中划分的堆空间开始地址,其中Bool allocated是内存是否被分配的标志。
当我们首次调用mmalloc分配内存时,就是从gHeapBase指向的堆空间中分割一段内存,大小为sizeof(blockhead)+size,并将allocated赋值为TRUE,表示已被占用,然后将剩余的内存再次作为blockhead类型链接在其后,即使结构体next指针指向其开始的位置,形成一个链表。以后再调用mmalloc时,需要从gHeapBase开始查询此链表,直到找到一个节点,其allocated为FALSE并且大小大于等于sizeof(blockhead)+size即可。链表中的空闲节点,是调用mfree函数释放内存的缘故。
 
NandFlash驱动:
vivi采用简化的MTD技术,MTD是用于访问memory设备(ROM、Flash)的Linux子系统,主要目的是为了使新的memory设备的驱动更加简单,它在硬件和上层之间提供了一个抽象的接口。
以CONFIG_MTD_SMC为例,调用smc_init实现mtd设备的初始化,这里涉及三个结构体变量,分别为mtd_info、nand_chip、nand_flash_dev类型的变量。首先为struct mtd_info *mymtd分配空间,并将mymtd->priv指向nand_chip结构体变量,通过这个指针,给结构体内的函数指针赋值,而这些函数通过一系列宏调用设置S3C2410芯片内和NandFlash读写等动作相关的寄存器。如this->write_data = write_data,而write_data函数为:
static void
write_data(u_char val)
{
 NFDATA = (u_char)val;
}
其中NFDATA是S3C2410中地址为0X4E00000C的寄存器,为可读写的NandFlash数据寄存器。
然后调用smc_insert,调用smc_scan,实现功能:调用nand_select宏实现NandFlash的复位,读取device ID,通过device ID查询nand_flash_dev数组nand_flash_ids[],找到NandFlash型号,完成mtd其它一些变量的赋值,包括驱动函数的加载,如:mtd->read = nand_read。
如此,以后涉及NandFlash读写等操作时,只需调用mtd结构体下的成员变量即可。

vivi命令:
vivi每一个命令都是一个结构体变量:
typedef struct user_command {
    const char *name;
    void (*cmdfunc)(int argc, const char **);
    struct user_command *next_cmd;
    const char *helpstr;
} user_command_t
例如:boot命令
user_command_t boot_cmd = {
    "boot",
    command_boot,
    NULL,
    "boot [{cmds}] \t\t\t-- Booting linux kernel"
}
vivi 的main函数通过调用misc()及init_buildin_cmds()将许多命令结构体形成一个链表,以全局变量head_cmd为头节点。执行 命令时,vivi_shell()调用串口终端函数serial_term(),首先通过getcmd()函数获取PC串口终端中的命令及参数,再调用函 数parseargs()解析输入的命令,然后调用execcmd()查找相应的函数
void (*cmdfunc)(int argc, const char **)执行。
添加自己的命令时注意,执行函数
void (*cmdfunc)(int argc, const char *argv[])时,其参数argc、argv是由串口接收缓冲区的内容(即PC串口终端输入的字符)经过函数parseargs()转换而来,argv[0]指向输入的命令字符(如“boot”),argv[1]及其以后才是真正的参数。

linux加载:
调 用exec_string("boot"),找到command_boot函数后执行,找到mtd_partition_t *kernel_part后,调用boot_kernel()完成kernel的拷贝和启动参数struct param_struct *params = (struct param_struct *)param_base的设置。再调用call_linux(),通过mov    pc, r2完成跳转。

阅读(1218) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~