📄 sm.c
字号:
/*
*********************************************************************************************************
* File : Sm.C
* Contents :
*
* $Date : 09/18/06 Kimi v0.1
* $Date : 10/18/06 Kimi v0.2
* $Date : 11/02/06 Kimi v1.0
*
* Copyright (c) 2006 Fameg, Inc. All rights reserved
*********************************************************************************************************
*/
#include "sm.h"
//----------------------------------------------------------------------------
// Description:
// Set SegmentBase
//----------------------------------------------------------------------------
void SmEraseAll (void)
{
UINT16 j;
UINT16 SmTotalBlocks = ((UINT16)1 << SmBlocksPerChipShift) * SmMaxChipsPerDevice;
for (j = 0; j < SmTotalBlocks; j++)
SmEraseBlock(j);
}
//----------------------------------------------------------------------------
// Description:
// Set SegmentBase
//----------------------------------------------------------------------------
void SmSetSegmentBase (BYTE Segment)
{
SegmentBase = (((UINT16)(Segment / PLANE_NUMBER) << SmBlock2SegShift) * PLANE_NUMBER) + (Segment % PLANE_NUMBER);
}
//----------------------------------------------------------------------------
// Description:
// Parse the active FLASH chip Status
//----------------------------------------------------------------------------
STATUS SmParseStatus (STATUS Status)
{
if ((Status & 0x40) == 0)
{
return STATUS_FLASH_ERROR;
}
else if ((Status & 0x80) == 0)
{
return STATUS_WRITE_PROTECT;
}
else if ((Status & 0x01) == 1)
{
return STATUS_FLASH_ERROR;
}
else
{
return STATUS_SUCCESS;
}
}
//----------------------------------------------------------------------------
// Description:
// Select the active FLASH chip
//----------------------------------------------------------------------------
void SmSelectChip (BYTE Chip)
{
switch (Chip)
{
case 0:
APLIFARL = 0xFC;
ReadyBusy = 0x02;
break;
case 1:
APLIFARL = 0xFA;
ReadyBusy = 0x04;
break;
case 2:
APLIFARL = 0xF6;
ReadyBusy = 0x08;
break;
case 3:
APLIFARL = 0xEE;
ReadyBusy = 0x10;
break;
default:
;
}
}
//----------------------------------------------------------------------------
// Description:
// Set the extra area of one block, especially the block address
//----------------------------------------------------------------------------
void SmSetBlockExtra (UINT16 BlockAddr)
{
BlockAddr &= SmBlockSegMask; // Segment LBA between 0 and 999
// Block Address Field = (Segment LBA) * 2 + 0x1000 + P (P : EvenParityData)
BlockAddr <<= 1;
BlockAddr |= 0x1000;
if (!EvenParity(BlockAddr))
{
BlockAddr |= 0x0001;
}
SpareArea[BLOCK_STS] = VALID_BLOCK;
SpareArea[DATA_STS] = VALID_DATA;
SpareArea[BLOCK_ADDR1_L] = ((TDataCast *)&BlockAddr)->ucByte[1];
SpareArea[BLOCK_ADDR2_L] = ((TDataCast *)&BlockAddr)->ucByte[1];
SpareArea[BLOCK_ADDR1_H] = ((TDataCast *)&BlockAddr)->ucByte[0];
SpareArea[BLOCK_ADDR2_H] = ((TDataCast *)&BlockAddr)->ucByte[0];
}
//----------------------------------------------------------------------------
// Description:
// Set the FLASH address for the followed FLASH access
//----------------------------------------------------------------------------
void SmSetFlashAddr (UINT32 Page)
{
BYTE Chip = Page >> SmPagesPerChipShift; // Calculate Chip Number
Page = Page & SmChipPageMask; // Make Chip Address in the correct range
SmSelectChip(Chip); // Select Corresponding Chip
FlashAddress[FLASH_ADDR0] = 0x00;
FlashAddress[FLASH_ADDR1] = 0x00;
FlashAddress[FLASH_ADDR2] = ((TDataCast *)&Page)->ucByte[3];
FlashAddress[FLASH_ADDR3] = ((TDataCast *)&Page)->ucByte[2];
FlashAddress[FLASH_ADDR4] = ((TDataCast *)&Page)->ucByte[1];
}
//----------------------------------------------------------------------------
// Description:
// Complete the NAND FLASH Command Function (Key Function)
//----------------------------------------------------------------------------
STATUS SmFlashCmd (BYTE Cmd)
{
switch (Cmd)
{
case FLASH_READ_EX:
FlashAddress[FLASH_ADDR1] = 0x08;
NanD_Command(0x00);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
NanD_Command(0x30);
while (!(APLIFREADYSTAT & ReadyBusy));
Nand_ReadSpare();
break;
case FLASH_READ:
NanD_Command(0x00);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
NanD_Command(0x30);
while (!(APLIFREADYSTAT & ReadyBusy));
Nand_ReadSector();
break;
case FLASH_READ_NEXT_DATA:
Nand_ReadSector();
break;
case FLASH_READ_ID:
NanD_Command(0x90);
NanD_Address(0x00);
FlashId[0] = NanD_Read();
FlashId[1] = NanD_Read();
FlashId[2] = NanD_Read();
FlashId[3] = NanD_Read();
FlashId[4] = NanD_Read();
break;
case FLASH_READ_STS:
NanD_Command(0x70);
FlashSts = NanD_Read();
break;
case FLASH_PROG:
NanD_Command(0x80);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
Nand_WriteSector();
break;
case FLASH_PROG_NEXT_DATA:
Nand_WriteSector();
break;
case FLASH_PROG_EX:
Nand_WriteSpare();
NanD_Command(0x10);
while (!(APLIFREADYSTAT & ReadyBusy));
break;
case FLASH_PAD:
FlashAddress[FLASH_ADDR1] = 0x08;
NanD_Command(0x80);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
Nand_WriteSpare();
NanD_Command(0x10);
while (!(APLIFREADYSTAT & ReadyBusy));
break;
case FLASH_ERASE:
NanD_Command(0x60);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
NanD_Command(0xD0);
while (!(APLIFREADYSTAT & ReadyBusy));
break;
case FLASH_CP:
NanD_Command(0x00);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
NanD_Command(0x35);
while (!(APLIFREADYSTAT & ReadyBusy));
break;
case FLASH_CP_PROG:
NanD_Command(0x85);
NanD_Address(FlashAddress[FLASH_ADDR0]);
NanD_Address(FlashAddress[FLASH_ADDR1]);
NanD_Address(FlashAddress[FLASH_ADDR2]);
NanD_Address(FlashAddress[FLASH_ADDR3]);
NanD_Address(FlashAddress[FLASH_ADDR4]);
NanD_Command(0x10);
while (!(APLIFREADYSTAT & ReadyBusy));
break;
default:
;
}
SmCmdStatus = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------
// Description:
// Read the FLASH ID and Quantity
//----------------------------------------------------------------------------
BYTE SmReadId (void)
{
BYTE RetryCount, Id[4], Chip;
for (Chip = 0; Chip < 4; Chip++) // Scan All Possible Chip
{
SmSelectChip(Chip); // Select Current Chip
for (RetryCount = 0; RetryCount < 3; RetryCount++)
{
if (SmFlashCmd(FLASH_READ_ID) != STATUS_SUCCESS)
{
continue;
}
Id[Chip] = FlashId[1];
break;
}
if (Id[0] != 0xFF)
{
if (Chip == 0)
{
SmMaxChipsPerDevice = 1;
}
else if (Id[Chip] == Id[0])
{
SmMaxChipsPerDevice++;
}
}
}
return Id[0];
}
//----------------------------------------------------------------------------
// Description:
// Read the FLASH status of Current Chip
//----------------------------------------------------------------------------
BYTE SmReadStatus (void)
{
BYTE RetryCount, Status;
for (RetryCount = 0; RetryCount < 3; RetryCount++)
{
if (SmFlashCmd(FLASH_READ_STS) != STATUS_SUCCESS)
{
continue;
}
Status = FlashSts;
break;
}
return Status;
}
//----------------------------------------------------------------------------
// Description:
// Read one page of data from SmartMedia to FIFO
//----------------------------------------------------------------------------
STATUS SmReadPage (UINT32 Page)
{
STATUS RetVal;
BYTE RetryCount;
for (RetryCount = 0; RetryCount < 3; RetryCount++)
{
// Add Read Redundant Area Code Begin
SmSetFlashAddr(Page); // Prepare Address for sending
SmFlashCmd(FLASH_READ_EX); // Combine with SmFlashCmd(FLASH_READ)?
// Add Read Redundant Area Code End
SmSetFlashAddr(Page);
if ((SmFlashCmd(FLASH_READ)) != STATUS_SUCCESS)
{
RetVal = STATUS_FLASH_ERROR;
continue;
}
/*
*********************************************************************************************************
* ECC Detect Area
*********************************************************************************************************
*/
if (SpareArea[DATA_STS] != VALID_DATA)
{
RetVal = STATUS_DATA_ERROR;
continue;
}
ChunkCounter++;
return STATUS_SUCCESS;
}
return RetVal;
}
//----------------------------------------------------------------------------
// Description:
// Write one page of data from FIFO to SmartMedia
//----------------------------------------------------------------------------
STATUS SmWritePage (UINT32 Page)
{
BYTE RetryCount;
STATUS RetVal;
for (RetryCount = 0; RetryCount < 3; RetryCount++)
{
if (SmNeedSetExtra)
{
SmSetBlockExtra(SmSrcBlockLog); // Prepare Redundant Area Data
}
SmSetFlashAddr(Page); // Prepare Address for sending
if ((SmFlashCmd(FLASH_PROG)) != STATUS_SUCCESS)
{
RetVal = STATUS_FLASH_ERROR;
continue;
}
/*
*********************************************************************************************************
* ECC Generate Area
*********************************************************************************************************
*/
ChunkCounter++;
return STATUS_SUCCESS;
}
return RetVal;
}
//----------------------------------------------------------------------------
// Description:
// Read next 512 bytes of data from the Smart Media device
//----------------------------------------------------------------------------
STATUS SmReadNextSector (void)
{
STATUS RetVal;
BYTE RetryCount;
for (RetryCount = 0; RetryCount < 3; RetryCount++)
{
if ((SmFlashCmd(FLASH_READ_NEXT_DATA)) != STATUS_SUCCESS)
{
RetVal = STATUS_FLASH_ERROR;
continue;
}
/*
*********************************************************************************************************
* ECC Detect Area
*********************************************************************************************************
*/
if (ChunkCounter == 3)
{
ChunkCounter = 0;
SectorStart++;
}
else
{
ChunkCounter++;
}
return STATUS_SUCCESS;
}
return RetVal;
}
//----------------------------------------------------------------------------
// Description:
// Write next 512 bytes of data from the Smart Media device
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -