コード例 #1
0
static URET femu_hw_auto_ReadPageWithLayout(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc,
        uffs_TagStore *ts, u8 *ecc_store)
{
    uffs_FileEmu *emu;
    int abs_page;
    struct uffs_StorageAttrSt *attr = dev->attr;
    unsigned char status;
    int spare_len;
    u8 spare[PAGE_SPARE_SIZE];
    u8 ecc_buf[RS_ECC_SIZE];
    int ret = UFFS_FLASH_IO_ERR;

    emu = (uffs_FileEmu *)(dev->attr->_private);

    if (!emu || !(emu->fp)) {
        goto ext;
    }

    abs_page = attr->pages_per_block * block + page;

    // now load full page to serial data buffer
    ret = load_sdata(dev, block, page);
    if (ret != UFFS_FLASH_NO_ERR)
        goto ext;

    start_sdata_access();

    dev->st.io_read += PAGE_FULL_SIZE;
    dev->st.page_read_count++;
    dev->st.spare_read_count++;

    if (data || ts) {

        if (data && data_len > 0) {
            if (data_len > attr->page_data_size)
                goto ext;

            drain_sdata(data, data_len);
        }

        if (ts) {
            if (g_sdata_buf_pointer < attr->page_data_size)
                drain_sdata(NULL, attr->page_data_size - g_sdata_buf_pointer);

            drain_sdata(spare, PAGE_SPARE_SIZE - RS_ECC_SIZE);

            // unload ts from spare
            uffs_FlashUnloadSpare(dev, spare, ts, NULL);
        }
    } else {
        // read bad block mark
        drain_sdata(NULL, attr->page_data_size + attr->block_status_offs - 1);
        drain_sdata(&status, 1);

        ret = (status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK);
    }

ext:
    return ret;
}
コード例 #2
0
ファイル: uffs_nandif.c プロジェクト: 634351070/rt-thread
static URET ReadPageWithLayout(uffs_Device   *dev,
                               u32            block,
                               u32            page,
                               u8            *data,
                               int            data_len,
                               u8            *ecc,              //NULL
                               uffs_TagStore *ts,
                               u8            *ecc_store)        //NULL
{
    int res = UFFS_FLASH_NO_ERR;
    int spare_len;
    rt_uint8_t spare[UFFS_MAX_SPARE_SIZE];

    RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size);

    page = block * dev->attr->pages_per_block + page;
    spare_len = dev->mem.spare_data_size;

    if (data == RT_NULL && ts == RT_NULL)
    {
#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
        RT_ASSERT(0); //should not be here
#else
        /* check block good or bad */

        rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private),
                         page, RT_NULL, 0,
                         spare, dev->attr->spare_size);//dev->mem.spare_data_size

        dev->st.io_read++;

        res = spare[dev->attr->block_status_offs] == 0xFF ?
                               UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK;
        return res;
#endif
    }

    if (data != RT_NULL)
    {
        dev->st.io_read += data_len;
        dev->st.page_read_count++;
    }

    res = rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private),
                           page, data, data_len, spare, spare_len);
    if (res == 0)
        res = UFFS_FLASH_NO_ERR;
    else if (res == -1)
    {
        //TODO ecc correct, add code to use hardware do ecc correct
        res = UFFS_FLASH_ECC_OK;
    }
    else
        res = UFFS_FLASH_ECC_FAIL;

    if (ts != RT_NULL)
    {
        // unload ts and ecc from spare, you can modify it if you like
        uffs_FlashUnloadSpare(dev, (const u8 *)spare, ts, RT_NULL);

        if ((spare[spare_len - 1] == 0xFF) && (res == UFFS_FLASH_NO_ERR))
            res = UFFS_FLASH_NOT_SEALED;

        dev->st.io_read += spare_len;
        dev->st.spare_read_count++;
    }

    return res;
}
コード例 #3
0
static URET femu_hw_ReadPageWithLayout(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc,
									uffs_TagStore *ts, u8 *ecc_store)
{
	int nread;
	uffs_FileEmu *emu;
	int abs_page;
	int full_page_size;
	struct uffs_StorageAttrSt *attr = dev->attr;
	unsigned char status;
	u8 spare[UFFS_MAX_SPARE_SIZE];
	int spare_len;

	emu = (uffs_FileEmu *)(dev->attr->_private);

	if (!emu || !(emu->fp)) {
		goto err;
	}

	abs_page = attr->pages_per_block * block + page;
	full_page_size = attr->page_data_size + attr->spare_size;

	if (data && data_len > 0) {
		if (data_len > attr->page_data_size)
			goto err;

		fseek(emu->fp, abs_page * full_page_size, SEEK_SET);
		nread = fread(data, 1, data_len, emu->fp);

		if (nread != data_len) {
			MSG("read page I/O error ?");
			goto err;
		}
		dev->st.io_read += nread;
		dev->st.page_read_count++;

		if (ecc) {
			// calculate ECC for data
			uffs_EccMake(data, data_len, ecc);
		}
	}

	if (ts) {

		spare_len = dev->mem.spare_data_size;
		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET);
		nread = fread(spare, 1, spare_len, emu->fp);

		if (nread != spare_len) {
			MSG("read page spare I/O error ?");
			goto err;
		}

		// unload ts and ecc from spare
		uffs_FlashUnloadSpare(dev, spare, ts, ecc_store);

		dev->st.io_read += nread;
		dev->st.spare_read_count++;
	}

	if (data == NULL && ts == NULL) {
		// read bad block mark
		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET);
		nread = fread(&status, 1, 1, emu->fp);

		if (nread != 1) {
			MSG("read badblock mark I/O error ?");
			goto err;
		}
		dev->st.io_read++;

		return status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK;
	}

	return UFFS_FLASH_NO_ERR;
err:
	return UFFS_FLASH_IO_ERR;
}
コード例 #4
0
/**
 * Read page data to buf (do ECC error correction if needed)
 * \param[in] dev uffs device
 * \param[in] block flash block num
 * \param[in] page flash page num of the block
 * \param[out] buf holding the read out data
 * \param[in] skip_ecc skip ecc when reading data from flash
 *
 * \return	#UFFS_FLASH_NO_ERR: success and/or has no flip bits.
 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
 *			#UFFS_FLASH_ECC_FAIL: spare data has flip bits and ecc correct failed.
 *			#UFFS_FLASH_ECC_OK: spare data has flip bits and corrected by ecc.
 *			#UFFS_FLASH_CRC_ERR: CRC verification failed.
 *			#UFFS_FLASH_UNKNOWN_ERR:
 *
 * \note if skip_ecc is U_TRUE, skip CRC as well.
 */
int uffs_FlashReadPage(uffs_Device *dev, int block, int page, uffs_Buf *buf, UBOOL skip_ecc)
{
	uffs_FlashOps *ops = dev->ops;
	struct uffs_StorageAttrSt *attr = dev->attr;
	int size = dev->com.pg_size;
	u8 ecc_buf[UFFS_MAX_ECC_SIZE];
	u8 ecc_store[UFFS_MAX_ECC_SIZE];
	UBOOL is_bad = U_FALSE;
#ifdef CONFIG_ENABLE_PAGE_DATA_CRC
	UBOOL crc_ok = U_TRUE;
#endif
	u8 * spare;

	int ret = UFFS_FLASH_UNKNOWN_ERR;

	spare = (u8 *) uffs_PoolGet(SPOOL(dev));
	if (spare == NULL)
		goto ext;

	if (ops->ReadPageWithLayout) {
		if (skip_ecc)
			ret = ops->ReadPageWithLayout(dev, block, page, buf->header, size, NULL, NULL, NULL);
		else
			ret = ops->ReadPageWithLayout(dev, block, page, buf->header, size, ecc_buf, NULL, ecc_store);
	}
	else {
		if (skip_ecc)
			ret = ops->ReadPage(dev, block, page, buf->header, size, NULL, NULL, 0);
		else
			ret = ops->ReadPage(dev, block, page, buf->header, size, ecc_buf, spare, dev->mem.spare_data_size);
	}

	if (UFFS_FLASH_IS_BAD_BLOCK(ret))
		is_bad = U_TRUE;

	if (UFFS_FLASH_HAVE_ERR(ret))
		goto ext;

#ifdef CONFIG_ENABLE_PAGE_DATA_CRC
	if (!skip_ecc) {
		crc_ok = (HEADER(buf)->crc == uffs_crc16sum(buf->data, size - sizeof(struct uffs_MiniHeaderSt)) ? U_TRUE : U_FALSE);

		if (crc_ok)
			goto ext;	// CRC is matched, no need to do ECC correction.
		else {
			if (dev->attr->ecc_opt == UFFS_ECC_NONE || dev->attr->ecc_opt == UFFS_ECC_HW_AUTO) {
				// ECC is not enabled or ecc correction already done, error return immediately,
				// otherwise, we try CRC check again after ecc correction.
				ret = UFFS_FLASH_CRC_ERR;
				goto ext;
			}
		}
	}
#endif

	// make ECC for UFFS_ECC_SOFT
	if (attr->ecc_opt == UFFS_ECC_SOFT && !skip_ecc)
		uffs_EccMake(buf->header, size, ecc_buf);

	// unload ecc_store if driver doesn't do the layout
	if (ops->ReadPageWithLayout == NULL) {
		if (!skip_ecc && (attr->ecc_opt == UFFS_ECC_SOFT || attr->ecc_opt == UFFS_ECC_HW))
			uffs_FlashUnloadSpare(dev, spare, NULL, ecc_store);
	}

	// check page data ecc
	if (!skip_ecc && (dev->attr->ecc_opt == UFFS_ECC_SOFT || dev->attr->ecc_opt == UFFS_ECC_HW)) {

		ret = uffs_EccCorrect(buf->header, size, ecc_store, ecc_buf);
		ret = (ret < 0 ? UFFS_FLASH_ECC_FAIL :
				(ret > 0 ? UFFS_FLASH_ECC_OK : UFFS_FLASH_NO_ERR));

		if (UFFS_FLASH_IS_BAD_BLOCK(ret))
			is_bad = U_TRUE;

		if (UFFS_FLASH_HAVE_ERR(ret))
			goto ext;
	}

#ifdef CONFIG_ENABLE_PAGE_DATA_CRC
	if (!skip_ecc && !UFFS_FLASH_HAVE_ERR(ret)) {
		// Everything seems ok, do CRC check again.
		if (HEADER(buf)->crc == uffs_crc16sum(buf->data, size - sizeof(struct uffs_MiniHeaderSt))) {
			ret = UFFS_FLASH_CRC_ERR;
			goto ext;
		}
	}
#endif

ext:
	switch(ret) {
		case UFFS_FLASH_IO_ERR:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d I/O error", block, page);
			break;
		case UFFS_FLASH_ECC_FAIL:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d ECC failed", block, page);
			ret = UFFS_FLASH_BAD_BLK;	// treat ECC FAIL as BAD BLOCK
			is_bad = U_TRUE;
			break;
		case UFFS_FLASH_ECC_OK:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d bit flip corrected by ECC", block, page);
			break;
		case UFFS_FLASH_BAD_BLK:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d BAD BLOCK found", block, page);
			break;
		case UFFS_FLASH_UNKNOWN_ERR:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d UNKNOWN error!", block, page);
			break;
		case UFFS_FLASH_CRC_ERR:
			uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d CRC failed", block, page);
			break;
		default:
			break;
	}

	if (is_bad)
		uffs_BadBlockAdd(dev, block);

	if (spare)
		uffs_PoolPut(SPOOL(dev), spare);


	return ret;
}
コード例 #5
0
/**
 * Read tag from page spare
 *
 * \param[in] dev uffs device
 * \param[in] block flash block num
 * \param[in] page flash page num
 * \param[out] tag tag to be filled
 *
 * \return	#UFFS_FLASH_NO_ERR: success and/or has no flip bits.
 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
 *			#UFFS_FLASH_ECC_FAIL: spare data has flip bits and ecc correct failed.
 *			#UFFS_FLASH_ECC_OK: spare data has flip bits and corrected by ecc.
*/
int uffs_FlashReadPageTag(uffs_Device *dev,
							int block, int page, uffs_Tags *tag)
{
	uffs_FlashOps *ops = dev->ops;
	u8 * spare_buf;
	int ret = UFFS_FLASH_UNKNOWN_ERR;
	int tmp_ret;
	UBOOL is_bad = U_FALSE;

	spare_buf = (u8 *) uffs_PoolGet(SPOOL(dev));
	if (spare_buf == NULL)
		goto ext;

	if (ops->ReadPageWithLayout) {
		ret = ops->ReadPageWithLayout(dev, block, page, NULL, 0, NULL, tag ? &tag->s : NULL, NULL);
		if (tag)
			tag->seal_byte = (ret == UFFS_FLASH_NOT_SEALED ? 0xFF : 0);
	}
	else {
		ret = ops->ReadPage(dev, block, page, NULL, 0, NULL,
									spare_buf, dev->mem.spare_data_size);

		if (tag) {
			tag->seal_byte = SEAL_BYTE(dev, spare_buf);

			if (!UFFS_FLASH_HAVE_ERR(ret))
				uffs_FlashUnloadSpare(dev, spare_buf, &tag->s, NULL);
		}
	}

	if (UFFS_FLASH_IS_BAD_BLOCK(ret))
		is_bad = U_TRUE;

	if (UFFS_FLASH_HAVE_ERR(ret))
		goto ext;

	if (tag) {
		if (!TAG_IS_SEALED(tag))	// not sealed ? don't try tag ECC correction
			goto ext;

		if (!TAG_IS_VALID(tag)) {
			if (dev->attr->ecc_opt != UFFS_ECC_NONE) {
				/*
				 * There could be a special case if:
				 *  a) tag is sealed (so we are here), and
				 *  b) s.valid == 1 and this bit is a 'bad' bit, and
				 *  c) after tag ECC (corrected by tag ECC) s.valid == 0.
				 *
				 * So we need to try tag ECC (don't treat it as bad block if ECC failed)
				 */

				struct uffs_TagStoreSt s;

				memcpy(&s, &tag->s, sizeof(s));
				tmp_ret = TagEccCorrect(&s);

				if (tmp_ret <= 0 || !TAG_IS_VALID(tag))	// can not corrected by ECC.
					goto ext;
			}
			else {
				goto ext;
			}				
		}

		// do tag ecc correction
		if (dev->attr->ecc_opt != UFFS_ECC_NONE) {
			ret = TagEccCorrect(&tag->s);
			ret = (ret < 0 ? UFFS_FLASH_ECC_FAIL :
					(ret > 0 ? UFFS_FLASH_ECC_OK : UFFS_FLASH_NO_ERR));

			if (UFFS_FLASH_IS_BAD_BLOCK(ret))
				is_bad = U_TRUE;

			if (UFFS_FLASH_HAVE_ERR(ret))
				goto ext;
		}
	}

ext:
	if (is_bad) {
		uffs_BadBlockAdd(dev, block);
		uffs_Perror(UFFS_MSG_NORMAL,
					"A new bad block (%d) is detected.", block);
	}

	if (spare_buf)
		uffs_PoolPut(SPOOL(dev), spare_buf);

	return ret;
}