介绍下当下状况,ucosii操作系统已移植到lpc3250上了,现在需要把yaffs文件系统和nandflash驱动移植到lpc3250上去。
Yaffs文件系统对操作系统提供的接口很简单就是几个互斥的函数,实现了这几个函数,与操作系统相关的就不用管了。
其实现在Yaffscfg2k.c中:
定义两个全局变量
static OS_EVENT * g_hFSEvent = NULL;
static int gs_nyaffsLockcnt = 0; //这里可以不用这个东西
//初始化互斥量事件
int yaffs_InitEvent(void)
{
unsigned char err;
#ifndef WIN32
if (g_hFSEvent == NULL)
{
g_hFSEvent = OSMutexCreate(15, &err);
if (g_hFSEvent == 0)
{
UART_Printf(2, "OSMboxCreate error\r\n");
}
if (err != OS_NO_ERR)
{
}
}
#endif
return 0;
}
//上锁
void yaffsfs_Lock(void)
{
unsigned char err;
//OSMboxPend(g_hFSEvent,(0),NULL);
OSMutexPend(g_hFSEvent,(0),&err);
if (err != OS_NO_ERR)
{
}
gs_nyaffsLockcnt++;
}
//解锁
void yaffsfs_Unlock(void)
{
#ifndef WIN32
//OSMboxPost(g_hFSEvent, (void*)1);
OSMutexPost(g_hFSEvent);
#endif
gs_nyaffsLockcnt--;
}
这样操作系统这边的事就摆平了。
Yaffs文件系统提供给nandflash的接口主要是填写nandflash相关信息,yaffs文件管理的区域结构体ST_FLASH_TYPE,之后只需要实现yaffs_startup函数就完了。Yaffs文件系统的操作函数不直接操作与flash驱动函数接头,而是通过函数指针实现的,yaffs_Device结构体中定义了操作函数相关的函数指针,这些函数指针时在yaffs_startup函数中填充的。
在Yaffscfg2k.c中如下实现:
//NandFlash的参数信息
#define NF_PAGE_DATA_BYTES (2048) //每个页的数据区大小
#define NF_PAGE_SPARE_BYTES (64) //每个页的备用区大小
#define NF_PAGES_PER_BLOCK (64) //每个块包含的页个数
#define NF_BLOCKS (512) //包含的Block个数
#define NF_BOOT_BLOCKS (256) //boot区 的BLOCK个数,约32M
#define NF_DATA_BLOCKS (NF_BLOCKS - NF_BOOT_BLOCKS) //data区的BLOCK个数,约223M
static yaffs_Device gst_dev_boot; //boot区
static yaffs_Device gst_dev_data; //data区
static yaffs_Device gst_dev_app; //app区
static yaffsfs_DeviceConfiguration yaffsfs_config[] =
{
{ "/boot", &gst_dev_boot},
{ "/data", &gst_dev_data},
{(void *)0,(void *)0} /* Null entry to terminate list */
};
下面是关于yaffs_startup函数的实现:
int yaffs_startup(ST_FLASH_TYPE *pstFlashType)
{
HAL_NandInit(NULL);
// Stuff to configure YAFFS
// Stuff to initialise anything special (eg lock semaphore).
yaffsfs_LocalInitialisation(); //加入互斥量
memset(&gst_dev_boot, 0, sizeof(gst_dev_boot));
memset(&gst_dev_data, 0, sizeof(gst_dev_data));
//Boot区
gst_dev_boot.totalBytesPerChunk = pstFlashType->nNF_PAGE_DATA_BYTES;
gst_dev_boot.nDataBytesPerChunk = pstFlashType->nNF_PAGE_DATA_BYTES;
gst_dev_boot.spareBytesPerChunk = pstFlashType->nNF_PAGE_SPARE_BYTES;
gst_dev_boot.nChunksPerBlock = pstFlashType->nNF_PAGES_PER_BLOCK;
gst_dev_boot.nReservedBlocks = 5;
//gst_dev_boot.inbandTags = 1;
//gst_dev_boot.checkpointStartBlock = 1;
//gst_dev_boot.checkpointEndBlock = 20;
gst_dev_boot.startBlock = pstFlashType->nStartBlock;
gst_dev_boot.endBlock = pstFlashType->nNF_BOOT_BLOCKS - 1; // Make it smaller
gst_dev_boot.isYaffs2 = 1;
gst_dev_boot.wideTnodesDisabled = 0;
gst_dev_boot.nShortOpCaches = 0; // Use caches
gst_dev_boot.genericDevice = (void *)0; // Used to identify the device in fstat.
gst_dev_boot.writeChunkWithTagsTOnAND= yflash2_WriteChunkWithTagsToNAND;
gst_dev_boot.readChunkWithTagsFromNAND=
yflash2_ReadChunkWithTagsFromNAND;
gst_dev_boot.eraseBlockInNAND = yflash2_EraseBlockInNAND;
gst_dev_boot.initialiseNAND = yflash2_InitialiseNAND;
gst_dev_boot.markNANDBlockBad = yflash2_MarkNANDBlockBad;
gst_dev_boot.queryNANDBlock = yflash2_QueryNANDBlock;
//Data区
gst_dev_data.totalBytesPerChunk = pstFlashType->nNF_PAGE_DATA_BYTES;
gst_dev_data.nDataBytesPerChunk = pstFlashType->nNF_PAGE_DATA_BYTES;
gst_dev_data.spareBytesPerChunk = pstFlashType->nNF_PAGE_SPARE_BYTES;
gst_dev_data.nChunksPerBlock = pstFlashType->nNF_PAGES_PER_BLOCK;
gst_dev_data.nReservedBlocks = 5;
//gst_dev_data.inbandTags = 1;
//gst_dev_data.checkpointStartBlock = 1;
//gst_dev_data.checkpointEndBlock = 20;
gst_dev_data.startBlock = pstFlashType->nNF_BOOT_BLOCKS;
gst_dev_data.endBlock = pstFlashType->nNF_BLOCKS - 2; // Make it smaller
gst_dev_data.isYaffs2 = 1;
gst_dev_data.wideTnodesDisabled = 0;
gst_dev_data.nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; // Use caches
gst_dev_data.genericDevice = (void *)1; // Used to identify the device in fstat.
gst_dev_data.writeChunkWithTagsToNAND = yflash2_WriteChunkWithTagsToNAND;//从这以下是yaffs 与硬件相关的函数
gst_dev_data.readChunkWithTagsFromNAND = yflash2_ReadChunkWithTagsFromNAND;
gst_dev_data.eraseBlockInNAND = yflash2_EraseBlockInNAND;
gst_dev_data.initialiseNAND = yflash2_InitialiseNAND;
gst_dev_data.markNANDBlockBad = yflash2_MarkNANDBlockBad;
gst_dev_data.queryNANDBlock = yflash2_QueryNANDBlock;
yaffs_initialise(yaffsfs_config);//将填充的结构提注册到YAFFS 中
return 0;
}
Yaffs文件系统为flash提供的接口都在上面的函数指针函数中实现了,下面来看一个:
在yaffs_fileem2k.c中有个yflash2_WriteChunkWithTagsToNAND函数,是关于flash块的擦写的其中就调用了HAL_NandPageWrite 这个函数,这个函数的nandflash提供的一个接口函数。
关于nandflash的分区管理,我们公司的分区时,把bootload放在第0块,1--9块存放eboot,之后又分了两个区,分别存放os和app。我谈论这个问题主要是在ucosii开启任务的时候,要填充ST_FLASH_TYPE stFlashType 结构体,填充结构后要调用yaffs_startup(&stFlashType);函数启动yaffs文件系统。