📄 mal_2k.c
字号:
SRL Y
RRC X
RRC A ; 1st shift
SRL Y
RRC X
RRC A ; 2nd shift
SRL Y
RRC X
RRC A ; 3rd shift
SRL Y
RRC X
RRC A ; 4th shift
SRL Y
RRC X
RRC A ; 5th shift
LD SMC_Laddr:1, A
LD SMC_Laddr, X
} // The C line below costs too much
// SMC_Laddr = (unsigned int)(MAL_Block_Address >> 5);
Adjust_Laddr();
SMC_Ppage = (unsigned char)MAL_Block_Address & 0x001F;
}
else { //for 2k Flash
asm {
LD A, MAL_Block_Address:2
LD X, MAL_Block_Address:1
LD SMC_Laddr:1, A
LD SMC_Laddr, X
} // The C line below costs too much
// SMC_Laddr = (unsigned int)(MAL_Block_Address >> 8);
Adjust_Laddr();
SMC_Ppage512 = SMC_Ppage = (unsigned char)MAL_Block_Address & 0x00FF; //512 Byte page number for 2K
SubBlock = (unsigned char) (SMC_Ppage % 4); //offset in the coloumn
SMC_Ppage = SMC_Ppage / 4; //2K page number for 2K Flash
}
if (SMC_Lookup_nCache0 == 0) // Card < 64MB
return; // No cache management needed
// Calculate the address of the last page: EndBlock
if (SMC_Cluster_Size != 64){
asm {
LD A, MAL_Block_Numbers:1
LD X, MAL_Block_Numbers
ADD A, SMC_Ppage
JRNC sub_1
INC X
sub_1: SUB A, #1
JRNC shift5
DEC X
shift5:
SRL X
RRC A ; 1st shift
SRL X
RRC A ; 2nd shift
SRL X
RRC A ; 3rd shift
SRL X
RRC A ; 4th shift
SRL X
RRC A ; 5th shift
ADD A, SMC_Laddr:1
LD EndBlock:1, A
LD A, X
ADC A, SMC_Laddr
LD EndBlock, A
} // The following C line costs too much
// EndBlock = SMC_Laddr + ((SMC_Ppage + MAL_Block_Numbers - 1) >> 5);
}
else { //for 2K flash
asm {
LD A, MAL_Block_Numbers:1
LD X, MAL_Block_Numbers
ADD A, SMC_Ppage
JRNC sub_2
INC X
sub_2: SUB A, #1
JRNC shift8
DEC X
shift8: LD A, X
ADD A, SMC_Laddr:1
LD EndBlock:1, A
CLR A
ADC A, SMC_Laddr
LD EndBlock, A
} // The following C line costs a lot
// EndBlock = SMC_Laddr + ((SMC_Ppage512 + MAL_Block_Numbers - 1) >> 8);
}
if (EndBlock >= 1000) { // The access will cross the zone boundary
unsigned char ZoneNext;
unsigned char ChipNext;
ZoneNext = SMC_Zone + 1;
ChipNext = NAND_Chip;
if(SMC_Cluster_Size != 64) {
if (ZoneNext >= Chip_Size[NAND_Chip]) {
ZoneNext -= Chip_Size[NAND_Chip];
goto com0;
// ChipNext++;
// while (Chip_Size[ChipNext] == 0)
// ChipNext++; // Skip bad or not exist chips
}
}
else {
if (ZoneNext >= (Chip_Size[NAND_Chip]/8)) {
ZoneNext -= (Chip_Size[NAND_Chip]/8);
com0: ChipNext++;
while (Chip_Size[ChipNext] == 0)
ChipNext++; // Skip bad or not exist chips
}
}
if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0) { // current zone hits table0
if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone1)
return;
NAND_Lookup_Update1(ChipNext, ZoneNext); // update lookup tabke 1 for ZoneNext
}
else if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1) {// current zone hits table1
if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone0)
return;
NAND_Lookup_Update0(ChipNext, ZoneNext); // update lookup table 0 for ZoneNext
}
else if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone0) // next zone hits table0
NAND_Lookup_Update1(NAND_Chip, SMC_Zone); // update lookup table 1 for SMC_Zone
else if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone1) // next zone hits table1
NAND_Lookup_Update0(NAND_Chip, SMC_Zone); // updata lookup table 0 for SMC_Zone
else {
NAND_Lookup_Update0(NAND_Chip, SMC_Zone); // updata lookup table 0 for SMC_Zone
NAND_Lookup_Update1(ChipNext, ZoneNext); // updata lookup table 1 for ZoneNext
}
}
else { // The access will not cross the zone boundary
if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0
|| gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1)
return;
#if USE_CACHE0
if (NAND_Chip == 0) // Cache has to be for chip0 only
if (SMC_Zone == 0 && SMC_Laddr < SMC_Lookup_nCache0) { // Hit on cache of zone0
if (EndBlock < SMC_Lookup_nCache0)
return;
}
#endif
// Going to make the lookup table for the new zone
if (SMC_Lookup_Count0 < SMC_Lookup_Count1)
NAND_Lookup_Update0(NAND_Chip, SMC_Zone);
else
NAND_Lookup_Update1(NAND_Chip, SMC_Zone);
}
}
#endif // THUMB_DRIVE
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Organization of the Lookup Table
There are two lookup tables, table0 & table1. Table0 always keep the
information for Zone 0 and the Table1 keeps the information for the current
working Zone.
A lookup table is a buffer with 1024 elements. The index of this buffer is
the logical address and the content of each element is the corresponding
physical address.
Assume LUT[x] is the value of xth element:
LUT[x] < 1024 LUT[x] is the physical address of logicall address x
LUT[x] >= 1024 (LUT[x] & 1024) is a free physical address and will be
allocated to the logical address of x.
NOTE: LUT[x] IS CONVERTED TO DTC ADDRESS FOR FASTING ACCESS
LUT[x] >> 5 or LUT[x] >> 4 is the real physical cluster address
Using the lookup table:
The first 1000 elements of a lookup table are used for mapping the logical
address to physical address. All the bad physical block addresses are saved
at the end of this table. Elements start from index 1000 are available to
use for new allocation.
x < 1000 LUT[x] is used for mapping
x >= 1024 - n LUT[x] is the physical address of a bad physical cluster
n is the number of bad blocks.
x >= 1000 & x < 1024 -n
LUT[x] is the free physical cluster that can be allocated
When an existing physical cluster is over-written, the free cluster on the
index 1000 is used. Then the old cluster is erased and put in the location
of index 1000.
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
//#pragma NO_ENTRY
void SMC_Convert_Lookup(unsigned short *pLUT)
{
unsigned short value;
int iLUT;
for (iLUT = 1023; iLUT >= 0; iLUT--) {
value = *pLUT;
if (SMC_Cluster_Size == 32)
*pLUT = value << 5;
else if (SMC_Cluster_Size == 64){
if (*pLUT & 0x400) { //to chk if it is a mapped cluster
*pLUT = value << 6;
*pLUT |= 0x0010;
}
else {
*pLUT = value << 6;
// *pLUT &= 0xffef; // last 6bits must be 0 after shift
}
}
else {
value &= ~0x0400;
*pLUT = value << 4;
}
if (value & 0x2000)
*pLUT |= 0x01; // bad cluster
pLUT++;
}
}
void SMC_Paddr_To_DTC_Addr(void)
{
Map_To_DTC_Addr256(malPaddr, SMC_Zone, SMC_Paddr, 0,Col);
}
unsigned short SMC_Get_Free()
{
#if USE_CACHE0
if (SMC_Lookup_pTable == SMC_Lookup_pCache0)
return SMC_Lookup_pFree0[0];
#endif
#ifndef THUMB_DRIVE
if (SMC_4MB)
return SMC_Lookup_pTable[500];
#endif
return SMC_Lookup_pTable[1000];
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Replace SMC_Laddr with SMC_Paddr and set SMC_Raddr on logical address 1000
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Update_Lookup()
{
#if ALLOW_OUT_RANGE
if (Mal_Addr_Out_Range & 0x01)
return;
#endif
SMC_Lookup_pTable[SMC_Laddr] = SMC_Paddr;
if (SMC_Wstate & SMC_OLD_CLUSTER) {
// malPaddr = Map_DTC_Addr(SMC_Zone, SMC_Raddr, 0);
// Map_To_DTC_Addr(malPaddr, SMC_Zone, SMC_Raddr, 0);
Map_To_DTC_Addr256(malPaddr, SMC_Zone, SMC_Raddr, 0,0);//for 2K Flash
if (DTC_SMC_Erase() != 0x01) // Erase the dirty cluster of malPaddr
asm NOP;
#if USE_CACHE0
if (SMC_Lookup_pTable == SMC_Lookup_pCache0)
SMC_Lookup_pFree0[0] = SMC_Raddr | 0x8000;
else
#endif
#ifndef THUMB_DRIVE
if (SMC_4MB)
SMC_Lookup_pTable[500] = SMC_Raddr | 0x8000;
else {
#endif
if (SMC_Cluster_Size != 64)
SMC_Lookup_pTable[1000] = SMC_Raddr | 0x8000;
else
SMC_Lookup_pTable[1000] = SMC_Raddr | 0x0010;//different map bit for 2K flash
#ifndef THUMB_DRIVE
}
#endif
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Convert the SMC_Laddr to SMC_Paddr in SMC_Zone
return TRUE if the logical Cluster of SMC_Laddr exists
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if USE_CACHE0
void SMC_Copy_Lookup_Cache0()
{
unsigned short *pW;
// Copy the first few lookup items of zone0
// They are PBR, MBR, FAT & ROOT
asm {
LD X, SMC_Lookup_nCache0
SLL X
DEC X
copy_cache:
LD A, ([SMC_Lookup_pTable.w],X)
LD (SMC_Lookup_pCache0,X), A
DEC X
JRPL copy_cache
}
// for (index = Lookup_nCache-1; index >= 0; index--)
// SMC_Lookup_pCache0[index] = SMC_Lookup_pTable[index];
// Copy the first few free lookup items of zone0
asm {
LD A, SMC_Lookup_pTable:1
ADD A, #0xD0
LD pW:1, A
LD A, SMC_Lookup_pTable
ADC A, #0x07
LD pW, A
}
// pW = SMC_Lookup_pTable+1000;
asm {
LD X, #CACHE0_FREE*2-1
copy_free0:
LD A, ([pW.w], X)
LD (SMC_Lookup_pFree0,X), A
DEC X
JRPL copy_free0
}
// for (index = CACHE0_FREE-1; index >= 0; index--)
// SMC_Lookup_pFree0[index] = pW[index];
}
#endif // USE_CACHE0
#pragma DATA_SEG DEFAULT_RAM // After here, all variable will be in non-Zero page
#ifndef THUMB_DRIVE
void SMC_Lookup_Update0(unsigned char Zone)
{
SMC_Lookup_pTable = SMC_Lookup_Table0;
#if USE_CACHE0
if (SMC_Lookup_Zone0 == 0)
SMC_Copy_Lookup_Cache0();
#endif
SMC_Lookup_Count0 = 0;
SMC_Lookup_Zone0 = Zone;
malRaddr = 1024; // number of clusters in the zone
if (SMC_4MB)
malRaddr = 512;
malNpage = SMC_Cluster_Size;
if (SMC_Cluster_Size == 64) {
Buffer_Param[0x00] = 0x00; //flag for recognition
Buffer_Param[0x02] = 0x00; //first cmd for Mapzone
Buffer_Param[0x03] = 0xe3; //Add for mazone
}
else {
Buffer_Param[0x00] = 0x01;
Buffer_Param[0x02] = 0x50;
Buffer_Param[0x03] = 0xe4;
}
// Map_To_DTC_Addr(malPaddr, Zone, 0, 0);
Map_To_DTC_Addr256(malPaddr, Zone, 0, 0, 2); //for 2K Flash
DTC_SMC_Map_Zone(SMC_Lookup_pTable);
SMC_Convert_Lookup(SMC_Lookup_pTable);
}
//#pragma NO_OVERLAP
void SMC_Lookup_Update1(unsigned char Zone)
{
SMC_Lookup_pTable = SMC_Lookup_Table1;
#if USE_CACHE0
if (SMC_Lookup_Zone1 == 0)
SMC_Copy_Lookup_Cache0();
#endif
SMC_Lookup_Count1 = 0;
SMC_Lookup_Zone1 = Zone;
malRaddr = 1024; // number of clusters in the zone
// if (SMC_4MB) // 4MB does not use LOOKUP Table 1
// malRaddr = 512;
malNpage = SMC_Cluster_Size;
if (SMC_Cluster_Size == 64) { //For 256MB
Buffer_Param[0x00] = 0x00; //flag for recognition
Buffer_Param[0x02] = 0x00; //first cmd for Mapzone
Buffer_Param[0x03] = 0xe3; //Adr for mapzone
}
else {
Buffer_Param[0x00] = 0x01;
Buffer_Param[0x02] = 0x50;
Buffer_Param[0x03] = 0xe4;
}
// Map_To_DTC_Addr(malPaddr, Zone, 0, 0);
Map_To_DTC_Addr256(malPaddr, Zone, 0, 0, 2); //for 2K Flash
DTC_SMC_Map_Zone(SMC_Lookup_pTable);
SMC_Convert_Lookup(SMC_Lookup_pTable);
}
#endif
static unsigned char SMC_Log2Phy()
{
#if ALLOW_OUT_RANGE
if (Mal_Addr_Out_Range & 0x03)
return FALSE; // The address is out of range now
#endif
#ifdef THUMB_DRIVE
if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0) { // Hit on table0
#else
if (SMC_Zone == SMC_Lookup_Zone0) { // Hit on table0
#endif
SMC_Lookup_pTable = SMC_Lookup_Table0;
if (SMC_Lookup_Count0 != LOOKUP_THRESHOLD)
SMC_Lookup_Count0++; // increase the visit counter of this table
if (SMC_Lookup_Count1 != 0)
SMC_Lookup_Count1--; // decrease the visit counter of another table
}
#ifdef THUMB_DRIVE
else if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1) {// Hit on table1
#else
else if (SMC_Zone == SMC_Lookup_Zone1) { // Hit on table1
#endif
SMC_Lookup_pTable = SMC_Lookup_Table1;
if (SMC_Lookup_Count1 != LOOKUP_THRESHOLD)
SMC_Lookup_Count1++; // increase the visit counter of this table
if (SMC_Lookup_Count0 != 0)
SMC_Lookup_Count0--; // decrease the visit counter of another table
}
else {
// No hit on both table
#if USE_CACHE0
// The _SMC_Get_Logical_Addr() gurantees it is on zone0 cache
SMC_Lookup_pTable = SMC_Lookup_pCache0;
#else
// asm nop; // There must be a bug if we are here
#endif
}
if (SMC_Cluster_Size == 64){
SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
return ((SMC_Paddr & 0x10) == 0); //for 2K Flash
}
SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
return ((SMC_Paddr & 0x8000) == 0);
// SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
// return ((SMC_Paddr & 0x8000) == 0);
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Mark and add SMC_Zone:SMC_Paddr to end of the lookup table
SMC_Laddr is the logical cluster number.
On return: SMC_Zone:SMC_Paddr will be the good cluster form SMC_Laddr
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Lookup_Map_Bad(void)
{
unsigned int temp;
unsigned short* pBad;
#if USE_CACHE0
if (SMC_Lookup_pTable != SMC_Lookup_pCache0) {
pBad = SMC_Lookup_pTable + 1023; // the last item
while (*pBad & 0x0F)
pBad--;
temp = *pBad;
*pBad = SMC_Paddr | 0x0001;
}
else {
// shift the free cluster array
// SMC_Lookup_pFree0[0] = SMC_Lookup_pFree0[1];
// SMC_Lookup_pFree0[1] = SMC_Lookup_pFree0[2];
asm {
CLR X
shift_free0:
LD A, (SMC_Lookup_pFree0:2,X)
LD (SMC_Lookup_pFree0,X), A
INC X
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -