📄 nor.c
字号:
// Write Data
flash_write_databuffer(pNorInfo, &address,(void*)data, numBytes);
// Program Buffer to Flash Confirm Write
flash_write_cmd(pNorInfo, blkAddress, 0, AMD_WRT_BUF_CONF_CMD);
// Read last data item
data_temp = flash_read_data(pNorInfo, (Uint32) (data + (address - startAddress)), 0);
while(TRUE)
{
//temp1 = flash_read_data(address, 0 );
if( (flash_read_data(pNorInfo, address, 0 ) & (BIT7 | BIT15)) == (data_temp & (BIT7 | BIT15) ) )
{
break;
}
else
{
// Timeout has occurred
if(flash_issetall(pNorInfo,address, 0, BIT5))
{
if( (flash_read_data(pNorInfo,address, 0 ) & (BIT7 | BIT15)) != (data_temp & (BIT7 | BIT15) ) )
{
printf("Timeout ocurred.\r\n",FALSE);
retval = E_FAIL;
}
break;
}
// Abort has occurred
if(flash_issetall(pNorInfo, address, 0, BIT1))
{
if( (flash_read_data(pNorInfo, address, 0 ) & (BIT7 | BIT15)) != (data_temp & (BIT7 | BIT15) ) )
{
printf("Abort ocurred.\r\n",FALSE);
retval = E_FAIL;
AMD_Write_Buf_Abort_Reset_Flash (pNorInfo);
}
break;
}
}
}
// Put chip back into read array mode.
AMD_Soft_Reset_Flash(pNorInfo);
if (retval == E_PASS)
retval = flash_verify_databuffer(pNorInfo, startAddress,(void*)data, numBytes);
return retval;
}
// AMD Write Buf Abort Reset Flash
void AMD_Write_Buf_Abort_Reset_Flash(PNOR_INFO pNorInfo)
{
// Reset Flash to be in Read Array Mode
AMD_Prefix_Commands(pNorInfo);
AMD_Soft_Reset_Flash(pNorInfo);
}
// ---------------------------------------------------------------------------
//--------------------- End of AMD specific commands ------------------------
// ---------------------------------------------------------------------------
// Get info on block address and sizes
Uint32 NOR_GetBlockInfo(PNOR_INFO pNorInfo, Uint32 address, Uint32* blockSize, Uint32* blockAddr)
{
Int32 i;
Uint32 currRegionAddr, nextRegionAddr;
currRegionAddr = (Uint32) pNorInfo->flashBase;
if ((address < currRegionAddr) || (address >= (currRegionAddr+pNorInfo->flashSize)))
{
return E_FAIL;
}
for(i=0; i< (pNorInfo->numberRegions); i++)
{
nextRegionAddr = currRegionAddr + (pNorInfo->blockSize[i] * pNorInfo->numberBlocks[i]);
if ( (currRegionAddr <= address) && (nextRegionAddr > address) )
{
*blockSize = pNorInfo->blockSize[i];
*blockAddr = address & (~((*blockSize) - 1));
break;
}
currRegionAddr = nextRegionAddr;
}
return E_PASS;
}
// --------------------------- NOR API Functions -----------------------------
//Initialize the AEMIF subsystem and settings
PNOR_INFO NOR_Open(Uint32 baseCSAddr)
{
VUint32 *ABCR;
PNOR_INFO pNorInfo;
Uint8 width;
// Alloc the main NOR structue
pNorInfo = (PNOR_INFO) ubl_alloc_mem(sizeof(NOR_INFO));
// Set NOR flash base address
pNorInfo->flashBase = baseCSAddr;
//Get the CSOffset (can be 0 through 3 - corresponds with CS2 through CS5)
pNorInfo->CSOffset = ( ( pNorInfo->flashBase & (0x0FFFFFFF)) >> 25) - 1;
// Set width to 8 or 16
width = ( ( (SYSTEM->BOOTCFG) >> 5) & 0x1 );
pNorInfo->busWidth = (width)?BUS_16BIT:BUS_8BIT;
// Select ASYNC EMIF Address Lines
SYSTEM->PINMUX[0] = 0xC1F;
// Program Asynchronous Wait Cycles Configuration Control Register
AEMIF->AWCCR |= 0x0 ;
// Program Asynchronous Bank3-5 Register
ABCR = &(AEMIF->AB1CR);
ABCR[pNorInfo->CSOffset] = 0x3FFFFFFC | width; // Adjust for quicker access times
// Perform CFI Query
if (QueryCFI(pNorInfo) == E_PASS)
{
// Below is specifically needed to check for AMD flash on DVEVM (rev. D or earlier)
// since it's top address line is not connected (don't ask me why)
if (pNorInfo->numberRegions == 1)
{
pNorInfo->flashBase += (pNorInfo->flashSize>>1);
if ( QueryCFI(pNorInfo) == E_PASS )
{
pNorInfo->flashSize >>= 1;
pNorInfo->flashBase -= pNorInfo->flashSize;
pNorInfo->numberBlocks[0] >>= 1;
}
else
{
pNorInfo->flashBase -= (pNorInfo->flashSize>>1);
}
}
}
else
{
printf("CFI query failed.\r\n", FALSE);
return NULL;
}
// Setup function pointers
printf("NOR Initialization:\r\n", FALSE);
printf("\tCommand Set: ", FALSE);
switch (pNorInfo->commandSet)
{
case AMD_BASIC_CMDSET:
case AMD_EXT_CMDSET:
Flash_Erase = &AMD_Erase;
Flash_BufferWrite = &AMD_BufferWrite;
Flash_Write = &AMD_Write;
Flash_ID = &AMD_ID;
printf("AMD\r\n", FALSE);
break;
case INTEL_BASIC_CMDSET:
case INTEL_EXT_CMDSET:
Flash_Erase = &Intel_Erase;
Flash_BufferWrite = &Intel_BufferWrite;
Flash_Write = &Intel_Write;
Flash_ID = &Intel_ID;
printf("Intel\r\n", FALSE);
break;
default:
Flash_Write = &Unsupported_Write;
Flash_BufferWrite = &Unsupported_BufferWrite;
Flash_Erase = &Unsupported_Erase;
Flash_ID = &Unsupported_ID;
printf("Unknown\r\n", FALSE);
break;
}
if ( (*Flash_ID)(pNorInfo) != E_PASS)
{
printf("NOR ID failed.\r\n", FALSE);
return NULL;
}
printf("\tManufacturer: ", FALSE);
switch(pNorInfo->manfID)
{
case AMD:
printf("AMD", FALSE);
break;
case FUJITSU:
printf("FUJITSU", FALSE);
break;
case INTEL:
printf("INTEL", FALSE);
break;
case MICRON:
printf("MICRON", FALSE);
break;
case SAMSUNG:
printf("SAMSUNG", FALSE);
break;
case SHARP:
printf("SHARP", FALSE);
break;
default:
printf("Unknown", FALSE);
break;
}
printf("\r\n", FALSE);
printf("\tSize: %d MB\r\n", pNorInfo->flashSize>>20);
return pNorInfo;
}
//Global Erase NOR Flash
Uint32 NOR_GlobalErase(PNOR_INFO pNorInfo)
{
return NOR_Erase( pNorInfo, (VUint32) pNorInfo->flashBase, (VUint32) pNorInfo->flashSize );
}
// Erase Flash Block
Uint32 NOR_Erase(PNOR_INFO pNorInfo, VUint32 start_address, VUint32 size)
{
VUint32 addr = start_address;
VUint32 range = start_address + size;
Uint32 blockSize, blockAddr;
printf("Erasing the NOR Flash\r\n", FALSE);
while (addr < range)
{
if (NOR_GetBlockInfo(pNorInfo, addr, &blockSize, &blockAddr) != E_PASS)
{
printf("Address out of range", FALSE);
return E_FAIL;
}
//Increment to the next block
if ( (*Flash_Erase)(pNorInfo, blockAddr) != E_PASS)
{
printf("Erase failure at block address 0x%x\r\n",blockAddr);
return E_FAIL;
}
addr = blockAddr + blockSize;
// Show status messages
printf("Erased through 0x%x\r\n", addr);
}
printf("Erase Completed\r\n", FALSE);
return(E_PASS);
}
// NOR_WriteBytes
Uint32 NOR_WriteBytes( PNOR_INFO pNorInfo,
Uint32 writeAddress,
Uint32 numBytes,
Uint32 readAddress)
{
Uint32 blockSize, blockAddr;
Int32 i;
Uint32 retval = E_PASS;
printf("Writing the NOR Flash\r\n", FALSE);
// Make numBytes even if needed
if (numBytes & 0x00000001)
numBytes++;
if (NOR_GetBlockInfo(pNorInfo, writeAddress, &blockSize, &blockAddr) != E_PASS)
{
printf("Address out of range", FALSE);
return E_FAIL;
}
while (numBytes > 0)
{
if( (numBytes < pNorInfo->bufferSize) || (writeAddress & (pNorInfo->bufferSize-1) ))
{
if ((*Flash_Write)(pNorInfo, writeAddress, flash_read_data(pNorInfo,readAddress,0) ) != E_PASS)
{
printf("\r\nNormal Write Failed.\r\n", FALSE);
retval = E_FAIL;
}
else
{
numBytes -= pNorInfo->busWidth;
writeAddress += pNorInfo->busWidth;
readAddress += pNorInfo->busWidth;
}
}
else
{
// Try to use buffered writes
if((*Flash_BufferWrite)(pNorInfo, writeAddress, (VUint8 *)readAddress, pNorInfo->bufferSize) == E_PASS)
{
numBytes -= pNorInfo->bufferSize;
writeAddress += pNorInfo->bufferSize;
readAddress += pNorInfo->bufferSize;
}
else
{
// Try normal writes as a backup
for(i = 0; i<(pNorInfo->bufferSize>>1); i++)
{
if ((*Flash_Write)(pNorInfo, writeAddress, flash_read_data(pNorInfo,readAddress,0) ) != E_PASS)
{
printf("\r\nNormal write also failed\r\n", FALSE);
retval = E_FAIL;
break;
}
else
{
numBytes -= pNorInfo->busWidth;
writeAddress += pNorInfo->busWidth;
readAddress += pNorInfo->busWidth;
}
}
}
}
// Output status info on the write operation
if (retval == E_PASS)
{
if ( ((writeAddress & (~((blockSize>>4)-1))) == writeAddress) || (numBytes == 0) )
{
printf("NOR Write OK through 0x%x\r\n", writeAddress);
if (NOR_GetBlockInfo(pNorInfo, writeAddress, &blockSize, &blockAddr) != E_PASS)
{
printf("Address out of range", FALSE);
return E_FAIL;
}
}
}
else
{
printf( "NOR Write Failed...Aborting!\r\n", FALSE);
return E_FAIL;
}
}
return retval;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -