yaffs2移植到ucos上

以前年搞过一次,将yaffs2移植到低版本的uboot上,刚好前段时间又有需求移植到ucos上,记录一下

yaffs2移植专题:

    使用的是2017-08-11更新的版本yaffs2-c1422c2.tar,路径:http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=snapshot;h=c1422c27f5f17c68acf261209292c7489085df6b;sf=tgz
    yaffs2移植实地址模式YDI主要适配os,以及flash的读写接口。
    yaffs2重要的结构体:
    yaffs_dev:            总的结构,需分配空间
    yaffs_param:        属性结构,param = &dev->param;包含分区名,nand的页,块等属性,起始地址,结束地址,保留块数量,tag等
    yaffs_driver:    驱动对接接口, drv = &dev->drv;主要:drv_write_chunk_fn,drv_read_chunk_fn,drv_erase_fn,drv_mark_bad_fn,drv_check_bad_fn...需要全部实现。
    最后由yaffs_add_device(dev);添加进去,所以可以支持多个分区,多次yaffs_add_device(devN);
    完成后可以用yaffs_mount(ROOT_PATH);注意ROOT_PATH必须和param的分区名对应,否则找不到。
    测试过程可以通过yaffs_set_trace(YAFFS_TRACE_ALWAYS | YAFFS_TRACE_ERROR | YAFFS_TRACE_BUG | 0);设置需要调试的模块信息。
    完成后即可用yaffs_access,yaffs_open,yaffs_write,yaffs_read,yaffs_close,yaffs_flush等接口正常操作。

    调试过程注意nand flash本身是否存在坏块,烧写之前进行erase擦除,不要使用scrub命令擦除,否则可能会将烧写内容写异常。

#include "yaffs2/yportenv.h"
#include "yaffs2/yaffs_trace.h"
#include "yaffs2/yaffs_guts.h"
#include "yaffs2/yaffs_packedtags2.h"


// for mt_nand config(w25n01gv spi nand flash) add by jason.luo at 2017/9/8 11:22:16
#define MTAPP_DEVICE_BASE 	0x3000000 	  //yaffs2 mount addr at 48MB              need fix
#define SIZE_IN_MB 60						            //flash total size: 128MB, yaffs size 60MB       need fix

static const char *yaffs_dev_name = "nand";

struct yaffs_dev *mtDev;

#ifndef RET_CODE
#define RET_CODE s32
#endif



static  void *p_dev       = NULL;
charsto_flash_info_t flash_info;

static int yflash2_GetStartBlock(){
  int startblock = (MTAPP_DEVICE_BASE/flash_info.blocksize);
  return startblock;
}

static int yflash2_GetNumberOfBlocks(void)
{
	int nBolocks = (SIZE_IN_MB * 1024 * 1024)/(flash_info.blocksize);
	return nBolocks;
}

static int yflash2_GetEndBlock(){
  int endblock = yflash2_GetStartBlock() + yflash2_GetNumberOfBlocks();
  return endblock;
}

static u32 yflash2_GetEndAddr(){
  u32 addr = yflash2_GetEndBlock()*flash_info.blocksize;
  return addr;
}

static int yflash2_Deinitialise(struct yaffs_dev *dev){
    (void)dev;
    return 0;
}

static int yflash2_WriteChunk(struct yaffs_dev *dev, int nand_chunk, const u8 *data, int data_len,const u8 *oob, int oob_len){

    int ret = -1;
	struct mtd_oob_ops ops;


    if (!data || !data_len) {
		data = NULL;
		data_len = 0;
	}

	if (!oob || !oob_len) {
		oob = NULL;
		oob_len = 0;
	}
   u32 addr = ((u32) nand_chunk) * dev->param.total_bytes_per_chunk;
   if(addr < MTAPP_DEVICE_BASE|| addr > yflash2_GetEndAddr()){
       return YAFFS_FAIL;
    }


   if(data && data_len)
   {
      ret = charsto_writeonly(p_dev,addr,(u8 *)data,data_len);
      if(ret)
      {
          OS_PRINTF("%s %d ret = %d\n",__FUNCTION__,__LINE__,ret);
      }
   }
   if(oob && oob_len)
   {
      memset(&ops, 0, sizeof(ops));
      ops.datbuf = NULL;
      ops.len = 0;
      ops.ooblen = oob_len;
      ops.mode = MTD_OOB_AUTO;
      	ops.ooboffs = 0;
      ops.oobbuf = (u8 *)oob;
      ret = charsto_write_oob(p_dev,addr,&ops);
      if(ret)
      {
          OS_PRINTF("%s %d ret = %d\n",__FUNCTION__,__LINE__,ret);
      }
   }

	if(ret < 0){
	{
      OS_PRINTF("%s %d ret = %d\n",__FUNCTION__,__LINE__,ret);
      return YAFFS_FAIL;
   }
	}else{
	return YAFFS_OK;
	}
}


static int yflash2_Initialise(struct yaffs_dev *dev)
{
	(void) dev;
   return YAFFS_OK;
}

static int yflash2_CheckBad(struct yaffs_dev *dev, int block_no)
{
  charsto_flash_bad_block_info_t info;
   u8 ret = 0;
   if(block_no < yflash2_GetStartBlock() || block_no > yflash2_GetEndBlock()){
    return YAFFS_FAIL;
  }

   info.addr = block_no;
   dev_io_ctrl(p_dev, CHARSTO_IOCTRL_IS_BAD_BLOCK, (u32)&info);
   ret = info.block_is_bad;

   if(ret == 0)
    	return YAFFS_OK;
   return YAFFS_FAIL;
}

static int yflash2_MarkBad(struct yaffs_dev *dev, int block_no)
{
	int ret = 0;
  if(block_no < yflash2_GetStartBlock() || block_no > yflash2_GetEndBlock()){
    return YAFFS_FAIL;
  }
  u32 offset = block_no;
 dev_io_ctrl(p_dev, CHARSTO_IOCTRL_MARK_BAD_BLOCK,offset);

	if(ret != 0)
		return YAFFS_FAIL;
	return YAFFS_OK;
}

static int yflash2_write_chunk_tags (struct yaffs_dev *dev,
				    int nand_chunk, const u8 *data,
				    const struct yaffs_ext_tags *tags){

    struct mtd_oob_ops ops;

	int retval = 0;

	loff_t addr;

	struct yaffs_packed_tags2 pt;

	int packed_tags_size = dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
	void *packed_tags_ptr = dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;

	yaffs_trace(YAFFS_TRACE_MTD,
		"nandmtd2_write_chunk_tags chunk %d data %p tags %p",
		nand_chunk, data, tags);

	addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;

	/* For yaffs2 writing there must be both data and tags.
	 * If we're using inband tags, then the tags are stuffed into
	 * the end of the data buffer.
	 */
	if (!data || !tags)
		BUG();
	else if (dev->param.inband_tags) {
		struct yaffs_packed_tags2_tags_only *pt2tp;
		pt2tp = (struct yaffs_packed_tags2_tags_only *)(data + dev->data_bytes_per_chunk);
		yaffs_pack_tags2_tags_only(dev,pt2tp, tags);
	} else {
		yaffs_pack_tags2(dev,&pt, tags, !dev->param.no_tags_ecc);
	}

    charsto_writeonly(p_dev,addr,(u8 *)data,dev->param.total_bytes_per_chunk);
	ops.mode = MTD_OOB_AUTO;
	ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
	ops.len = 0;//dev->param.total_bytes_per_chunk;
	ops.ooboffs = 0;
	ops.datbuf = NULL;//(u8 *) data;
	ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
	retval = charsto_write_oob(p_dev, addr, &ops);
	if (retval == 0)
		return YAFFS_OK;
	else
		return YAFFS_FAIL;
}





static int yflash2_read_chunk_tags(struct yaffs_dev *dev,
				   int nand_chunk, u8 *data,
				   struct yaffs_ext_tags *tags){

	u8 local_spare[128];
	struct mtd_oob_ops ops;
	int retval = 0;
	int local_data = 0;
	struct yaffs_packed_tags2 pt;

  loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
	int packed_tags_size =
	    dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
	void *packed_tags_ptr =
	    dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;

	yaffs_trace(YAFFS_TRACE_ERROR,
		"nandmtd2_read_chunk_tags chunk %d data %p tags %p",
		nand_chunk, data, tags);

	if (dev->param.inband_tags) {

		if (!data) {
			local_data = 1;
			data = yaffs_get_temp_buffer(dev);
		}

	}

	if (dev->param.inband_tags || (data && !tags)){
    	/* Do not allow reads past end of device */
    	if ((addr + dev->param.total_bytes_per_chunk) > flash_info.chipsize)
    		return -1;
		retval = charsto_read(p_dev, addr,data,dev->param.total_bytes_per_chunk);
   }
	else if (tags) {

		ops.mode = MTD_OOB_AUTO;
		ops.ooblen = packed_tags_size;
		ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
		ops.ooboffs = 0;
		ops.datbuf = data;
		ops.oobbuf = local_spare;
		retval = charsto_read_oob(p_dev, addr, &ops);
	}

	if (dev->param.inband_tags) {
		if (tags) {
			struct yaffs_packed_tags2_tags_only *pt2tp;
			pt2tp =
				(struct yaffs_packed_tags2_tags_only *)
				&data[dev->data_bytes_per_chunk];
			yaffs_unpack_tags2_tags_only(dev,tags, pt2tp);
		}
	} else {
		if (tags) {
			memcpy(packed_tags_ptr,
			       local_spare,
			       packed_tags_size);
			yaffs_unpack_tags2(dev,tags, &pt, !dev->param.no_tags_ecc);
		}
	}

	if (local_data)
		yaffs_release_temp_buffer(dev, data);

	if (tags && retval == -EBADMSG
	    && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
		tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
		dev->n_ecc_unfixed++;
	}
	if (tags && retval == -EUCLEAN
	    && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
		tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
		dev->n_ecc_fixed++;
	}
	if (retval == 0)
		return YAFFS_OK;
	else
		return YAFFS_FAIL;
    

}



static int yflash2_QueryBlock (struct yaffs_dev *dev, int block_no,enum yaffs_block_state *state,u32 *seq_number){
    int retval = 0;
    charsto_flash_bad_block_info_t info;
	yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_QueryNANDBlock %d", block_no);

   info.addr = block_no;
   dev_io_ctrl(p_dev, CHARSTO_IOCTRL_IS_BAD_BLOCK, (u32)&info);
   retval = info.block_is_bad;

	if (retval) {
		yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
		*state = YAFFS_BLOCK_STATE_DEAD;
		*seq_number = 0;
	} else {
		struct yaffs_ext_tags t;
		yflash2_read_chunk_tags(dev,
					   block_no *
					   dev->param.chunks_per_block, NULL,
					   &t);

		if (t.chunk_used) {
			*seq_number = t.seq_number;
			*state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
		} else {
			*seq_number = 0;
			*state = YAFFS_BLOCK_STATE_EMPTY;
		}
	}
	yaffs_trace(YAFFS_TRACE_MTD, "block is bad seq %d state %d",
			*seq_number, *state);

	if (retval == 0)
		return YAFFS_OK;
	else
		return YAFFS_FAIL;
}






static int yflash2_EraseBlock(struct yaffs_dev *dev, int block_no)
{
    if(block_no < yflash2_GetStartBlock() || block_no > yflash2_GetEndBlock()){
      return YAFFS_FAIL;
    }
   charsto_erase(p_dev,block_no*128*1024,1);
  return YAFFS_OK;
}

static int yflash2_ReadChunk(struct yaffs_dev *dev, int nand_chunk,u8 *data, int data_len,u8 *oob, int oob_len,enum yaffs_ecc_result *ecc_result_out){
    int ret = -1;
    struct mtd_oob_ops ops;
    u32  addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
    if(addr < MTAPP_DEVICE_BASE|| addr > yflash2_GetEndAddr()){
       return YAFFS_FAIL;
    }

    if(data && data_len){
        ret = charsto_read(p_dev,addr,data,data_len);
      }
    if(oob && oob_len){
    	memset(&ops, 0, sizeof(ops));
    	ops.mode = MTD_OOB_AUTO;
    	ops.len = 0;
    	ops.ooblen = oob_len;
    	ops.datbuf = NULL;
    	ops.oobbuf = oob;
      ret = charsto_read_oob(p_dev,addr,&ops);
     }
      if(ret < 0)
      {
          OS_PRINTF("spi_nand_do_read_ops 0x%x error\n",addr);
        	return YAFFS_FAIL;
      }
      *ecc_result_out = YAFFS_ECC_RESULT_NO_ERROR;
      return YAFFS_OK;
}

static struct yaffs_dev *yflash2_install_drv(const char *name,int startblock,int endblock){

	struct yaffs_param *param;
	struct yaffs_driver *drv = NULL;
  	struct yaffs_dev *dev = NULL;
  
  	struct yaffs_tags_handler *tagger = NULL;

	dev = malloc(sizeof(*dev));

	if(!dev){
		return NULL;
   }

	memset(dev, 0, sizeof(*dev));

	dev->param.name = strdup(name);

	if(!dev->param.name) {
		free(dev);
		return NULL;
	}
	
	param = &dev->param;
    param->total_bytes_per_chunk = flash_info.pagesize;
	param->chunks_per_block = flash_info.blocksize / flash_info.pagesize;
    param->spare_bytes_per_chunk = flash_info.oobsize;
	param->start_block = startblock;        //0X3000000 = 384
	param->end_block = endblock-1;
	param->is_yaffs2 = 1;
	
   	param->use_nand_ecc=1;               //nand ecc or yaffs ecc
	param->empty_lost_n_found = 1;       //auto empty
	param->n_reserved_blocks = 5;
	param->refresh_period = 1000;
	param->n_caches = 10;                   // Use caches
    param->inband_tags = 0;                //must set for yaffs2 big page
    param->no_tags_ecc = 1;

	drv = &dev->drv;
	drv->drv_initialise_fn = yflash2_Initialise;
   drv->drv_deinitialise_fn = yflash2_Deinitialise;
	drv->drv_write_chunk_fn = yflash2_WriteChunk;
	drv->drv_read_chunk_fn = yflash2_ReadChunk;
	drv->drv_erase_fn = yflash2_EraseBlock;
	drv->drv_mark_bad_fn = yflash2_MarkBad;
	drv->drv_check_bad_fn = yflash2_CheckBad;
   tagger = &dev->tagger;
   tagger->mark_bad_fn = yflash2_MarkBad;
   tagger->query_block_fn = yflash2_QueryBlock;
   tagger->write_chunk_tags_fn = yflash2_write_chunk_tags;
   tagger->read_chunk_tags_fn  = yflash2_read_chunk_tags;

	yaffs_add_device(dev);
	return dev;
}


int yaffs_start_up(void){
	static int start_up_called = 0;
	if(start_up_called){
		return 0;
   }
	start_up_called = 1;
	yaffsfs_OSInitialisation();
    //get snf first

    p_dev = dev_find_identifier(NULL, DEV_IDT_TYPE, SYS_DEV_TYPE_CHARSTO);
    //  charsto_flash_info_t flash_info;
    dev_io_ctrl(p_dev, CHARSTO_IOCTRL_GET_FLASH_INFO, (u32)&flash_info);

    int start_block = yflash2_GetStartBlock();
    
    int end_block = yflash2_GetEndBlock();
    
    mtDev = yflash2_install_drv(yaffs_dev_name,start_block,end_block);
    if(mtDev == NULL){
        return -1;
    }
    return -1;
}

int mt_yaffs_start_up(void){
//  yaffs_set_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_ALWAYS | YAFFS_TRACE_BUG | YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_SCAN_DEBUG | YAFFS_TRACE_SCAN);
  return yaffs_start_up();
}


name对应的是挂载点"/name"
param->inband_tags = 0; OOB存储tag
tagger = &dev->tagger;函数不能偷懒,都得设置起




  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
YAFFS2(Yet Another Flash File System 2)是一种针对嵌入式系统设计的开源嵌入式文件系统。移植YAFFS2到单片机上涉及以下步骤: 1. 了解单片机的硬件和存储器:单片机的硬件架构和存储器类型对文件系统的移植至关重要。需要了解单片机的处理器类型、存储器大小和类型,例如闪存或EEPROM等。 2. 下载和配置YAFFS2:从官方网站或源代码仓库下载YAFFS2的最新版本。根据单片机的硬件和存储器特性,修改YAFFS2的配置文件,例如设置闪存大小、页大小和块大小等。 3. 移植文件操作接口:单片机的操作系统可能不支持标准的文件操作接口,需要根据单片机的特性实现文件系统的操作接口。这些接口包括读写文件、创建删除文件、目录遍历等。 4. 适配存储器驱动程序:YAFFS2需要针对单片机的存储器类型进行适配。根据单片机的存储器接口和特性,修改YAFFS2的底层驱动程序,确保与单片机的存储器正常交互。 5. 编译和链接YAFFS2:使用适当的交叉编译工具链,将YAFFS2编译为单片机可执行的格式。确保编译选项与单片机的体系结构和操作系统匹配。 6. 测试和调试:将移植后的YAFFS2文件系统部署到单片机上,并进行详细的功能测试和性能测试。通过检查文件系统的功能和性能是否符合预期,进行必要的调试和优化。 总之,移植YAFFS2到单片机需要对单片机硬件和存储器有深入的了解,并进行文件操作接口适配和存储器驱动程序适配。合理配置和编译YAFFS2,最后进行测试和调试,确保其正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值