📄 nf_unusual.c
字号:
//! @file nf_unusual.c,v
//!
//! Copyright (c) 2004 Atmel.
//!
//! Please read file license.txt for copyright notice.
//!
//! @brief This file contains the high level management for nand-flash
//! memory devices which are rarely used. The code is put in a bank
//! in order to save code space.
//!
//! @version 1.22 snd3-refd1-1_9_5 $Id: nf_unusual.c,v 1.22 2007/07/27 12:57:17 sguyon Exp $
//!
//! @todo
//! @bug
// TODO: remplacer les s_shift_xxx en (1<<s_shift_xxx): et ainsi faire des DIV/MUL plutot que des shift
// TODO: decomposer g_phys_page_addr en s_phys_block et s_phys_page (offset dans le block)
//_____ I N C L U D E S ___________________________________________________
//#define _TRACE_ (DISABLE)
#include "config.h"
#include "conf\conf_nf.h"
#include "lib_mcu\nfc\nfc_drv.h"
#include "nf_mngt.h"
#include "conf\conf_clock.h"
#include "lib_mcu\debug.h"
#include "lib_mcu\clock\clock_drv.h"
//_____ P R I V A T E D E C L A R A T I O N _____________________________
#if (NF_GENERIC_DRIVER==TRUE) || (defined NF_AUTO_DETECT_2KB) ||(defined NF_AUTO_DETECT_512B)
extern _MEM_TYPE_SLOW_ U8 g_n_zones ; // number of zones (=1024 blocks) per device
extern _MEM_TYPE_SLOW_ U16 g_n_blocks ; // number of blocks per device
#endif
extern _MEM_TYPE_SLOW_ U8 g_page_buffer[NF_FULL_PAGE_BUFFER_SIZE] ; // Used to bufferize a page
extern _MEM_TYPE_BIT_ bit g_nf_init ; // Boolean set when driver is initialized
extern _MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz ; // Size of the last sub-LUT. Unit in number of logical blocks
extern _MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz ; // Size of the sub-LUT. Unit in number of logical blocks
Bool g_is_found_lut ;
Bool g_is_found_fbb ;
extern Bool g_fatal ; // Used in LUT/FBB building and ECC management...
_MEM_TYPE_SLOW_ U8 g_n_real_sub_lut;
_MEM_TYPE_SLOW_ U16 g_curr_block_addr[ NF_N_DEVICES]; // holds the last block address for each device
_MEM_TYPE_SLOW_ U8 g_byte[16] ; // Buffer which holds spare bytes
extern _MEM_TYPE_SLOW_ U8 g_n_sub_lut ; // Holds the number of sub-Lut
extern _MEM_TYPE_SLOW_ U16 g_lut_block_addr [ N_SUBLUT ] ; // LUT block address
extern _MEM_TYPE_SLOW_ U8 g_lut_block_index[ N_SUBLUT ] ; // LUT index, unit in (LUT size/page size)
static _MEM_TYPE_SLOW_ U8 s_nfd_rev ; // Nand Flash Driver revision;
extern _MEM_TYPE_SLOW_ U16 g_nf_first_block ; // Block addr of the beginning of dynamic area
static _MEM_TYPE_SLOW_ U8 s_n_quarantine_blocks[NF_N_DEVICES] ; // count quarantine blocks (ECC error discovered in them, but block not yet bad) for each device
static _MEM_TYPE_SLOW_ U16 s_n_invalid_blocks[ NF_N_DEVICES] ; // count invalid blocks (bad, management, LUT, ...) for each device
extern _MEM_TYPE_SLOW_ U16 g_n_export_blocks ; // Number of physical blocks exported for mass-storage use
extern _MEM_TYPE_SLOW_ U16 g_n_free_blocks ; // Number of free physical blocks
extern _MEM_TYPE_SLOW_ U16 g_fbb_block_addr ; // Free-Blocks block address
extern _MEM_TYPE_SLOW_ U8 g_fbb_block_index ; // Free-Blocks block index
extern _MEM_TYPE_SLOW_ U32 g_last_log_sector ; // Holds the last logical sector number
extern _MEM_TYPE_SLOW_ U32 g_copy_src ; // Used to copy NF pages (source page)
extern _MEM_TYPE_SLOW_ U16 g_block_to_kill[ NF_N_DEVICES] ; // Holds the blocks number which will be erased
extern _MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES] ; // Holds the current phys page number for each device
extern _MEM_TYPE_FAST_ U8 g_curr_dev_id ; // Holds the current device number that is used
extern _MEM_TYPE_MEDFAST_ U16 g_log_block_id ; // Logical Block address
extern _MEM_TYPE_SLOW_ Cache_lut g_cache_lut; // LUT cache
extern _MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb; // Free-Blocks block cache
//#undef ERASING_ALL
//#define ERASING_ALL ENABLE
#if (ERASING_ALL==ENABLE)
U8 g_forever=TRUE;
static void ut_nfc_erase_all( void );
#endif
static void nf_init_buffer( void );
static Status_bool nf_scan( void );
static Status_bool nf_rebuild( void );
static Bool is_nf_invalid( void );
#if (ISP_VERSION<0x04) // Static area with fixed length
static void nf_scan_static_area( void );
#endif
static U16 nf_fetch_free_block( U8 i_dev );
static U8 nf_refine_index( U16 block_addr, U8 inc, U8 pattern) ;
//! Clears the internal buffer.
//!
//! @return nothing
//!
static void nf_init_buffer( void )
{
U16 u16_tmp;
for ( u16_tmp=NF_FULL_PAGE_BUFFER_SIZE ; u16_tmp!=0 ; u16_tmp-=2 )
{
g_page_buffer[u16_tmp-1]=0 ;
g_page_buffer[u16_tmp-2]=0 ;
}
}
//! Initializes the nand flash memory driver.
//!
//! The device identification is performed to initialize the
//! driver accordingly
//!
//! @param none
//!
//! @return none
//!
void nf_init ( void )
{
g_nf_init=FALSE;
// s_pending_write=FALSE;
#if (NF_GENERIC_DRIVER==TRUE)
#error Check this init...
g_n_zones = NF_N_ZONES;
g_n_blocks = NF_N_BLOCKS;
g_shift_block_page = NF_SHIFT_BLOCK_PAGE;
g_shift_page_byte = NF_SHIFT_PAGE_BYTE;
s_shift_sector_byte = NF_SHIFT_SECTOR_BYTE;
g_n_row_cycles = NF_N_ROW_CYCLES;
if ( Is_nf_2k() ) // 2KB pages
{
g_ofst_blk_status = 0;
}
if ( Is_nf_512() ) // 512B pages
{
g_ofst_blk_status = 5;
}
s_shift_log_page_sector = G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE + NF_SHIFT_N_DEVICES;
s_shift_log_block_sector = s_shift_log_page_sector + G_SHIFT_BLOCK_PAGE;
#endif
g_cache_lut.ctrl.valid = FALSE; g_cache_lut.ctrl.dirty = FALSE;
g_cache_fbb.ctrl.valid = FALSE; g_cache_fbb.ctrl.dirty = FALSE;
}
//! Ensure that the memory is in a good state before starting to use it
//!
//! The function will scan the memory, test if the memory is valid, clean it
//! if it has to and rebuild all the management blocks. This function shall be
//! called prior to any use of the memory after a power-up.
//!
//! @param none
//!
//! @return a status:
//! PASS if the command has been succesfully executed;
//! FAIL else
//!
Status_bool nf_verify_resume( void )
{
U8 u8_nb_loop;
Bool status_bool;
// Speed-up NF initialization
pll_on();
clk_cpu_boost(CLK_CPU_BOOST);
#if (ISP_VERSION<0x04) // Static area with fixed length
nf_scan_static_area(); // Look for static area limit
#endif
status_bool = nf_scan();
#if (ISP_VERSION>=0x04) // Static area length may vary
nfc_put_conf( NF_N_DEVICES, TRUE, g_nf_first_block-1 ); // NF locked (system zone only)
#endif
#if (ERASING_ALL==ENABLE)
ut_nfc_erase_all();
while(g_forever);
status_bool = nf_scan();
#endif
if(( PASS!=status_bool )
|| ( is_nf_invalid() ) // The NF is not cleanly built
) {
// The NF seems not cleanly built, or not built at all.
//
u8_nb_loop = 0;
while( 1 )
{
u8_nb_loop++;
if( u8_nb_loop > 2 )
{
status_bool=FAIL;
break; // Error NF access or control
}
nf_cleanup_memory();
if( PASS != nf_scan() )
continue;
if( PASS != nf_rebuild() )
continue;
status_bool = PASS;
break;
}
}
if (status_bool==PASS)
{
g_nf_init = TRUE;
Nf_check_lut();
Nf_check_fbb( FALSE );
}
clk_cpu_boost(CLK_CPU_NORMAL);
pll_off();
return status_bool;
}
//! Cleanup the memory by erasing all the management blocks.
//!
//! The sub-LUT blocks, the recovery block and the free-blocks block
//! will be erased on any devices.
//!
//! @param none
//!
void nf_cleanup_memory(void)
{
U8 i_dev =0;
U16 i_block=0;
U8 block_valid;
U8 block_id;
// Scan all the devices and looks for:
// - the sub-LUT
// - the recovery block
// - the free-blocks block
//
for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
{
// Select the devices
//
Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -