📄 nf.c
字号:
/*_____ E X T E R N V A R I A B L E ___________________________________*/
extern data Uint32 gl_ptr_mem; /* memory data pointer */
extern data Byte EnglishPage;
extern bdata Byte PlayStatusSign;
extern xdata Byte sound_mode;
extern xdata Byte light_mode;
extern xdata Byte PlayVolume;
extern pdata Byte gl_buffer[];
extern bdata bit light_bit;
extern bdata bit record_open_bit;
extern bdata bit NormalPlay;
extern xdata Uint16 nb_reserved_sector;
extern xdata Byte ReplayTime;
extern Union_IDATA xdata UnionIDATA;
extern Union_XDATA xdata UnionXDATA;
/*_____ EXTERN ADDRESS _________________________________________________*/
xdata Byte nf_send_cmd At(NF_CMD_LATCH_ENABLE_ADD); /* Command */
xdata Byte nf_send_add At(NF_ADD_LATCH_ENABLE_ADD); /* Address */
xdata Byte volatile nf_data At(NF_ADDRESS_CMD_DATA);/* Data */
extern void nf_read_init(Uint32 offset);
void store_read(void);
void store_write(void);
/*_____ V A R I A B L E ________________________________________________*/
bdata bit block_used; /* When a block was used */
bdata bit nf_busy;
bdata bit nf_64=1;
data Uint32 current_physical_sector_addr;
data Uint32 address;
data Uint16 look_up_table_block; /* Look up table block address */
data Byte index_block_erased = 0; /* give the number of block to be erased */
xdata Byte store_ptr;
idata Uint32 address_look_up_table;
idata Uint16 gl_cpt_page;
idata Byte index_reassign; /* give the number of block to be reassigned */
idata Byte nf_zone_max; /* max zone number (from 1 to 8) */
idata Byte nf_device_type; /* Give the size of device in Mbytes */
idata Byte index_look_up_table; /* Index of free block for LUT */
idata Uint16 redundant_logical_block_value; /* Logical block value in the redundant area */
idata Uint16 block_to_be_erased[NF_FREE_BLOCK_SIZE];/* Block address to be erased */
idata Byte index_block_used[NF_FREE_BLOCK_SIZE]; /* Index of new assigned block */
xdata Byte nf_spare_block_number[NF_ZONE_MAX]; /* Number of free spare block in each zone */
xdata Uint32 nf_disk_size; /* Size of the disk in sector - 1 */
xdata Byte index_free_block[NF_ZONE_MAX]; /* index in the LUT for free block for data */
/* reassign_block : conversion logical block/physical block */
/* it's used to update the look up table */
xdata t_reassign_block reassign_block[NF_FREE_BLOCK_SIZE];
/*_____ D E F I N I T I O N ____________________________________________*/
/*_____ C O D E ________________________________________________________*/
/* Card Identification System definition */
code Byte nf_cis_table[]=
{
0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21,
0x02, 0x04, 0x01, 0x22, 0x02, 0x01, 0x01, 0x22, 0x03, 0x02, 0x04, 0x07, 0x1A, 0x05, 0x01, 0x03,
0x00, 0x02, 0x0F, 0x1B, 0x08, 0xC0, 0xC0, 0xA1, 0x01, 0x55, 0x08, 0x00, 0x20, 0x1B, 0x0A, 0xC1,
0x41, 0x99, 0x01, 0x55, 0x64, 0xF0, 0xFF, 0xFF, 0x20, 0x1B, 0x0C, 0x82, 0x41, 0x18, 0xEA, 0x61,
0xF0, 0x01, 0x07, 0xF6, 0x03, 0x01, 0xEE, 0x1B, 0x0C, 0x83, 0x41, 0x18, 0xEA, 0x61, 0x70, 0x01,
0x07, 0x76, 0x03, 0x01, 0xEE, 0x15, 0x14, 0x05, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x30, 0x2E, 0x30, 0x00, 0xFF, 0x14, 0x00, 0xFF, 0x00, 0x00
};
extern bdata bit Nf_WP;
/*_____ D E C L A R A T I O N ______________________________________________*/
/*F**************************************************************************
* NAME: read_spare_byte
----------------------------------------------------------------------------
* PURPOSE: read spare data byte and construct the look up table.
*****************************************************************************/
Uint16 read_spare_byte_sub(Byte mode,Byte nf_zone,Uint16 start,Uint16 free_bloc_pos);
void read_spare_byte(void)
{
Uint16 free_bloc_pos,start,block;
Uint16 i,j;
Byte dummy,nf_zone;
// idata Uint32 address2; /* LUT table address */
// idata Uint32 address3; /* Used to determine free physical block */
bit bad_block;
xdata Uint16 last_physical_used_block[NF_ZONE_MAX]; /* Last physical block used */
Nf_CS_ON();
/***************************************************/
/* Search bad block */
/***************************************************/
address = 0x8000; /* Start from sector 0 */
Nf_wait_busy();
for (j = NF_BLOCK_PER_ZONE; j != 0; j--) /* Only zone 0 */
{
nf_send_rc_cmd();
if ( Nf_rd_byte() == 0xFF ) /* Not a bad block */
{
if ( Nf_rd_byte() == 0xE8) /* Look up table? */
{
nf_block_erase(address);
}
}
address += 32;
}
address = 0; /* Start from sector 0 */
Nf_wait_busy();
for (i = 0; i < nf_zone_max; i++)
{
nf_spare_block_number[i] = 0;
for (j = NF_BLOCK_PER_ZONE; j != 0; j--)
{
nf_send_rc_cmd();
if ( Nf_rd_byte() != 0xFF ) /* 0xFF = valid block */
nf_spare_block_number[i]++;
else
{
dummy = Nf_rd_byte();
if ( (dummy == 0x00) || ( (dummy != 0xFF) && ( (dummy & 0xF8) != 0x10 )) ) // Value in redundant spare area not correct
{
nf_spare_block_number[i]++;
if(i == 1)
{
gl_buffer[nf_spare_block_number[1]-1] = dummy;
}
}
}
address += 32;
}
}
for (i = 0; i < nf_zone_max; i++)
{
nf_spare_block_number[i] = (32 - nf_spare_block_number[i]) << 1;
}
/***************************************************/
/* Search a look-up table and erase it */
/***************************************************/
address = 0;
Nf_wait_busy();
for (j = NF_BLOCK_PER_ZONE; j != 0; j--) /* Only zone 0 */
{
nf_send_rc_cmd();
if ( Nf_rd_byte() == 0xFF ) /* Not a bad block */
{
if ( Nf_rd_byte() == 0xE8) /* Look up table? */
{
nf_block_erase(address);
}
}
address += 32;
}
/***************************************************/
/* Find the last physical block used for each zone */
/***************************************************/
for (nf_zone = 0; nf_zone < nf_zone_max; nf_zone++)
{
last_physical_used_block[nf_zone] = (Uint16)(nf_zone) << 10;
address = (Uint32)(nf_zone) << 15;
Nf_wait_busy();
for (j = NF_BLOCK_PER_ZONE; j != 0; j--)
{
nf_send_rc_cmd();
if ( Nf_rd_byte() == 0xFF) /* Not a bad block */
{
dummy = Nf_rd_byte();
if ( ((dummy & 0xF8) == 0x10) && (dummy != 0x00) ) /* Used block */
{
last_physical_used_block[nf_zone] = address >> 5;
}
}
address += 32;
}
}
/***************************************************/
/* Find free physical block for LUT */
/***************************************************/
address = 0;
do
{
bad_block = FALSE;
/* Send READ C Area command */
nf_send_rc_cmd();
if (Nf_rd_byte() == 0xFF) /* Not a bad block */
dummy = Nf_rd_byte();
else
bad_block = TRUE;
address += 32;
}
while ( (dummy != 0xFF) || (dummy == 0x00) || (bad_block) );
address -= 32;
/* Updata look up table address */
look_up_table_block = address >> 5;
address_look_up_table = address;
/*********************************************************/
/* Create the look-up table */
/* ***************************************************** */
for (nf_zone = 0; nf_zone < nf_zone_max; nf_zone++) /* for each zone */
{
start = 0; /* initialize the logical block value */
free_bloc_pos = last_physical_used_block[nf_zone];
do
{
free_bloc_pos = read_spare_byte_sub(MODE_CMDA,nf_zone,start,free_bloc_pos);
start += 128; /* process next 128 logical block */
free_bloc_pos = read_spare_byte_sub(MODE_CMDB,nf_zone,start,free_bloc_pos);
start += 128;
address++;
}
while (start < NF_BLOCK_PER_ZONE);
}
/***************************************************/
/* Recopy the LUT */
/***************************************************/
index_look_up_table = 20;
index_free_block[0] = 0;
address = address_look_up_table + 3;
Nf_wait_busy();
Nf_send_command(NF_READ_B_AREA_CMD);
Nf_send_address(0x00);
Nf_send_address ( ((Byte*)&address)[3] );
Nf_send_address ( ((Byte*)&address)[2] );
if (nf_64)
Nf_send_address ( ((Byte*)&address)[1] );
Nf_wait_busy();
nf_upload_buffer();
block = (gl_buffer[192] << 8) + gl_buffer[193];
block = block & 0x7FFF;
if (block != look_up_table_block)
{
address = (Uint32)(block) << 5;
for (j = 32; j != 0; j--)
{
Nf_wait_busy();
Nf_send_command(NF_READ_A_AREA_CMD);
Nf_send_address(0x00);
Nf_send_address ( ((Byte*)&address_look_up_table)[3] );
Nf_send_address ( ((Byte*)&address_look_up_table)[2] );
if (nf_64)
Nf_send_address ( ((Byte*)&address_look_up_table)[1] );
Nf_wait_busy();
nf_upload_buffer();
nf_send_w_cmd(MODE_CMDA,0);
nf_download_buffer();
Nf_send_command(NF_PAGE_PROGRAM_CMD);
Nf_wait_busy();
Nf_send_command(NF_READ_B_AREA_CMD);
Nf_send_address(0x00);
Nf_send_address ( ((Byte*)&address_look_up_table)[3] );
Nf_send_address ( ((Byte*)&address_look_up_table)[2] );
if (nf_64)
Nf_send_address ( ((Byte*)&address_look_up_table)[1] );
Nf_wait_busy();
nf_upload_buffer();
nf_send_w_cmd(MODE_CMDB,0);
nf_download_buffer();
/* Write redundant data */
Nf_wr_byte(0xFF); Nf_wr_byte(0xFF); Nf_wr_byte(0xFF);
Nf_wr_byte(0xFF); Nf_wr_byte(0xFF);
Nf_wr_byte(0xFF);
Nf_wr_byte(0xE8); Nf_wr_byte(0xFF); /* Logical block value */
Nf_wr_byte(0xFF); Nf_wr_byte(0xFF); Nf_wr_byte(0xFF); /* ECC area 2 */
Nf_wr_byte(0xE8); Nf_wr_byte(0xFF); /* Logical block value */
Nf_wr_byte(0xFF); Nf_wr_byte(0xFF); Nf_wr_byte(0xFF); /* ECC area 1 */
Nf_send_command(NF_PAGE_PROGRAM_CMD);
address++;
address_look_up_table++;
}
/* Erase old LUT */
nf_block_erase(address_look_up_table - 1);
/* New address of LUT */
look_up_table_block = block;
address_look_up_table = (Uint32)(block) << 5;
}
Nf_CS_OFF();
}
//------------------------
Uint16 read_spare_byte_sub(Byte mode,Byte nf_zone,Uint16 start, Uint16 free_bloc_pos)
{
data Uint16 block;
idata Uint32 address2;
idata Uint32 address3;
data Uint16 i,j;
data Byte dummy;
bdata bit bad_block;
nf_init_buffer(); /* Reinitialize the buffer */
address2 = (Uint32)(nf_zone) << 15; /* Block address */
Nf_wait_busy();
for (j = NF_BLOCK_PER_ZONE; j != 0 ; j--) /* for each block */
{ // Read Spare data value
Nf_send_command (NF_READ_C_AREA_CMD);
Nf_send_address ( 0x05 );
Nf_send_address ( ((Byte*)&address2)[3] );
Nf_send_address ( ((Byte*)&address2)[2] );
if (nf_64)
{
Nf_send_address ( ((Byte*)&address2)[1] );
}
Nf_wait_busy();
// Calculate the logical/physical conversion
if (Nf_rd_byte() == 0xFF) // Not a bad block
{
// Read the value of logical block
((Byte*)&block)[0] = Nf_rd_byte();
((Byte*)&block)[1] = Nf_rd_byte();
// Don't take bad block or unused block
if ((block != 0xFFFF) && (block != 0x0000))
{
// Calculate the logical block value
block = (block & 0x0FFF) >> 1;
// If the value is in the range, then save it
if ( (block < start + 128) && (block >= start))
{
gl_buffer[2 * block] = (address2 >> 5) >> 8;
gl_buffer[2 * block + 1] = address2 >> 5;
}
}
}
address2 += 32; // increase address
}
address3 = (Uint32)(free_bloc_pos) << 5;
for (i = 0; i < 256; i+=2)
{
if (gl_buffer[i] == 0xFF)
{
do // Search free physical block
{
bad_block = FALSE;
address3 += 32;
if (address3 >= ((Uint32)(nf_zone + 1) << 15) )
{
address3 = (Uint32)(nf_zone) << 15;
}
Nf_send_command(NF_READ_C_AREA_CMD);
Nf_send_address(0x05);
Nf_send_address ( ((Byte*)&address3)[3] );
Nf_send_address ( ((Byte*)&address3)[2] );
if (nf_64)
{
Nf_send_address ( ((Byte*)&address3)[1] );
}
Nf_wait_busy();
if (Nf_rd_byte() == 0xFF) // Not a bad block ?
{
dummy = Nf_rd_byte();
}
else
{
bad_block = TRUE;
}
}
while ( (dummy != 0xFF) || (dummy == 0x00) || (bad_block) );
free_bloc_pos = address3 >> 5;
gl_buffer[i] = (free_bloc_pos >> 8) + 0x80;
gl_buffer[i + 1] = free_bloc_pos;
}
}
nf_send_w_cmd(mode,0);
// Write 256 bytes from the buffer
nf_download_buffer();
// Valid the page programmation
Nf_send_command(NF_PAGE_PROGRAM_CMD);
return free_bloc_pos;
}
//------------------------
void nf_send_rc_cmd()
{
Nf_send_command (NF_READ_C_AREA_CMD);
Nf_send_address ( 0x05 );
Nf_send_address ( ((Byte*)&address)[3] ); /* 2nd address cycle */
Nf_send_address ( ((Byte*)&address)[2] ); /* 3rd address cycle */
if (nf_64) /* Size of card >= 64Mbytes ?*/
Nf_send_address ( ((Byte*)&address)[1] );/* 4th address cycle */
Nf_wait_busy();
}
//------------------------
void nf_send_ra_cmd()
{
Nf_send_command (NF_READ_A_AREA_CMD);
Nf_send_address ( 0x00 );
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[3] );
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[2] );
if (nf_64)
{
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[1] );
}
}
//------------------------
void nf_send_w_cmd(Byte Mode,bit Par)
{
Nf_wait_busy();
if (Mode == MODE_CMDA)
{
Nf_send_command (NF_READ_A_AREA_CMD);
}
else
{
Nf_send_command (NF_READ_B_AREA_CMD);
}
Nf_send_command(NF_SEQUENTIAL_DATA_INPUT_CMD);
Nf_send_address (0x00);
if(!Par)
{
Nf_send_address ( ((Byte*)&address)[3] );
Nf_send_address ( ((Byte*)&address)[2] );
if (nf_64)
Nf_send_address ( ((Byte*)&address)[1] );
}
else
{
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[3] );
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[2] );
if (nf_64)
Nf_send_address ( ((Byte*)¤t_physical_sector_addr)[1] );
}
}
/*F**************************************************************************
* NAME: nf_init
*----------------------------------------------------------------------------
* PURPOSE: NF initialisation
*****************************************************************************/
//bdata bit nf_connect=1;
extern void load_hex(Byte i ,Byte j, Byte buf);
extern void lcd_deal(void);
void nf_init (void)
{
Nf_CS_ON();
/* Read ID code */
Nf_send_command(NF_READ_ID_CMD);
Nf_send_address(0x00);
Nf_wait_busy();
ACC = Nf_rd_byte();
// if (0XEC == Nf_rd_byte())nf_connect=KO;
switch (Nf_rd_byte()) /* Device code */
{
case 0x73 : /* 16 Mbyte */
nf_device_type = NF_SIZE_16MB;
nf_zone_max = 1;
nb_reserved_sector=1;
nf_disk_size = NF_SECTOR_SIZE_16MB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -