📄 nandflash.c
字号:
} else {
for(i=0; i<uBytesToRead; i++)
{
*pOutBuffer = READ_NAND();
pOutBuffer++;
}
}
exit:
/* Disable the chip */
NAND_DISABLE_CE();
return bRet;
}
#else /* NANDFLASH_LARGE_BLOCKS */
/*------------------------------------------------------------------------------*/
/* \fn AT91F_NandReadSector */
/* \brief Read a Sector */
/*------------------------------------------------------------------------------*/
static BOOL AT91F_NandReadSector(PSNandInfo pNandInfo, unsigned int uSectorAddr, char *pOutBuffer, unsigned int fZone)
{
BOOL bRet = TRUE;
unsigned int uBytesToRead, i;
/* WARNING : During a read procedure you can't call the ReadStatus flash cmd */
/* The ReadStatus fill the read register with 0xC0 and then corrupt the read.*/
/* Enable the chip */
NAND_ENABLE_CE();
/* Write specific command, Read from start */
WRITE_NAND_COMMAND(CMD_READ_1);
/* Push offset address */
switch(fZone)
{
case ZONE_DATA:
uBytesToRead = pNandInfo->uDataNbBytes;
WRITE_NAND_ADDRESS(0x00);
WRITE_NAND_ADDRESS(0x00);
break;
case ZONE_INFO:
uBytesToRead = pNandInfo->uSpareNbBytes;
pOutBuffer += pNandInfo->uDataNbBytes;
if (pNandInfo->uDataBusWidth)
{ /* 16 bits */
WRITE_NAND_ADDRESS(((pNandInfo->uDataNbBytes/2) >> 0) & 0xFF); /* Div 2 is because we address in word and not
in byte */
WRITE_NAND_ADDRESS(((pNandInfo->uDataNbBytes/2) >> 8) & 0xFF);
} else { /* 8 bits */
WRITE_NAND_ADDRESS((pNandInfo->uDataNbBytes >> 0) & 0xFF);
WRITE_NAND_ADDRESS((pNandInfo->uDataNbBytes >> 8) & 0xFF);
}
break;
case ZONE_DATA | ZONE_INFO:
uBytesToRead = pNandInfo->uSectorNbBytes;
WRITE_NAND_ADDRESS(0x00);
WRITE_NAND_ADDRESS(0x00);
break;
default:
bRet = FALSE;
goto exit;
}
/* Push sector address */
uSectorAddr >>= pNandInfo->uOffset;
WRITE_NAND_ADDRESS((uSectorAddr >> 0) & 0xFF);
WRITE_NAND_ADDRESS((uSectorAddr >> 8) & 0xFF);
WRITE_NAND_ADDRESS((uSectorAddr >> 16) & 0xFF);
WRITE_NAND_COMMAND(CMD_READ_2);
/* Wait for flash to be ready (can't pool on status, read upper WARNING) */
NAND_WAIT_READY();
NAND_WAIT_READY(); /* Need to be done twice, READY detected too early the first time? */
/* Read loop */
if (pNandInfo->uDataBusWidth)
{ /* 16 bits */
for(i=0; i<uBytesToRead/2; i++) /* Div2 because of 16bits */
{
*((short*)pOutBuffer) = READ_NAND16();
pOutBuffer+=2;
}
} else {
for(i=0; i<uBytesToRead; i++)
{
*pOutBuffer++ = READ_NAND();
}
}
exit:
/* Disable the chip */
NAND_DISABLE_CE();
return bRet;
}
#endif
/*------------------------------------------------------------------------------*/
/* \fn AT91F_NandRead */
/* \brief Read Sector Algorithm */
/*------------------------------------------------------------------------------*/
static BOOL AT91F_NandRead(PSNandInfo pNandInfo, unsigned int uBlockNb, unsigned int uSectorNb, unsigned int uSpareValue, char *pOutBuffer)
{
PSSectorInfo pSectorInfo;
unsigned int uSectorAddr = uBlockNb * pNandInfo->uBlockNbData + uSectorNb * pNandInfo->uDataNbBytes;
/* If uSectorNb = 0 -> First sector of the Block so read Spare bytes */
if (!uSectorNb)
{
/* Read First Page Spare zone */
AT91F_NandReadSector(pNandInfo, uSectorAddr, pOutBuffer, ZONE_INFO);
pSectorInfo = (PSSectorInfo)&pOutBuffer[pNandInfo->uDataNbBytes];
if (pSectorInfo->bBadBlock != 0xFF)
{
return FALSE;
}
/* Read Second Page Spare zone */
AT91F_NandReadSector(pNandInfo, uSectorAddr + pNandInfo->uDataNbBytes, pOutBuffer, ZONE_INFO);
pSectorInfo = (PSSectorInfo)&pOutBuffer[pNandInfo->uDataNbBytes];
if (pSectorInfo->bBadBlock != 0xFF)
{
return FALSE;
}
}
return AT91F_NandReadSector(pNandInfo, uSectorAddr, pOutBuffer, ZONE_DATA);
}
/*------------------------------------------------------------------------------*/
/* \fn load_nandflash */
/* \brief load from nandflash */
/*------------------------------------------------------------------------------*/
int load_nandflash(unsigned int img_addr, unsigned int img_size, unsigned int img_dest)
{
SNandInfo sNandInfo;
PSNandInitInfo pNandInitInfo;
unsigned char *pOutBuffer = (unsigned char*)img_dest;
unsigned int blockIdx, badBlock, blockRead, length, sizeToRead, nbSector, newBlock, sectorIdx, blockError, sectorSize;
nandflash_hw_init();
/* Read Nand Chip ID */
pNandInitInfo = AT91F_NandReadID();
if (!pNandInitInfo)
{
#ifdef CFG_DEBUG
dbg_print("\n\r-E- No NandFlash detected !!!\n\r");
#endif
return -1;
}
/* Initialize NandInfo Structure */
AT91F_NandInit(&sNandInfo, pNandInitInfo);
if (sNandInfo.uDataBusWidth)
nandflash_cfg_16bits_dbw_init();
/* Initialize the block offset */
blockIdx = img_addr / sNandInfo.uBlockNbData;
/* Initialize the number of bad blocks */
badBlock = 0;
blockRead = 0;
length = img_size;
while (length > 0)
{
/* Read a buffer corresponding to a block in the origin file */
if (length < sNandInfo.uBlockNbData)
{
sizeToRead = length;
}
else
{
sizeToRead = sNandInfo.uBlockNbData;
}
/* Adjust the number of sectors to read */
nbSector = sizeToRead / sNandInfo.uDataNbBytes;
if (sizeToRead % sNandInfo.uDataNbBytes)
{
nbSector++;
}
newBlock = 1;
/* Loop until a valid block has been read */
while (newBlock == 1)
{
/* Reset the error flag */
blockError = 0;
/* Read the sectors */
for (sectorIdx=0; (sectorIdx < nbSector) && (blockError == 0); sectorIdx++)
{
sectorSize = sizeToRead - (sectorIdx * sNandInfo.uDataNbBytes);
if (sectorSize < sNandInfo.uDataNbBytes)
{
sectorSize = sizeToRead - (sectorIdx * sNandInfo.uDataNbBytes);
}
else
{
sectorSize = sNandInfo.uDataNbBytes;
}
/* Read the sector */
if (AT91F_NandRead(&sNandInfo, blockIdx, sectorIdx, ZONE_DATA, pOutBuffer) == FALSE)
{
blockError = 1;
}
else
{
pOutBuffer+=sNandInfo.uDataNbBytes;
}
}
if (blockError == 0)
{
/* If the block is valid exit */
newBlock = 0;
}
blockIdx++;
}
/* Decrement length */
length -= sizeToRead;
blockRead++;
}
return 0;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -