- 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
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user