📄 flash.c
字号:
UINT32 base,
UINT32 block,
BOOL lock
)
{
return TRUE;
}
//------------------------------------------------------------------------------
static BOOL
LockDownBlock2(
OAL_FLASH_INFO *pInfo,
UINT32 base,
UINT32 block
)
{
return TRUE;
}
//------------------------------------------------------------------------------
static BOOL
EraseBlock2(
OAL_FLASH_INFO *pInfo,
UINT32 base,
UINT32 block
)
{
UINT32 code;
UINT8 bits;
// Start block reset
WriteCommand(pInfo, base, 0x0555, 0xAA);
WriteCommand(pInfo, base, 0x02AA, 0x55);
WriteCommand(pInfo, base, 0x0555, 0x80);
WriteCommand(pInfo, base, 0x0555, 0xAA);
WriteCommand(pInfo, base, 0x02AA, 0x55);
WriteCommand(pInfo, block, 0, 0x30);
// Wait until it is done
while (TRUE)
{
bits = BitsAnd(pInfo, block, 0);
if ((bits & (1 << 5)) == 0) continue;
code = INREG32((UINT32*)block);
if (code == 0xFFFFFFFF) break;
break;
}
// Switch back to read mode
WriteCommand(pInfo, base, 0, 0xF0);
return (code == 0xFFFFFFFF);
}
//------------------------------------------------------------------------------
static BOOL
StartEraseBlock2(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
return FALSE;
}
//------------------------------------------------------------------------------
static UINT32
ContinueEraseBlock2(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
return OAL_FLASH_ERASE_FAILED;
}
//------------------------------------------------------------------------------
static UINT32
WriteData2(
OAL_FLASH_INFO *pInfo,
UINT32 base,
UINT32 pos,
VOID *pBuffer
)
{
UINT32 size = 0;
UINT32 code;
UINT8 bits;
// Set flash memory to write mode
WriteCommand(pInfo, base, 0x555, 0xAA);
WriteCommand(pInfo, base, 0x2AA, 0x55);
WriteCommand(pInfo, base, 0x555, 0xA0);
// Now write info and wait until it is done
switch (pInfo->width)
{
case 4:
OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
while (TRUE)
{
bits = BitsAnd(pInfo, pos, 0);
if ((bits & (1 << 5)) == 0) continue;
code = INREG32((UINT32*)pos);
break;
}
if (code == *(UINT32*)pBuffer) size = sizeof(UINT32);
break;
case 2:
OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
while (TRUE)
{
bits = BitsAnd(pInfo, pos, 0);
if ((bits & (1 << 5)) == 0) continue;
code = INREG16((UINT16*)pos);
break;
}
if (code == *(UINT16*)pBuffer) size = sizeof(UINT16);
break;
case 1:
OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
while (TRUE)
{
bits = BitsAnd(pInfo, pos, 0);
if ((bits & (1 << 5)) == 0) continue;
code = INREG8((UINT8*)pos);
break;
}
if (code == *(UINT8*)pBuffer) size = sizeof(UINT8);
break;
}
return size;
}
#endif OAL_FLASH_NO_COMMAND_SET_2
//------------------------------------------------------------------------------
// Common code
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Function: OALFlashInfo
//
// This function read NOR flash memory layout via CFI.
//
// Note: please pass through Uncached Address (pBase)!
//
BOOL
OALFlashInfo(
VOID *pBase,
OAL_FLASH_INFO *pInfo
)
{
BOOL rc = FALSE;
UINT32 base = (UINT32)pBase;
UINT32 code1, code2, code3;
UINT32 i;
OALMSG(OAL_FUNC, (L"+OALFlashInfo(0x%08x, ...)\r\n", pBase));
// Just to avoid possible problems
memset(pInfo, 0, sizeof(*pInfo));
// Try 32-bit geometry
OUTREG32((UINT32*)(base + 4 * 0x55), 0x98989898);
code1 = INREG32((UINT32*)(base + 4 * 0x10));
code2 = INREG32((UINT32*)(base + 4 * 0x11));
code3 = INREG32((UINT32*)(base + 4 * 0x12));
if (code1 == 'QQQQ' && code2 == 'RRRR' && code3 == 'YYYY')
{
pInfo->width = 4;
pInfo->parallel = 4;
}
else if (code1 == 'Q\0Q\0' && code2 == 'R\0R\0' && code3 == 'Y\0Y\0')
{
pInfo->width = 4;
pInfo->parallel = 2;
}
else if (code1 == 'Q\0\0\0' && code2 == 'R\0\0\0' && code3 == 'Y\0\0\0')
{
pInfo->width = 4;
pInfo->parallel = 1;
}
else
{
// Now try luck with 16-bit geometry
OUTREG16((UINT16*)(base + 2 * 0x55), 0x0098);
code1 = INREG16((UINT16*)(base + 2 * 0x10));
code2 = INREG16((UINT16*)(base + 2 * 0x11));
code3 = INREG16((UINT16*)(base + 2 * 0x12));
if (code1 == 'QQ' && code2 == 'RR' && code3 == 'YY')
{
pInfo->width = 2;
pInfo->parallel = 2;
}
else if (code1 == '\0Q' && code2 == '\0R' && code3 == '\0Y')
{
pInfo->width = 2;
pInfo->parallel = 1;
}
else
{
// So last opportunity is 8-bit mode
OUTREG8((UINT8*)(base + 0x55), 0x98);
code1 = INREG8((UINT8*)(base + 0x10));
code2 = INREG8((UINT8*)(base + 0x11));
code3 = INREG8((UINT8*)(base + 0x12));
if (code1 == 'Q' && code2 == 'R' && code3 == 'Y')
{
pInfo->width = 1;
pInfo->parallel = 1;
}
else
{
goto cleanUp;
}
}
}
// Read primary command set, size, burst size and number of regions
pInfo->set = ReadInfo(pInfo, base, 0x13, 0, 1);
pInfo->size = 1 << ReadInfo(pInfo, base, 0x27, 0, 1);
pInfo->burst = 1 << ReadInfo(pInfo, base, 0x2A, 0, 1);
pInfo->regions = ReadInfo(pInfo, base, 0x2C, 0, 1);
// Verify that parallel chips are same
for (i = 1; i < pInfo->parallel; i++)
{
if ( (pInfo->set != ReadInfo(pInfo, base, 0x13, i, 1)) ||
(pInfo->size != (1 << ReadInfo(pInfo, base, 0x27, 0, 1))) ||
(pInfo->burst != (1 << ReadInfo(pInfo, base, 0x2A, 0, 1))) ||
(pInfo->regions != ReadInfo(pInfo, base, 0x2C, 0, 1)) )
{
goto cleanUp;
}
}
// If there is more regions than expected
if (pInfo->regions > 8) goto cleanUp;
// Read region info
for (i = 0; i < pInfo->regions; i++)
{
code1 = ReadInfo(pInfo, base, 0x2d + (i << 2), 0, 4);
pInfo->aBlocks[i] = (code1 & 0xFFFF) + 1;
pInfo->aBlockSize[i] = (code1 >> 8) & 0x00FFFF00;
if (pInfo->aBlockSize[i] == 0) pInfo->aBlockSize[i] = 128;
}
// Switch back to read mode
switch (pInfo->set)
{
case 1: // Intel/Sharp
case 3:
WriteCommand(pInfo, base, 0, 0xFF);
break;
case 2: // AMD/Fujitsu
WriteCommand(pInfo, base, 0, 0xF0);
break;
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashInfo(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL
OALFlashTiming(
VOID *pBase,
OAL_FLASH_TIMING *pTimingInfo
)
{
BOOL rc = FALSE;
UINT32 base = (UINT32)pBase;
OAL_FLASH_INFO info;
// Ther read first chip info
if (!OALFlashInfo((VOID*)base, &info)) goto cleanUp;
// Switch to CFI Query
WriteCommand(&info, base, 0x55, 0x98);
// Read timeout parameters
pTimingInfo->writeDelay = ReadInfo(&info, base, 0x1F, 0, 1);
pTimingInfo->writeTimeout = ReadInfo(&info, base, 0x23, 0, 1);
pTimingInfo->bufferDelay = ReadInfo(&info, base, 0x20, 0, 1);
pTimingInfo->bufferTimeout = ReadInfo(&info, base, 0x24, 0, 1);
pTimingInfo->eraseDelay = ReadInfo(&info, base, 0x21, 0, 1);
pTimingInfo->eraseTimeout = ReadInfo(&info, base, 0x25, 0, 1);
// Switch back to read mode
switch (info.set)
{
case 1: // Intel/Sharp
case 3:
WriteCommand(&info, base, 0, 0xFF);
break;
case 2: // AMD/Fujitsu
WriteCommand(&info, base, 0, 0xF0);
break;
}
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALFlashLock
//
// This function locks/unlocks region on NOR flash memory.
//
BOOL
OALFlashLock(
VOID *pBase,
VOID *pStart,
DWORD size,
BOOL lock
)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base = (UINT32)pBase;
UINT32 start = (UINT32)pStart;
UINT32 end, chip, blockStart, blockEnd;
UINT32 region, block;
// First get end addresss
end = start + size;
// Ther read first chip info
if (!OALFlashInfo((VOID*)base, &info))
{
goto cleanUp;
}
region = block = 0;
blockStart = chip = base;
while (blockStart < end)
{
// Block end
blockEnd = blockStart + info.aBlockSize[region] * info.parallel;
// Should block be erased?
if (start < blockEnd && end >= blockStart)
{
switch (info.set)
{
#ifndef OAL_FLASH_NO_COMMAND_SET_1
case 1: // Intel/Sharp
case 3:
if (!LockBlock1(&info, chip, blockStart, lock))
{
goto cleanUp;
}
break;
#endif OAL_FLASH_NO_COMMAND_SET_1
#ifndef OAL_FLASH_NO_COMMAND_SET_2
case 2: // AMD
if (!LockBlock2(&info, chip, blockStart, lock))
{
goto cleanUp;
}
break;
#endif OAL_FLASH_NO_COMMAND_SET_2
default:
goto cleanUp;
}
}
// Move to next block
blockStart = blockEnd;
if (blockStart >= end) break;
if (++block >= info.aBlocks[region])
{
block = 0;
if (++region >= info.regions)
{
// Try read next chip layout
if (!OALFlashInfo((VOID*)block, &info)) break;
region = 0;
chip = block;
}
}
}
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALFlashErase
//
// Note: please pass through Uncached Addresses (pBase, pStart)!
//
BOOL OALFlashErase(
VOID *pBase,
VOID *pStart,
UINT32 size
)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base = (UINT32)pBase;
UINT32 start = (UINT32)pStart;
UINT32 end = start + size;
UINT32 chip, blockStart, blockEnd;
UINT32 region, block;
OALMSG(OAL_FUNC, (
L"+OALFlashErase(0x%08x, 0x%08x, 0x%08x)\r\n", pBase, pStart, size
));
// Read first chip layout
if (!OALFlashInfo((VOID*)base, &info))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashErase failed get flash memory info\r\n"
));
goto cleanUp;
}
region = block = 0;
blockStart = chip = base;
while (blockStart < end)
{
// Block end (+1)
blockEnd = blockStart + info.aBlockSize[region] * info.parallel;
// Should block be erased?
if (start < blockEnd && end >= blockStart)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -