From a2a17fd24a3ef04d79c78480da50944cd5db640c Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 2 May 2009 16:18:20 +0000 Subject: [PATCH] - improved erase/program failure detection - added block_lock/unlock functions - locked blocks are unlocked automatically during erase Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@461 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/bsp/examples/cfiflash.c | 176 ++++++++++++++++++++++---- lib/CPUs/MIPS/bsp/examples/cfiflash.h | 25 +++- 2 files changed, 169 insertions(+), 32 deletions(-) diff --git a/lib/CPUs/MIPS/bsp/examples/cfiflash.c b/lib/CPUs/MIPS/bsp/examples/cfiflash.c index 92aeaed..c2beb7a 100644 --- a/lib/CPUs/MIPS/bsp/examples/cfiflash.c +++ b/lib/CPUs/MIPS/bsp/examples/cfiflash.c @@ -99,15 +99,38 @@ UINT32 cfi_find(flash_t *pObj) return 0; } -UINT32 cfi_block_erase(flash_t *pObj, UINT32 word_index) +UINT32 cfi_block_is_locked(flash_t *pObj, UINT32 word_index) { volatile UINT32 *pF; UINT32 status, block_index, block_mask; + UINT32 error; pF = (UINT32*)pObj->pBase; if (word_index >= (pObj->info.flashsize/4)) - return -1; + return CFI_ERR_INVPARAM; + + block_mask = ((pObj->info.nblocks-1) << 16); + block_index = word_index & block_mask; + + *pF = 0x00900090; + + error = ((UINT32)pF[block_index+2] & 0x00010001) != 0; + *pF = 0x00FF00FF; + + return error; +} + +UINT32 cfi_block_erase(flash_t *pObj, UINT32 word_index) +{ + volatile UINT32 *pF; + UINT32 status, block_index, block_mask; + UINT32 error; + + pF = (UINT32*)pObj->pBase; + + if (word_index >= (pObj->info.flashsize/4)) + return CFI_ERR_INVPARAM; block_mask = ((pObj->info.nblocks-1) << 16); block_index = word_index & block_mask; @@ -115,39 +138,119 @@ UINT32 cfi_block_erase(flash_t *pObj, UINT32 word_index) pF[block_index] = 0x00200020; pF[block_index] = 0x00D000D0; + error = 0; do { status = pF[block_index]; } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + if (status & (SR_BIT_ECLBS | SR_BIT_VPENS | SR_BIT_DPS)) + { + error = CFI_ERR_DEV_FAIL | status; + } + pF[block_index] = 0x00FF00FF; - return 0; + return error; +} + +UINT32 cfi_block_lock(flash_t *pObj, UINT32 word_index) +{ + volatile UINT32 *pF; + UINT32 status, block_index, block_mask; + UINT32 error; + + pF = (UINT32*)pObj->pBase; + + if (word_index >= (pObj->info.flashsize/4)) + return CFI_ERR_INVPARAM; + + block_mask = ((pObj->info.nblocks-1) << 16); + block_index = word_index & block_mask; + + pF[block_index] = 0x00600060; + pF[block_index] = 0x00010001; + + error = 0; + do + { + status = pF[block_index]; + + } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + + if (status & (SR_BIT_PSLBS | SR_BIT_VPENS | SR_BIT_ECLBS)) + { + error = CFI_ERR_DEV_FAIL | status; + } + + pF[block_index] = 0x00FF00FF; + + return error; +} + +UINT32 cfi_block_unlock(flash_t *pObj, UINT32 word_index) +{ + volatile UINT32 *pF; + UINT32 status, block_index, block_mask; + UINT32 error; + + pF = (UINT32*)pObj->pBase; + + if (word_index >= (pObj->info.flashsize/4)) + return CFI_ERR_INVPARAM; + + block_mask = ((pObj->info.nblocks-1) << 16); + block_index = word_index & block_mask; + + pF[block_index] = 0x00600060; + pF[block_index] = 0x00D000D0; + + error = 0; + do + { + status = pF[block_index]; + + } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + + if (status & (SR_BIT_PSLBS | SR_BIT_VPENS | SR_BIT_ECLBS)) + { + error = CFI_ERR_DEV_FAIL | status; + } + + pF[block_index] = 0x00FF00FF; + + return error; } UINT32 cfi_program_single(flash_t *pObj, UINT32 word_index, UINT32 word) { volatile UINT32 *pF; - UINT32 status; + UINT32 status, error; pF = (UINT32*)pObj->pBase; if (word_index >= (pObj->info.flashsize/4)) - return -1; + return CFI_ERR_INVPARAM; pF[word_index] = 0x00400040; pF[word_index] = word; + error = 0; do { status = pF[word_index]; } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + if (status & (SR_BIT_PSLBS | SR_BIT_VPENS | SR_BIT_DPS)) + { + error = CFI_ERR_DEV_FAIL | status; + } + pF[word_index] = 0x00FF00FF; - return 0; + return error; } @@ -156,11 +259,12 @@ UINT32 cfi_program_multi(flash_t *pObj, UINT32 word_index, UINT32 *pWords, UINT3 int i, j, k; volatile UINT32 *pF; UINT32 status, bcurr, bnext, block_mask, nblock_write, nbuf_write; + UINT32 error; pF = (UINT32*)pObj->pBase; if (word_index >= (pObj->info.flashsize/4)) - return -1; + return CFI_ERR_INVPARAM; block_mask = ((pObj->info.nblocks-1) << 16); @@ -174,28 +278,25 @@ UINT32 cfi_program_multi(flash_t *pObj, UINT32 word_index, UINT32 *pWords, UINT3 if (nblock_write > num_words) nblock_write = num_words; -// printf("bcurr : %8.8X\n", bcurr); -// printf("bnext : %8.8X\n", bnext); -// printf("windex : %8.8X\n", word_index); -// printf("num_words : %d\n", num_words); -// printf("nblock_write : %d\n", nblock_write); - while(nblock_write) { + error = 0; pF[bcurr] = 0x00E800E8; do { status = pF[bcurr]; -// printf("status : %8.8X\n", status); } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + if (status & (SR_BIT_PSLBS | SR_BIT_VPENS | SR_BIT_DPS)) + { + error = CFI_ERR_DEV_FAIL | status; + break; + } nbuf_write = nblock_write; if (nblock_write > pObj->info.wbuf_size/4) nbuf_write = pObj->info.wbuf_size/4; -// printf("nbuf_write : %d\n", nbuf_write); - pF[bcurr] = (nbuf_write-1) << 16 | (nbuf_write-1); for (j=0; j < nbuf_write; j++) @@ -205,20 +306,31 @@ UINT32 cfi_program_multi(flash_t *pObj, UINT32 word_index, UINT32 *pWords, UINT3 nblock_write -= j; num_words -= j; + error = 0; pF[bcurr] = 0x00D000D0; do { status = pF[bcurr]; -// printf("status : %8.8X\n", status); } while((status & SR_BIT_ISMS) != SR_BIT_ISMS); + if (status & (SR_BIT_PSLBS | SR_BIT_VPENS | SR_BIT_DPS)) + { + error = CFI_ERR_DEV_FAIL | status; + break; + } pF[bcurr] = 0x00FF00FF; } + + if (IS_ERROR(error)) + { + pF[bcurr] = 0x00FF00FF; + break; + } bcurr = bnext; } - return 0; + return error; } @@ -231,15 +343,24 @@ UINT32 flash_find(flash_t *pObj, UINT32 base_addr) UINT32 flash_erase(flash_t *pObj, UINT32 offset, UINT32 size) { int i; - UINT32 offset_end; + UINT32 offset_end, error; offset_end = offset + size; for (i=offset; i < offset_end; i += pObj->info.blocksize) - if (cfi_block_erase(pObj, i/4) < 0) - return -1; + { + if (cfi_block_is_locked(pObj, i/4)) + { + error = cfi_block_unlock(pObj, i/4); + if (IS_ERROR(error)) + break; + } + error = cfi_block_erase(pObj, i/4); + if (IS_ERROR(error)) + break; + } - return 0; + return error; } @@ -257,12 +378,12 @@ UINT32 flash_verify(flash_t *pObj, UINT32 offset, UINT8 *pData, UINT32 size) for (i=0; i < size; i++) if (pF[i] != pData[i]) - return -1; + return CFI_ERR_VFY_FAIL; return 0; } -UINT32 flash_aligned_addr_by_offset(flash_t *pObj, UINT32 offset) +UINT32 flash_get_blocknum_by_offset(flash_t *pObj, UINT32 offset) { UINT32 blocknum; @@ -270,7 +391,12 @@ UINT32 flash_aligned_addr_by_offset(flash_t *pObj, UINT32 offset) if (offset%pObj->info.blocksize) blocknum++; - return blocknum*pObj->info.blocksize; + return blocknum; +} + +UINT32 flash_aligned_addr_by_offset(flash_t *pObj, UINT32 offset) +{ + return flash_get_blocknum_by_offset(pObj, offset) * pObj->info.blocksize; } UINT32 flash_aligned_addr_by_blocknum(flash_t *pObj, UINT32 blocknum) diff --git a/lib/CPUs/MIPS/bsp/examples/cfiflash.h b/lib/CPUs/MIPS/bsp/examples/cfiflash.h index 4089537..b1638e1 100644 --- a/lib/CPUs/MIPS/bsp/examples/cfiflash.h +++ b/lib/CPUs/MIPS/bsp/examples/cfiflash.h @@ -4,13 +4,20 @@ #include "libsys.h" -#define SR_BIT_DPS 0x00020002 -#define SR_BIT_PSS 0x00040004 -#define SR_BIT_VPENS 0x00080008 -#define SR_BIT_PSLBS 0x00100010 -#define SR_BIT_ECLBS 0x00200020 -#define SR_BIT_ESS 0x00400040 -#define SR_BIT_ISMS 0x00800080 +#define SR_BIT_DPS 0x00020002 +#define SR_BIT_PSS 0x00040004 +#define SR_BIT_VPENS 0x00080008 +#define SR_BIT_PSLBS 0x00100010 +#define SR_BIT_ECLBS 0x00200020 +#define SR_BIT_ESS 0x00400040 +#define SR_BIT_ISMS 0x00800080 + +#define CFI_ERR_BASE (LSYS_ERR_BASE + 0x00100000) +#define CFI_ERR_GENERAL (CFI_ERR_BASE + 0) +#define CFI_ERR_NOTFOUND (CFI_ERR_BASE + 1) +#define CFI_ERR_INVPARAM (CFI_ERR_BASE + 2) +#define CFI_ERR_VFY_FAIL (CFI_ERR_BASE + 3) +#define CFI_ERR_DEV_FAIL (CFI_ERR_BASE + 0x10000000) typedef struct _sflash_info_t { @@ -33,12 +40,16 @@ typedef struct _sflash_t void cfi_init(flash_t *pObj, UINT32 base_addr); UINT32 cfi_find(flash_t *pObj); +UINT32 cfi_block_is_locked(flash_t *pObj, UINT32 word_index); UINT32 cfi_block_erase(flash_t *pObj, UINT32 word_index); +UINT32 cfi_block_lock(flash_t *pObj, UINT32 word_index); +UINT32 cfi_block_unlock(flash_t *pObj, UINT32 word_index); UINT32 cfi_program_single(flash_t *pObj, UINT32 word_index, UINT32 word); UINT32 cfi_program_multi(flash_t *pObj, UINT32 word_index, UINT32 *pWords, UINT32 num_words); UINT32 flash_aligned_addr_by_offset(flash_t *pObj, UINT32 offset); UINT32 flash_aligned_addr_by_blocknum(flash_t *pObj, UINT32 blocknum); +UINT32 flash_get_blocknum_by_offset(flash_t *pObj, UINT32 offset); UINT32 flash_find(flash_t *pObj, UINT32 base_addr); UINT32 flash_erase(flash_t *pObj, UINT32 offset, UINT32 size); UINT32 flash_program(flash_t *pObj, UINT32 offset, UINT8 *pData, UINT32 size);