一个项目中用到了nandflash,开始的时候,没有用文件系统的打算,就在代码中直接操作nandflash,后来由于项目的变动,时间比较充足,就萌生了移植文件系统的想法。yaffs2就进入了我的视野,下面就对我在移植yaffs文件的过程进行总结。
1、在yaffs官方主页上,看了三个文档,分别是
How Yaffs Works,
The Yaffs Direct Interface, 。在yaffs port Guide文件中有一个简历环境的描述,这样来确定用yaffs文件包中那些文件会被用到。个人觉得,这部分需要一些花费一些精力。我已经将这个文件包抽取出来,保存到一个目录中,可以直接使用,文件包在下载目录中。
2、调试部分,在调试之前你必须要有一个稳定的硬件环境,尤其是SDRAM,我的调试时间,基本上是花在了调试SDRAM上,这也是我之前对硬件调试不认真造成的,就是LPC4088出来的DQM脚和SDRAM的DQM脚接反了。在写8位数据的时候,其实修改的是16位的数据,造成一部分数据莫名其妙的被修改了。当时我一直怀疑是SDRAM的时序问题。所以花费了很多时间,不能解决这个问题。这个问题的表现是“发现yaffs的bug”。之后我只好认认真真的看数据手册,于是我感觉可能是DQM这块有问题。后来发现确实有问题。
另外一个问题是编译器的问题,就是对位域的处理,我用的keil4.72编译的。在yaffsfs.c中第920行一个循环中,如代码:
-
for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
-
fdx = &yaffsfs_fd[i];
-
tmp = fdx->inodeId; //
-
if (tmp == 0xFFF)
-
tmp = -1;
-
if (fdx->handleCount > 0 &&
-
/*fdx->inodeId*/tmp >= 0 &&
-
yaffsfs_inode[fdx->inodeId].iObj
-
== obj) {
-
if (!fdx->shareRead)
-
sharedReadAllowed = 0;
-
if (!fdx->shareWrite)
-
sharedWriteAllowed = 0;
-
if (fdx->reading)
-
alreadyReading = 1;
-
if (fdx->writing)
-
alreadyWriting = 1;
-
}
-
}
其中fdx->inodeId是一个12bit的变量,它最初被复制为-1,也就是0xFFF,但是keil4.72下,图中代码第6行被作为了一个整形无符号数来处理。因此我改动了这部分代码,4-7行。增加了一个变量。
3、与flash的接口,主要集中在yaffs_nand_drv.c中,只要填充下面这个函数即可:
-
struct yaffs_dev *yflash2_install_drv( char *name, int start_b, int end_b)
-
{
-
struct yaffs_dev *dev = NULL;
-
struct yaffs_param *param;
-
struct yaffs_driver *drv;
-
struct yaffs_tags_handler *tag;
-
char* name_copy = NULL;
-
-
dev = malloc(sizeof(*dev));
-
-
if(!dev)
-
return NULL;
-
-
param = &dev->param;
-
memset(dev, 0, sizeof(*dev));
-
-
name_copy = strdup(name);
-
param->name=name_copy;
-
-
if(!param->name||!dev)
-
{
-
free(dev);
-
free(name_copy);
-
return NULL;
-
}
-
-
drv = &dev->drv;
-
-
drv->drv_write_chunk_fn = yaffs_nand_drv_WriteChunk;
-
drv->drv_read_chunk_fn = yaffs_nand_drv_ReadChunk;
-
drv->drv_erase_fn = yaffs_nand_drv_EraseBlock;
-
drv->drv_mark_bad_fn = yaffs_nand_drv_MarkBad;
-
drv->drv_check_bad_fn = yaffs_nand_drv_CheckBad;
-
drv->drv_initialise_fn = yaffs_nand_drv_Initialise;
-
drv->drv_deinitialise_fn = yaffs_nand_drv_Deinitialise;
-
dev->driver_context = (void *) 1;
-
-
-
param->total_bytes_per_chunk = 2048;
-
param->chunks_per_block = 64;
-
param->spare_bytes_per_chunk = 64;
-
param->start_block = start_b;
-
param->end_block = end_b;
-
param->is_yaffs2 = 1;
-
param->use_nand_ecc = 0;
-
-
param->n_reserved_blocks = 10;
-
param->wide_tnodes_disabled = 0;
-
param->refresh_period = 1000;
-
param->n_caches = 5; // Use caches
-
-
param->enable_xattr = 10;
-
-
tag = &dev->tagger;
-
-
-
-
yaffs_add_device(dev);
-
-
-
return dev;
-
}
从28行到36行,就是flash的接口函数,yaffs就是通过这些接口来操作nand,39到45行时根据flash的规格和你对flash的分区来设定。
4、用户接口部分
在使用之前yaffs之前,先要调用int yaffs_start_up(void)函数,部分我也做了修改,我是将flash分成2个分区,我的flash的总共有1024个块。第一分区是sys分区,从0-255块,共256块。第二分区是user分区,除第一分区之外的剩余块,即从256-1023块,代码如下:
-
int yaffs_start_up(void)
-
{
-
static int start_up_called = 0;
-
-
if(start_up_called)
-
return 0;
-
start_up_called = 1;
-
-
/* Call the OS initialisation (eg. set up lock semaphore */
-
yaffsfs_OSInitialisation();
-
if (yflash2_install_drv("/sys", 0, 255) == NULL) //32M size
-
return YAFFS_FAIL;
-
if (yflash2_install_drv("/user", 256, 1023) == NULL) //86M size
-
return YAFFS_FAIL;
-
-
-
return YAFFS_OK;
-
}
这部分代码在yaffscfg2k.c中。
在此之后,就可以mount分区,进行读写等文件操作了。
5、参考代码,
yaffs2文件包,后续会提供一个keil的工程,包含yaffs,并将yaffs文件包单独出来。keil工程是针对lpc4088的。后续会提供stm32的包。目前这部分还需要整理。
下载地址
阅读(3323) | 评论(0) | 转发(0) |