📄 nor.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// File: flash.c
//
// This file implements CFI flash memory erase and write functions. Current
// implementation doesn't support flash/block protection bit and it doesn't
// use buffer write even if flash supports it.
//
#include <windows.h>
#include <oal.h>
#include "bsp.h"
//------------------------------------------------------------------------------
static BOOL BitZero(UINT32 code, UINT32 bit, UINT32 width, UINT32 parallel)
{
BOOL rc = FALSE;
switch (width) {
case 4:
if (parallel == 4) {
rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 8))) == 0 ||
(code & (1 << (bit + 16))) == 0 ||
(code & (1 << (bit + 24))) == 0;
} else if (parallel == 2) {
rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 16))) == 0;
} else if (parallel == 1) {
rc = (code & (1 << bit)) == 0;
}
break;
case 2:
if (parallel == 2) {
rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 8))) == 0;
} else if (parallel == 1) {
rc = (code & (1 << bit)) == 0;
}
break;
case 1:
rc = (code & (1 << bit)) == 0;
break;
}
return rc;
}
//------------------------------------------------------------------------------
//
// adjusts offset for width, reads width worth of data from that address
//
static UINT32 ReadIdentification(UINT32 base, UINT32 offset, UINT32 width)
{
UINT32 data = 0;
switch (width) {
case 4:
data = INREG32((UINT32*)(base + (offset << 2)));
break;
case 2:
data = INREG16((UINT16*)(base + (offset << 1))) & 0xFFFF;
break;
case 1:
data = INREG8((UINT8*)(base + offset)) & 0xFF;
break;
}
return data;
}
static UINT32 ReadInfo(UINT32 base, UINT32 offset, UINT32 size, UINT32 width)
{
UINT32 data = 0;
INT32 count = (INT32)size;
switch (width) {
case 4:
while (count-- > 0) {
data <<= 8;
data |= INREG32((UINT32*)(base + ((offset + count) << 2))) & 0xFF;
}
break;
case 2:
while (count-- > 0) {
data <<= 8;
data |= INREG16((UINT16*)(base + ((offset + count) << 1))) & 0xFF;
}
break;
case 1:
while (count-- > 0) {
data <<= 8;
data |= INREG8((UINT8*)(base + offset + count));
}
break;
}
return data;
}
//------------------------------------------------------------------------------
static VOID WriteCommand(
UINT32 base, UINT32 offset, UINT8 cmd, UINT32 width, UINT32 parallel
) {
UINT32 code;
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;
}
}
//------------------------------------------------------------------------------
static BOOL UnlockBlock1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
//BOOL rc;
//UINT32 code;
// Start block unlock
WriteCommand(base, 0, 0x50, pInfo->width, pInfo->parallel);
WriteCommand(block, 0, 0x60, pInfo->width, pInfo->parallel);
WriteCommand(block, 0, 0xD0, pInfo->width, pInfo->parallel);
// Note: We could (should?) verify the unlock worked
// Switch back to read mode
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
return TRUE;
}
//------------------------------------------------------------------------------
static BOOL EraseBlock1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
BOOL rc;
UINT32 code;
// Start block reset
WriteCommand(base, 0, 0x50, pInfo->width, pInfo->parallel);
WriteCommand(block, 0, 0x20, pInfo->width, pInfo->parallel);
WriteCommand(block, 0, 0xD0, pInfo->width, pInfo->parallel);
// Wait until it is done
do {
WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
code = INREG32((UINT32*)base);
} while (BitZero(code, 7, pInfo->width, pInfo->parallel));
// Reset memory back to normal state
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
// Bit 5 in code is zero if erase succeeded
rc = BitZero(code, 5, pInfo->width, pInfo->parallel);
// Switch back to read mode
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
return rc;
}
//------------------------------------------------------------------------------
static BOOL EraseBlock2(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
BOOL rc = FALSE;
UINT32 code, code2;
// Start block reset
WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x555, 0x80, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
// Wait until it is done
switch (pInfo->set) {
case 2:
WriteCommand(block, 0, 0x30, pInfo->width, pInfo->parallel);
// Poll DQ3
while (TRUE) {
code = INREG16((UINT16 *)block);
if (code & (1U << 3)) break;
}
// Poll DQ7 (done) and DQ5 (error)
while (TRUE) {
code = INREG16((UINT16 *)block);
// DQ7 goes high when successful erase completes
if (code & (1U << 7)) {
rc = TRUE;
break;
}
// DQ5 goes high if erase error
if (code & (1U << 5)) break;
}
break;
case 0x0701:
WriteCommand(block, 0, 0x80, pInfo->width, pInfo->parallel);
while (TRUE) {
code = INREG32((UINT32*)block);
code2 = INREG32((UINT32*)block);
if ((code & (1<<6)) == (code2 & (1<<6)))
break;
}
rc = TRUE;
}
// Switch back to read mode
WriteCommand(base, 0, 0xF0, pInfo->width, pInfo->parallel);
return rc;
}
//------------------------------------------------------------------------------
static UINT32 WriteData1(
ULONG base, ULONG pos, OAL_FLASH_INFO *pInfo, VOID *pBuffer
) {
UINT32 size = 0, code;
// Issue write command
WriteCommand(base, 0, 0x40, pInfo->width, pInfo->parallel);
// Now write info and wait until it is done
switch (pInfo->width) {
case 4:
OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
do {
WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
code = INREG32((UINT32*)pos);
} while (BitZero(code, 7, pInfo->width, pInfo->parallel));
if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 4;
break;
case 2:
OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
do {
WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
code = INREG16((UINT16*)pos);
} while (BitZero(code, 7, pInfo->width, pInfo->parallel));
if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 2;
break;
case 1:
OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
do {
WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
code = INREG8((UINT8*)pos);
} while (BitZero(code, 7, pInfo->width, pInfo->parallel));
if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 1;
break;
}
// Reset memory back to normal state
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
// Return result
return size;
}
//------------------------------------------------------------------------------
static ULONG WriteData2(
UINT32 base, UINT32 pos, OAL_FLASH_INFO *pInfo, VOID *pBuffer
) {
UINT32 size = 0, code = 0, code2 = 0;
// Set flash memory to write mode
WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
WriteCommand(base, 0x555, 0xA0, pInfo->width, pInfo->parallel);
// Now write info and wait until it is done
switch (pInfo->width) {
case 4:
OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
switch (pInfo->set) {
case 2:
while (TRUE) {
code = INREG32((UINT32*)pos);
if (code == *(UINT32*)pBuffer) break;
if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
code = INREG32((UINT32*)pos);
break;
}
break;
case 0x0701:
while (TRUE) {
code = INREG32((UINT32*)pos);
code2 = INREG32((UINT32*)pos);
if ((code & (1<<6)) == (code2 & (1<<6)))
break;
}
code = INREG32((UINT32*)pos);
break;
}
if (code == *(UINT32*)pBuffer) size = sizeof(UINT32);
break;
case 2:
OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
switch (pInfo->set) {
case 2:
while (TRUE) {
code = INREG16((UINT16*)pos);
if (code == *(UINT16*)pBuffer) break;
if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
code = INREG16((UINT16*)pos);
break;
}
break;
case 0x0701:
while (TRUE) {
code = INREG16((UINT32*)pos);
code2 = INREG16((UINT32*)pos);
if ((code & (1<<6)) == (code2 & (1<<6)))
break;
}
code = INREG16((UINT32*)pos);
break;
}
if (code == *(UINT16*)pBuffer) size = sizeof(UINT16);
break;
case 1:
OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
switch (pInfo->set) {
case 2:
while (TRUE) {
code = INREG8((UINT8*)pos);
if (code == *(UINT8*)pBuffer) break;
if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
code = INREG8((UINT8*)pos);
break;
}
break;
case 0x0701:
while (TRUE) {
code = INREG8((UINT32*)pos);
code2 = INREG8((UINT32*)pos);
if ((code & (1<<6)) == (code2 & (1<<6)))
break;
}
code = INREG8((UINT32*)pos);
break;
}
if (code == *(UINT8*)pBuffer) size = sizeof(UINT8);
break;
}
return size;
}
//------------------------------------------------------------------------------
static BOOL ReadIdent1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo, BYTE* pId, UINT32 count)
{
UINT32 offset = 0x81;
UINT32 i = 0;
// Start read device identification command
WriteCommand(base, 0, 0x90, pInfo->width, pInfo->parallel);
// Now read count bytes into the pId buffer
// bytes are contiguous, so don't read every other byte
while (i < count)
{
// read a width at the following offset
UINT32 Ident = ReadIdentification(block, offset, pInfo->width);
memcpy(pId, &Ident, pInfo->width);
// read a width at a time
pId += pInfo->width;
i+= pInfo->width;
// each width == 1 offset (ie reading 0x81-0x88 with a width = 2 will get 16 bytes)
offset++;
}
// Switch back to read mode
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
return TRUE;
}
//------------------------------------------------------------------------------
BOOL OALFlashInfo(VOID *pBase, OAL_FLASH_INFO *pInfo)
{
BOOL rc = FALSE;
UINT32 base, code1, code2, code3, i;
OALMSG(OAL_FUNC, (L"+OALFlashInfo(0x%08x, ...)\r\n", pBase));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -