atheros之flash驱动程序分析

来源:互联网 发布:java的编译器是什么 编辑:程序博客网 时间:2024/03/29 15:35

1:uboot中的参数mtkparts

在uboot的bootargs的参数设置如下:其中mtdparts=“”的内容会传递给内核进行解析。
即:


在linux内核文件Cmdlinepart.c打开调试信息:即:

/* debug macro */
#if 1 //更改为1,将打开调试信息
#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
#else
#define dbg(x) printk(x)
#endif
同时此文件中有如下的定义:
static int mtdpart_setup(char *s)
{
cmdline = s;
printk("mtdpart_setup:%s\n",cmdline);
return 1;
}
__setup("mtdparts=", mtdpart_setup);
上面的__setup()函数就是将"mtdparts="传递给mtdpart_setup()函数来进行处理。
系统启动时的打印信息为:
mtdpart_setup:ar7240-nor0:256k(u-boot),64k(u-boot-env),1088k(uImage),14336k(rootfs),256k(NVRAM),256k(ART)


定义解析器cmdline_parser,其解析的字符串对象为:"cmdlinepart"
static struct mtd_part_parser cmdline_parser = {
.owner = THIS_MODULE,
.parse_fn = parse_cmdline_partitions,
.name = "cmdlinepart",
};
static int __init cmdline_parser_init(void)
{
return register_mtd_parser(&cmdline_parser);
}
上面为:将定义的cmdline_parser添加到系统中。

2:ar7240_flash.c文件分析

/*
 * sets up flash_info and returns size of FLASH (bytes)
 */
static int __init ar7240_flash_init(void)
{
int i, np;
ar7240_flash_geom_t *geom;
struct mtd_info *mtd;
struct mtd_partition *mtd_parts;
uint8_t index;


init_MUTEX(&ar7240_flash_sem);


#if defined(ATH_SST_FLASH)
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x3);
ar7240_spi_flash_unblock();
ar7240_reg_wr(AR7240_SPI_FS, 0);
#else
#ifndef CONFIG_WASP_SUPPORT
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x43);
#endif
#endif
for (i = 0; i < AR7240_FLASH_MAX_BANKS; i++) {


index = ar7240_flash_probe();
geom = &flash_geom_tbl[index];


/* set flash size to value from bootloader if it passed valid value */
/* otherwise use the default 4MB.                                   */
if (__ath_flash_size >= 4 && __ath_flash_size <= 16)
geom->size = __ath_flash_size * 1024 * 1024;


mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
if (!mtd) {
printk("Cant allocate mtd stuff\n");
return -1;
}
memset(mtd, 0, sizeof(struct mtd_info));


mtd->name = AR7240_FLASH_NAME;
mtd->type = MTD_NORFLASH;
mtd->flags = MTD_CAP_NORFLASH | MTD_WRITEABLE;
mtd->size = geom->size;
mtd->erasesize= geom->sector_size;
mtd->numeraseregions= 0;
mtd->eraseregions= NULL;
mtd->owner = THIS_MODULE;
mtd->erase = ar7240_flash_erase;
mtd->read = ar7240_flash_read;
mtd->write = ar7240_flash_write;
mtd->writesize= 1;
np = parse_mtd_partitions(mtd, part_probes, &mtd_parts, 0);
if (np > 0) {
add_mtd_partitions(mtd, mtd_parts, np);
} else {
printk("No partitions found on flash bank %d\n", i);
}
}
return 0;
}
在上面的函数中:主要是解析mtdparts参数,将解析的每一个mtd_parts添加到系统中去。其中
mtd->erase = ar7240_flash_erase;
mtd->read = ar7240_flash_read;
mtd->write = ar7240_flash_write;
为nor flash的读写和察除函数。同时part_probes定义为:
static const char *part_probes[] __initdata = { "cmdlinepart", "RedBoot", NULL };
其中"cmdlinepart"和前面定义的便利cmdline_parser中的.name字段的定义相同。
函数parse_mtd_partitions()定义如下:
int parse_mtd_partitions(struct mtd_info *master, const char **types,
struct mtd_partition **pparts, unsigned long origin)
{
struct mtd_part_parser *parser;
int ret = 0;
for ( ; ret <= 0 && *types; types++) {
parser = get_partition_parser(*types);//根据第一个type即"cmdlinepart"参数找到对应的struct mtd_part_parser
if (!parser && !request_module("%s", *types))
parser = get_partition_parser(*types);
if (!parser) {
printk(KERN_NOTICE "%s partition parsing not available\n",
      *types);
continue;
}
//其中 (*parser->parse_fn)就是前面定义的cmdline_parser变量中的parse_cmdline_partitions函数。
ret = (*parser->parse_fn)(master, pparts, origin);
if (ret > 0) {
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
      ret, parser->name, master->name);
}
put_partition_parser(parser);
}
return ret;
}
函数add_mtd_partitions()定义如下:
int add_mtd_partitions(struct mtd_info *master,const struct mtd_partition *parts,int nbparts)
{
struct mtd_part *slave;
uint64_t cur_offset = 0;
int i;
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);


for (i = 0; i < nbparts; i++) {
slave = add_one_partition(master, parts + i, i, cur_offset);
if (!slave)
return -ENOMEM;
cur_offset = slave->offset + slave->mtd.size;
}
return 0;
}
在执行上面的函数时的打印信息如下:可以看出在使用add_one_partition()函数添加分区。
6 cmdlinepart partitions found on MTD device ar7240-nor0
Creating 6 MTD partitions on "ar7240-nor0":
0x000000000000-0x000000040000 : "u-boot"
mtd:-----  mtd0ro 
mtd: Giving out device 0 to u-boot
0x000000040000-0x000000050000 : "u-boot-env"
mtd:-----  mtd1ro 
mtd: Giving out device 1 to u-boot-env
0x000000050000-0x000000160000 : "uImage"
mtd:-----  mtd2ro 
mtd: Giving out device 2 to uImage
0x000000160000-0x000000f60000 : "rootfs"
mtd:-----  mtd3ro 
mtd: Giving out device 3 to rootfs
0x000000f60000-0x000000fa0000 : "NVRAM"
mtd:-----  mtd4ro 
mtd: Giving out device 4 to NVRAM
0x000000fa0000-0x000000fe0000 : "ART"
mtd:-----  mtd5ro 
mtd: Giving out device 5 to ART
同时在看看/dev目录下面的设备:


上面的显示中视乎少了一些主设备号为:90的MTD设备。主要是因为在atheros的SDK是手动建立的
dev设备而不是根据sys文件系统来自动生成的。其手动建立使用的脚本为:


但是可以看看mini2440板子上面的mtd设备



3:总结:

跟mini2440相比,上面的flash初始化过程相对来说简单明了。
主要主城如下:
A:定义变量struct mtd_info *mtd,struct mtd_partition *mtd_parts;
B:对mtd的主要成员函数定义赋值,包括:read,wirte,earse。
C:解析uboot中定义的变量:mtdparts=ar7240-nor0:256k(u-boot),64k(u-boot-env),1088k(uImage),14336k(rootfs),256k(NVRAM),256k(ART)
D:将解析的变量从放到定义的mtd_parts变量中。
E:调用函数add_mtd_partitions()添加各个分区。
顺便记录一个linux内核DUG()函数的定义:
static void dbg(const char *fmt, ...)
{
va_list va;
char buff[256];
va_start(va, fmt);
vsprintf(buff, fmt, va);
va_end(va);
printk(buff);
}

原创粉丝点击