📄 flash.c
字号:
u16Tmp = *pu16OpC;
u16FlshID = ((UINT8)ftohs(u16Tmp)) << 8;
// read device id
pu16OpC++;
u16Tmp = *pu16OpC;
u16FlshID |= ((UINT8)ftohs(u16Tmp));
// exit autoselect mode
*pu16OpC = htofs(0x00F0);
INTR_vCriticalSectionLeave();
DBG_PRN_FLSH(" FLSH: AMDid=[%04X]", u16FlshID);
return u16FlshID;
}
static UINT16 s_u16ReadSstId (UINT32 u32Addr)
{
volatile UINT8 *pbyOpA, *pbyOpB, *pbyOpC;
UINT16 u16FlshID;
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
u16FlshID = 0;
// SST read manufacturer id procedure
pbyOpA = (PUINT8)((u32Addr & 0xFFFF0000) | 0x5555);
pbyOpB = (PUINT8)((u32Addr & 0xFFFF0000) | 0x2AAA);
pbyOpC = (PUINT8)(u32Addr & 0xFFF80000);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
// enter product identifier mode
*pbyOpA = 0xAA;
*pbyOpB = 0x55;
*pbyOpA = 0x90;
// read manufacturer id
SOC_vDelayPoll(5);
u16FlshID = (*pbyOpC) << 8;
// read device id
pbyOpC++;
u16FlshID |= (*pbyOpC);
// exit product identifier mode
*pbyOpC = 0xF0;
SOC_vDelayPoll(5);
INTR_vCriticalSectionLeave();
DBG_PRN_FLSH(" FLSH: SSTid=[%04X]", u16FlshID);
return u16FlshID;
}
static void s_vConfigFlshIdAndBase (UINT32 u32Addr)
{
// try AMD read manufacturer and device id procedure
sg_wFlshID = s_u16ReadAmdId(u32Addr);
if (sg_wFlshID == AMD_MANU_ID) {
// if ROM0 is AMD
if (s_u16ReadAmdId(ASIC_ROM_BASE_ADDR) == AMD_MANU_ID)
sg_u32FlshBase = ASIC_ROM_BASE_ADDR;
else
sg_u32FlshBase = ASIC_ROM_BASE_ADDR + ASIC_ROM_0_SIZE;
}
else {
sg_wFlshID = s_u16ReadSstId(u32Addr);
sg_u32FlshBase = ASIC_ROM_BASE_ADDR;
}
sg_u32FlshBase |= ASIC_NON_CACHE_ADDR;
}
static void s_vEraseSect (UINT32 u32SectAddr)
{
volatile UINT8 *pbyOpA, *pbyOpB, *pbyOpC;
volatile UINT16 *pu16OpA, *pu16OpB, *pu16OpC;
UINT8 byTmp1 = 0, byTmp2 = 0;
UINT16 u16Tmp;
if (sg_wFlshID == AMD_MANU_ID) {
pu16OpA = (PUINT16)(sg_u32FlshBase | (0x555 << 1));
pu16OpB = (PUINT16)(sg_u32FlshBase | (0x2AA << 1));
pu16OpC = (PUINT16)u32SectAddr;
*pu16OpA = htofs(0x00AA);
*pu16OpB = htofs(0x0055);
*pu16OpA = htofs(0x0080);
*pu16OpA = htofs(0x00AA);
*pu16OpB = htofs(0x0055);
*pu16OpC = htofs(0x0030);
// check toggle bit
do {
u16Tmp = *pu16OpC;
byTmp1 = (UINT8)ftohs(u16Tmp);
u16Tmp = *pu16OpC;
byTmp2 = (UINT8)ftohs(u16Tmp);
byTmp1 ^= byTmp2;
} while (byTmp1 & 0x40);
}
else if (sg_wFlshID == SST_MANU_ID) {
pbyOpA = (PUINT8)(sg_u32FlshBase | 0x5555);
pbyOpB = (PUINT8)(sg_u32FlshBase | 0x2AAA);
pbyOpC = (PUINT8)u32SectAddr;
*pbyOpA = 0xAA;
*pbyOpB = 0x55;
*pbyOpA = 0x80;
*pbyOpA = 0xAA;
*pbyOpB = 0x55;
*pbyOpC = 0x30;
// check toggle bit
do {
byTmp1 = *pbyOpC;
byTmp2 = *pbyOpC;
byTmp1 ^= byTmp2;
} while (byTmp1 & 0x40);
}
}
static void s_vProgramSect (UINT32 u32SectAddr, UINT32 u32SectSize, BOOL bEndianConvt)
{
volatile UINT8 *pbyOpA, *pbyOpB, *pbyOpC;
volatile UINT16 *pu16OpA, *pu16OpB, *pu16OpC;
UINT8 byTmp1 = 0, byTmp2 = 0;
UINT16 u16Index = 0;
UINT16 u16Tmp;
if (sg_wFlshID == AMD_MANU_ID) {
pu16OpA = (PUINT16)(sg_u32FlshBase | (0x555 << 1));
pu16OpB = (PUINT16)(sg_u32FlshBase | (0x2AA << 1));
pu16OpC = (PUINT16)u32SectAddr;
// enter unlock bypass mode
*pu16OpA = htofs(0x00AA);
*pu16OpB = htofs(0x0055);
*pu16OpA = htofs(0x0020);
for (u16Index = 0; u16Index < (u32SectSize / 2); u16Index++) {
// unlock bypass program
*pu16OpA = htofs(0x00A0);
u16Tmp = *(((PUINT16)sg_abyBuf) + u16Index);
if (bEndianConvt)
u16Tmp = REV_WORD(u16Tmp);
pu16OpC[u16Index] = u16Tmp;
// check toggle bit
do {
u16Tmp = *pu16OpC;
byTmp1 = (UINT8)ftohs(u16Tmp);
u16Tmp = *pu16OpC;
byTmp2 = (UINT8)ftohs(u16Tmp);
byTmp1 ^= byTmp2;
} while (byTmp1 & 0x40);
}
// exit unlock bypass mode
*pu16OpA = htofs(0x0090);
*pu16OpA = htofs(0x0000);
}
else if (sg_wFlshID == SST_MANU_ID) {
pbyOpA = (PUINT8)(sg_u32FlshBase | 0x5555);
pbyOpB = (PUINT8)(sg_u32FlshBase | 0x2AAA);
pbyOpC = (PUINT8)u32SectAddr;
for (u16Index = 0; u16Index < u32SectSize; u16Index++) {
*pbyOpA = 0xAA;
*pbyOpB = 0x55;
*pbyOpA = 0xA0;
pbyOpC[u16Index] = sg_abyBuf[u16Index];
// check toggle bit
do {
byTmp1 = *pbyOpC;
byTmp2 = *pbyOpC;
byTmp1 ^= byTmp2;
} while (byTmp1 & 0x40);
}
}
}
static BOOL s_bVerifyBlock (UINT32 u32Addr, PUINT8 pu8Data, UINT32 u32BlockSize, BOOL bEndianConvt)
{
UINT32 u32Idx;
u32Addr |= ASIC_NON_CACHE_ADDR; // For non-cache access
if (bEndianConvt) {
for (u32Idx = 0; u32Idx < u32BlockSize; u32Idx += 2) {
if ((*(PUINT16)(u32Addr + u32Idx)) != REV_WORD(*(PUINT16)(pu8Data + u32Idx)))
return FALSE;
}
}
else {
for (u32Idx = 0; u32Idx < u32BlockSize; u32Idx++) {
if ((*(PUINT8)(u32Addr + u32Idx)) != *(pu8Data + u32Idx)) {
DBG_PRN_FLSH(" FLSH: [%04X]!=[%04X]", *(PUINT8)(u32Addr + u32Idx), *(pu8Data + u32Idx));
return FALSE;
}
}
}
return TRUE;
}
//
// Sector Erase operation
//
void FLSH_vEraseSect (UINT32 u32SectAddr)
{
u32SectAddr |= ASIC_NON_CACHE_ADDR; // For non-cache access
s_vConfigFlshIdAndBase(u32SectAddr);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
s_vEraseSect(u32SectAddr);
INTR_vCriticalSectionLeave();
}
//
// Sector Program operation
//
void FLSH_vProgramSect (UINT32 u32SectAddr, UINT32 u32SectSize)
{
u32SectAddr |= ASIC_NON_CACHE_ADDR; // For non-cache access
s_vConfigFlshIdAndBase(u32SectAddr);
// protect flash erase/program address sequence from being interrupted
INTR_vCriticalSectionEnter();
s_vProgramSect(u32SectAddr, u32SectSize, FALSE);
INTR_vCriticalSectionLeave();
}
BOOL FLSH_bUpdateChksum (UINT32 u32StartAddr, UINT32 u32EndAddr)
{
UINT32 u32ChkSum = 0;
UINT16 u16ChkSum;
UINT16 u16TmpBuf;
UINT32 uu;
UINT32 u32Size = u32EndAddr - u32StartAddr;
// if not 2-byte alignment, error
if ((u32Size % 2) != 0)
return FALSE;
for (uu = 0; uu < (u32Size / 2); uu++) {
FLSH_bReadBlock(u32StartAddr + uu * 2, (PUINT8)&u16TmpBuf, 2);
u32ChkSum += u16TmpBuf;
}
u16ChkSum = ((UINT16)u32ChkSum) + ((UINT16)(u32ChkSum >> 16));
u16ChkSum = ~u16ChkSum;
if (!FLSH_bWriteBlock(u32EndAddr, (PUINT8)(&u16ChkSum), 2, FALSE))
return FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -