📄 flash.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
// This file implements CFI NOR flash memory erase and write functions.
//
#include <windows.h>
#include <oal.h>
//------------------------------------------------------------------------------
static struct {
BOOL pending;
OAL_FLASH_INFO info;
UINT32 base;
UINT32 end;
UINT32 pos;
UINT32 region;
UINT32 block;
} s_erase;
//------------------------------------------------------------------------------
static UCHAR
BitsOr(
OAL_FLASH_INFO *pInfo,
DWORD base,
ULONG offset
)
{
UCHAR bits = 0;
DWORD data;
ULONG width = pInfo->width;
ULONG parallel = pInfo->parallel;
switch (width)
{
case 4:
data = INREG32((UINT32*)(base + (offset << 2)));
switch (parallel)
{
case 4:
bits = (UCHAR)(((data >> 24)&0xFF) | ((data >> 16)&0xFF));
bits |= (UCHAR)(((data >> 8)&0xFF) | ((data >> 0)&0xFF));
break;
case 2:
bits = (UCHAR)(((data >> 16)&0xFF) | ((data >> 0)&0xFF));
break;
case 1:
bits = (UCHAR)(data&0xFF);
break;
}
break;
case 2:
data = INREG16((UINT16*)(base + (offset << 1)));
switch (parallel)
{
case 2:
bits = (UCHAR)(((data >> 8)&0xFF) | ((data >> 0)&0xFF));
break;
case 1:
bits = (UCHAR)(data&0xFF);
break;
}
break;
case 1:
bits = INREG8((UINT8*)(base + offset));
break;
}
return bits;
}
//------------------------------------------------------------------------------
static UCHAR
BitsAnd(
OAL_FLASH_INFO *pInfo,
DWORD base,
ULONG offset
)
{
UINT8 bits = 0;
UINT32 data;
ULONG width = pInfo->width;
ULONG parallel = pInfo->parallel;
switch (width)
{
case 4:
data = INREG32((UINT32*)(base + (offset << 2)));
switch (parallel)
{
case 4:
bits = (UCHAR)(((data >> 24)&0xFF) & ((data >> 16)&0xFF));
bits &= (UCHAR)(((data >> 8)&0xFF) & ((data >> 0)&0xFF));
break;
case 2:
bits = (UCHAR)(((data >> 16)&0xFF) & ((data >> 0)&0xFF));
break;
case 1:
bits = (UCHAR)(data&0xFF);
break;
}
break;
case 2:
data = INREG16((UINT16*)base);
switch (parallel)
{
case 2:
bits = (UCHAR)(((data >> 8)&0xFF) & ((data >> 0) & 0xFF));
break;
case 1:
bits = (UCHAR)(data&0xFF);
break;
}
break;
case 1:
bits = INREG8((UINT8*)base);
break;
}
return bits;
}
//------------------------------------------------------------------------------
static UINT32
ReadInfo(
OAL_FLASH_INFO *pInfo,
DWORD base,
ULONG offset,
ULONG shift,
ULONG size
)
{
DWORD data = 0;
ULONG count = (INT32)size;
switch (pInfo->width)
{
case 4:
if (shift >= 4) shift = 0;
while (count-- > 0)
{
data <<= 8;
data |= INREG32(
(UINT32*)(base + ((offset + count) << 2) + shift)
) & 0xFF;
}
break;
case 2:
if (shift >= 2) shift = 0;
while (count-- > 0)
{
data <<= 8;
data |= INREG16(
(UINT16*)(base + ((offset + count) << 1) + shift)
) & 0xFF;
}
break;
case 1:
while (count-- > 0)
{
data <<= 8;
data |= INREG8((UINT8*)(base + offset + count));
}
break;
}
return data;
}
//------------------------------------------------------------------------------
static VOID
WriteCommand(
OAL_FLASH_INFO *pInfo,
DWORD base,
ULONG offset,
UCHAR cmd
)
{
DWORD code;
ULONG width = pInfo->width;
ULONG parallel = pInfo->parallel;
switch (width)
{
case 4:
if (parallel == 4)
{
code = cmd | (cmd << 8) | (cmd << 16) | (cmd << 24);
}
else if (parallel == 2)
{
code = cmd | (cmd << 16);
}
else if (parallel == 1)
{
code = cmd;
}
else
{
break;
}
OUTREG32((UINT32*)(base + (offset << 2)), code);
break;
case 2:
if (parallel == 2)
{
code = cmd | (cmd << 8);
}
else if (parallel == 1)
{
code = cmd;
}
else
{
break;
}
OUTREG16((UINT16*)(base + (offset << 1)), code);
break;
case 1:
if (parallel != 1) break;
code = cmd;
OUTREG8((UINT8*)(base + offset), code);
break;
}
}
//------------------------------------------------------------------------------
// Command Set 1 support (Intel)
//------------------------------------------------------------------------------
#ifndef OAL_FLASH_NO_COMMAND_SET_1
//------------------------------------------------------------------------------
static BOOL
LockBlock1(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block,
BOOL lock
)
{
UCHAR command;
UCHAR bits;
command = lock ? 0x01 : 0xD0;
// Set block lock
WriteCommand(pInfo, block, 0, 0x60);
WriteCommand(pInfo, block, 0, command);
// Verify it is correct
WriteCommand(pInfo, block, 0x02, 0x90);
if (lock)
{
bits = BitsAnd(pInfo, block, 0x02);
}
else
{
bits = BitsOr(pInfo, block, 0x02);
}
// Reset memory back to normal state
WriteCommand(pInfo, block, 0, 0xFF);
return (((bits & (1 << 0)) != 0) == lock);
}
//------------------------------------------------------------------------------
static BOOL
LockDownBlock1(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
UCHAR bits;
// Set block lock-down
WriteCommand(pInfo, block, 0, 0x60);
WriteCommand(pInfo, block, 0, 0x2F);
// Verify it is correct
WriteCommand(pInfo, block, 0x02, 0x90);
bits = BitsAnd(pInfo, block, 0x02);
// Reset memory back to normal state
WriteCommand(pInfo, block, 0, 0xFF);
return ((bits & (1 << 1)) != 0);
}
//------------------------------------------------------------------------------
static BOOL
EraseBlock1(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
BOOL rc;
UCHAR bits;
// Start block reset
WriteCommand(pInfo, base, 0, 0x50);
WriteCommand(pInfo, block, 0, 0x20);
WriteCommand(pInfo, block, 0, 0xD0);
// Wait until it is done
do {
WriteCommand(pInfo, base, 0, 0x70);
bits = BitsAnd(pInfo, base, 0);
}
while ((bits & (1 << 7)) == 0);
// Reset memory back to normal state
WriteCommand(pInfo, base, 0, 0xFF);
// Bit 5 is zero if erase succeeded
WriteCommand(pInfo, base, 0, 0x70);
bits = BitsOr(pInfo, base, 0);
rc = (bits & (1 << 5)) == 0;
// Switch back to read mode
WriteCommand(pInfo, base, 0, 0xFF);
return rc;
}
//------------------------------------------------------------------------------
static BOOL
StartEraseBlock1(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
// Erase status register
WriteCommand(pInfo, block, 0, 0x50);
// Start block reset
WriteCommand(pInfo, block, 0, 0x20);
WriteCommand(pInfo, block, 0, 0xD0);
return TRUE;
}
//------------------------------------------------------------------------------
static UINT32
ContinueEraseBlock1(
OAL_FLASH_INFO *pInfo,
DWORD base,
DWORD block
)
{
UINT32 rc = OAL_FLASH_ERASE_PENDING;
UINT8 bits;
// Check if erase is done
WriteCommand(pInfo, block, 0, 0x70);
bits = BitsAnd(pInfo, block, 0);
if ((bits & (1 << 7)) == 0) goto cleanUp;
// Bit 5 is zero if erase succeeded
rc = (bits & (1 << 5)) == 0 ? OAL_FLASH_ERASE_DONE : OAL_FLASH_ERASE_FAILED;
cleanUp:
// Switch back to read mode
WriteCommand(pInfo, block, 0, 0xFF);
return rc;
}
//------------------------------------------------------------------------------
static UINT32
WriteData1(
OAL_FLASH_INFO *pInfo,
ULONG base,
ULONG pos,
VOID *pBuffer
)
{
UINT32 size = 0;
UINT8 bits;
// Issue write command
WriteCommand(pInfo, base, 0, 0x40);
// Now write info and wait until it is done
switch (pInfo->width)
{
case 4:
OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
break;
case 2:
OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
break;
case 1:
OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
break;
}
// Wait until write is done
WriteCommand(pInfo, base, 0, 0x70);
bits = BitsAnd(pInfo, pos, 0);
while ((bits & (1 << 7)) == 0)
{
WriteCommand(pInfo, base, 0, 0x70);
bits = BitsAnd(pInfo, pos, 0);
}
// Bit 4 is zero if write succeeded
if ((bits & (1 << 4)) == 0) size = pInfo->width;
// Reset memory back to normal state
WriteCommand(pInfo, base, 0, 0xFF);
// Return result
return size;
}
#endif OAL_FLASH_NO_COMMAND_SET_1
//------------------------------------------------------------------------------
// Command Set 2 support (AMD)
//------------------------------------------------------------------------------
#ifndef OAL_FLASH_NO_COMMAND_SET_2
//------------------------------------------------------------------------------
static BOOL
LockBlock2(
OAL_FLASH_INFO *pInfo,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -