123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- /*
- * RT-Thread Device Interface for uffs
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "dfs_uffs.h"
- static int nand_init_flash(uffs_Device *dev)
- {
- return UFFS_FLASH_NO_ERR;
- }
- static int nand_release_flash(uffs_Device *dev)
- {
- return UFFS_FLASH_NO_ERR;
- }
- static int nand_erase_block(uffs_Device *dev, unsigned block)
- {
- int res;
- res = rt_mtd_nand_erase_block(RT_MTD_NAND_DEVICE(dev->_private), block);
- return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR;
- }
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- static int nand_check_block(uffs_Device *dev, unsigned block)
- {
- int res;
- res = rt_mtd_nand_check_block(RT_MTD_NAND_DEVICE(dev->_private), block);
- return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK;
- }
- static int nand_mark_badblock(uffs_Device *dev, unsigned block)
- {
- int res;
- res = rt_mtd_nand_mark_badblock(RT_MTD_NAND_DEVICE(dev->_private), block);
- return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR;
- }
- #endif
- #if (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_NONE) || (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_SOFT)
- static int nand_read_page(uffs_Device *dev,
- u32 block,
- u32 page,
- u8 *data,
- int data_len,
- u8 *ecc,
- rt_uint8_t *spare,
- int spare_len)
- {
- int res;
- page = block * dev->attr->pages_per_block + page;
- if (data == NULL && spare == NULL)
- {
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- RT_ASSERT(0); //should not be here
- #else
- /* check block status: bad or good */
- rt_uint8_t spare[UFFS_MAX_SPARE_SIZE];
- rt_memset(spare, 0, UFFS_MAX_SPARE_SIZE);
- rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private),
- page, RT_NULL, 0,
- spare, dev->attr->spare_size);//dev->mem.spare_data_size
- res = spare[dev->attr->block_status_offs] == 0xFF ?
- UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK;
- return res;
- #endif
- }
- rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private),
- page, data, data_len, spare, spare_len);
- return UFFS_FLASH_NO_ERR;
- }
- static int nand_write_page(uffs_Device *dev,
- u32 block,
- u32 page,
- const u8 *data,
- int data_len,
- const u8 *spare,
- int spare_len)
- {
- int res;
- RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size);
- page = block * dev->attr->pages_per_block + page;
- if (data == NULL && spare == NULL)
- {
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- RT_ASSERT(0); //should not be here
- #else
- /* mark bad block */
- rt_uint8_t spare[UFFS_MAX_SPARE_SIZE];
- rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE);
- spare[dev->attr->block_status_offs] = 0x00;
- res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private),
- page, RT_NULL, 0,
- spare, dev->attr->spare_size);//dev->mem.spare_data_size
- if (res != RT_EOK)
- goto __error;
- #endif
- }
- res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private),
- page, data, data_len, spare, spare_len);
- if (res != RT_EOK)
- goto __error;
- return UFFS_FLASH_NO_ERR;
- __error:
- return UFFS_FLASH_IO_ERR;
- }
- const uffs_FlashOps nand_ops =
- {
- nand_init_flash, /* InitFlash() */
- nand_release_flash, /* ReleaseFlash() */
- nand_read_page, /* ReadPage() */
- NULL, /* ReadPageWithLayout */
- nand_write_page, /* WritePage() */
- NULL, /* WirtePageWithLayout */
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- nand_check_block,
- nand_mark_badblock,
- #else
- NULL, /* IsBadBlock(), let UFFS take care of it. */
- NULL, /* MarkBadBlock(), let UFFS take care of it. */
- #endif
- nand_erase_block, /* EraseBlock() */
- };
- void uffs_setup_storage(struct uffs_StorageAttrSt *attr,
- struct rt_mtd_nand_device *nand)
- {
- rt_memset(attr, 0, sizeof(struct uffs_StorageAttrSt));
- // attr->total_blocks = nand->end_block - nand->start_block + 1;/* no use */
- attr->page_data_size = nand->page_size; /* page data size */
- attr->pages_per_block = nand->pages_per_block; /* pages per block */
- attr->spare_size = nand->oob_size; /* page spare size */
- attr->ecc_opt = RT_CONFIG_UFFS_ECC_MODE; /* ecc option */
- attr->ecc_size = 0; /* ecc size is 0 , the uffs will calculate the ecc size*/
- attr->block_status_offs = attr->ecc_size; /* indicate block bad or good, offset in spare */
- attr->layout_opt = RT_CONFIG_UFFS_LAYOUT; /* let UFFS do the spare layout */
- }
- #elif RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_HW_AUTO
- static int WritePageWithLayout(uffs_Device *dev,
- u32 block,
- u32 page,
- const u8 *data,
- int data_len,
- const u8 *ecc, //NULL
- const uffs_TagStore *ts)
- {
- int res;
- 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 == NULL && ts == NULL)
- {
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- RT_ASSERT(0); //should not be here
- #else
- /* mark bad block */
- rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE);
- spare[dev->attr->block_status_offs] = 0x00;
- res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private),
- page, RT_NULL, 0,
- spare, dev->attr->spare_size);//dev->mem.spare_data_size
- if (res != RT_EOK)
- goto __error;
- dev->st.io_write++;
- return UFFS_FLASH_NO_ERR;
- #endif
- }
- if (data != NULL && data_len != 0)
- {
- RT_ASSERT(data_len == dev->attr->page_data_size);
- dev->st.page_write_count++;
- dev->st.io_write += data_len;
- }
- if (ts != RT_NULL)
- {
- uffs_FlashMakeSpare(dev, ts, RT_NULL, (u8 *)spare);
- dev->st.spare_write_count++;
- dev->st.io_write += spare_len;
- }
- res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private),
- page, data, data_len, spare, spare_len);
- if (res != RT_EOK)
- goto __error;
- return UFFS_FLASH_NO_ERR;
- __error:
- return UFFS_FLASH_IO_ERR;
- }
- 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;
- }
- const uffs_FlashOps nand_ops =
- {
- nand_init_flash, /* InitFlash() */
- nand_release_flash, /* ReleaseFlash() */
- NULL, /* ReadPage() */
- ReadPageWithLayout, /* ReadPageWithLayout */
- NULL, /* WritePage() */
- WritePageWithLayout,/* WirtePageWithLayout */
- #if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON)
- nand_check_block,
- nand_mark_badblock,
- #else
- NULL, /* IsBadBlock(), let UFFS take care of it. */
- NULL, /* MarkBadBlock(), let UFFS take care of it. */
- #endif
- nand_erase_block, /* EraseBlock() */
- };
- static rt_uint8_t hw_flash_data_layout[UFFS_SPARE_LAYOUT_SIZE] =
- {
- 0x05, 0x08, 0xFF, 0x00
- };
- static rt_uint8_t hw_flash_ecc_layout[UFFS_SPARE_LAYOUT_SIZE] =
- {
- 0x00, 0x04, 0xFF, 0x00
- };
- void uffs_setup_storage(struct uffs_StorageAttrSt *attr,
- struct rt_mtd_nand_device *nand)
- {
- rt_memset(attr, 0, sizeof(struct uffs_StorageAttrSt));
- // attr->total_blocks = nand->end_block - nand->start_block + 1;/* no use */
- attr->page_data_size = nand->page_size; /* page data size */
- attr->pages_per_block = nand->pages_per_block; /* pages per block */
- attr->spare_size = nand->oob_size; /* page spare size */
- attr->ecc_opt = RT_CONFIG_UFFS_ECC_MODE; /* ecc option */
- attr->ecc_size = nand->oob_size-nand->oob_free; /* ecc size */
- attr->block_status_offs = attr->ecc_size; /* indicate block bad or good, offset in spare */
- attr->layout_opt = RT_CONFIG_UFFS_LAYOUT; /* let UFFS do the spare layout */
- /* calculate the ecc layout array */
- hw_flash_data_layout[0] = attr->ecc_size + 1; /* ecc size + 1byte block status */
- hw_flash_data_layout[1] = 0x08;
- hw_flash_data_layout[2] = 0xFF;
- hw_flash_data_layout[3] = 0x00;
- hw_flash_ecc_layout[0] = 0;
- hw_flash_ecc_layout[1] = attr->ecc_size;
- hw_flash_ecc_layout[2] = 0xFF;
- hw_flash_ecc_layout[3] = 0x00;
- /* initialize _uffs_data_layout and _uffs_ecc_layout */
- rt_memcpy(attr->_uffs_data_layout, hw_flash_data_layout, UFFS_SPARE_LAYOUT_SIZE);
- rt_memcpy(attr->_uffs_ecc_layout, hw_flash_ecc_layout, UFFS_SPARE_LAYOUT_SIZE);
- attr->data_layout = attr->_uffs_data_layout;
- attr->ecc_layout = attr->_uffs_ecc_layout;
- }
- #endif
|