⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nf_mngt.c

📁 mp3播放器
💻 C
字号:
//! @file nf_mngt.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.
//!
//! It supports 1, 2 or 4 Nands of same type. Type can be 512B or 2kB Nand.
//!
//! @version 1.62 snd3-refd1-1_9_5 $Id: nf_mngt.c,v 1.62 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)
#define NF_ECC_MNGT    (ENABLE)

#include "config.h"
#include "conf\conf_nf.h"
#include "lib_mcu\nfc\nfc_drv.h"
#include "nf_mngt.h"
#include "modules\control_access\dfc_mngt.h"
#include "lib_mcu\int\int_drv.h"

#include "conf\conf_clock.h"
#include "lib_mcu\debug.h"


//_____ D E F I N I T I O N ________________________________________________

//#error Attention au modulo, call uidiv, uldiv, ...
//Se servir plus souvent du Random Data Input pour le code 2K (cr閍tion de LUT)

#if( NF_BAD_CONFIG==(FALSE) )

//_____ M A C R O S ________________________________________________________


//_____ P R I V A T E    D E C L A R A T I O N _____________________________

// Static definition, which can be optimized by the compiler
//
#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
extern _MEM_TYPE_FAST_        U8    g_n_row_cycles          ; // number of row cycles to access a page of the NF memory
extern _MEM_TYPE_SLOW_        U8    g_copy_back_cont        ; // 0 = copy back not supported, N = number of    CONTINUE subdivision contraint on copyback
extern _MEM_TYPE_SLOW_        U8    g_copy_back_discont     ; // 0 = copy back not supported, N = number of DISCONTINUE subdivision contraint on copyback
#endif

#if (NF_GENERIC_DRIVER==TRUE)
       _MEM_TYPE_FAST_        U8    g_shift_page_byte       ; // (1<<n) size of page,   unit in bytes
       _MEM_TYPE_FAST_        U8    g_shift_block_page      ; // (1<<n) size of physical block,  unit in pages
       _MEM_TYPE_SLOW_        U8    g_ofst_blk_status       ; // Offset of Block Status information in spare zone
static _MEM_TYPE_SLOW_        U8    s_shift_sector_byte     ; // (1<<n) size of sector, unit in bytes
static _MEM_TYPE_SLOW_        U8    s_shift_log_page_sector ; // (1<<n) size of logical   page,  unit in sectors
static _MEM_TYPE_SLOW_        U8    s_shift_log_block_sector; // (1<<n) size of logical  block,  unit in sectors
#endif


       Bool g_fatal       ; // Used in LUT/FBB building and ECC management...


static Bool s_mem         ;
#if (defined ATMEL_WARNING)
#  warning In waiting for a recoding of the control_access module.
#endif
static Bool s_start       ;

       _MEM_TYPE_SLOW_ U32  g_copy_src                         ; // Used to copy NF pages (source page)
       _MEM_TYPE_SLOW_ U16  g_nf_first_block=0                 ; // Block addr of the beginning of dynamic area

typedef enum
{
   STATE_READ_INIT=0       // The very first open_read must be done
,  STATE_READ_RESUME_PAGE  // A page has been read
,  STATE_WRITE_INIT        // The very first open_write must be done
,  STATE_WRITE_RESUME_PAGE // A page has been written
,  STATE_COMPLETE          // The read or write session is over.
} Nf_state;


       _MEM_TYPE_SLOW_ Cache_lut g_cache_lut; // LUT cache
       _MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb; // Free-Blocks block cache


       _MEM_TYPE_SLOW_ U8   g_page_buffer[NF_FULL_PAGE_BUFFER_SIZE] ; // Used to bufferize a page

// Dynamic variables
//
static _MEM_TYPE_SLOW_    U32       s_save_log_addr              ; // Used for Stand-by / Restart operations
static _MEM_TYPE_SLOW_    U16       s_save_n_sector              ; // Used for Stand-by / Restart operations
static _MEM_TYPE_SLOW_    U32       s_save2_log_addr             ; // Used for Stand-by / Restart operations
static _MEM_TYPE_SLOW_    U16       s_save2_n_sector             ; // Used for Stand-by / Restart operations
       _MEM_TYPE_BIT_     bit       g_nf_init                    ; // Boolean set when driver is initialized
       _MEM_TYPE_MEDFAST_ U16       g_log_block_id               ; // Logical Block address
       _MEM_TYPE_SLOW_    U16       g_n_export_blocks=(U16)-1    ; // Number of physical blocks exported for mass-storage use
       _MEM_TYPE_SLOW_    U16       g_n_free_blocks              ; // Number of free physical blocks
       _MEM_TYPE_SLOW_    U8        g_n_sub_lut                  ; // Holds the number of sub-Lut
       _MEM_TYPE_SLOW_    U16       g_sub_lut_log_sz             ; // Size of the sub-LUT. Unit in number of logical blocks
       _MEM_TYPE_SLOW_    U16       g_last_sub_lut_log_sz        ; // Size of the last sub-LUT. Unit in number of logical blocks
       _MEM_TYPE_SLOW_    U16       g_fbb_block_addr             ; // Free-Blocks block address
       _MEM_TYPE_SLOW_    U8        g_fbb_block_index            ; // Free-Blocks block index
       _MEM_TYPE_SLOW_    U16       g_lut_block_addr [ N_SUBLUT ]; // LUT block address
       _MEM_TYPE_SLOW_    U8        g_lut_block_index[ N_SUBLUT ]; // LUT index, unit in (LUT size/page size)

static _MEM_TYPE_FAST_    U16       s_n_sectors                  ; // Holds the number of sectors to read/write
static _MEM_TYPE_FAST_    U8        s_nb_sectors_step            ; // Holds the number of sectors read after each page
       _MEM_TYPE_FAST_    U8        g_curr_dev_id                ; // Holds the current device number that is used
static _MEM_TYPE_FAST_    U16       s_curr_n_byte                ; // Holds the position in the page
static _MEM_TYPE_FAST_    U32       s_curr_log_sector            ; // Holds the logical sector number
       _MEM_TYPE_SLOW_    U32       g_last_log_sector = -1       ; // Holds the last logical sector number on which a Write has been done
static _MEM_TYPE_FAST_    Nf_state  s_state                      ; // Holds the current state of the driver

       _MEM_TYPE_SLOW_    U16       g_block_to_kill[ NF_N_DEVICES]    ; // Holds the blocks number which will be erased
       _MEM_TYPE_FAST_    U32       g_phys_page_addr[NF_N_DEVICES]    ; // Holds the current phys page number for each device

       _MEM_TYPE_SLOW_    U32       g_save_phys_page_addr             ; // Holds the previous phys page number
       _MEM_TYPE_SLOW_    U8        g_save_curr_dev_id                ; // Holds the previous device number that is used

       _MEM_TYPE_FAST_    U32       g_next_phys_page_addr             ; // Holds the previous phys page number

typedef enum
{
   NF_TRANS_NORMAL  // make simple translation.
,  NF_TRANS_FLUSH   // make simple translation. Force flush of LUT and FBB caches.
,  NF_TRANS_SWAP    // Swap blocks LUT <-> FBB
} Nf_translate_mode;


//_____ P R I V A T E    F U N C T I O N S _________________________________
//
static void        nf_translate( Nf_translate_mode mode );
static Status_bool nf_open_read(    bit check_pending_write );
static Status_bool nf_open_write(   bit check_pending_write );
static void        nf_cache_lut_refill( U16 log_block_id  );
static void        nf_cache_lut_flush( void  );
static void        nf_erase_old_blocks( void );

//_____ F U N C T I O N S __________________________________________________
//



//! Ensure that the memory is in a good state before starting to use it
//!
//! @param none
//!
//! @return a status:
//!           PASS if the command has been succesfully executed;
//!           FAIL else
//!
Status_bool nf_verify( void )
{
   if ( g_nf_init ) return PASS;

   return nf_verify_resume();
}



//! Initializes the NF driver on the first USB Test Unit Ready.
//!
//! @param none
//!
//! @return CTRL_GOOD if ok,
//!         CTRL_NO_PRESENT in case of problems.
//!
Ctrl_status nf_test_unit_ready ( void )
{
   return ( nf_verify()==PASS ) ? CTRL_GOOD : CTRL_FAIL;
}


//! Returns the address of the last valid logical sector.
//!
//! @param none
//!
//! @return CTRL_GOOD if ok,
//!         CTRL_NO_PRESENT in case of problems.
//!
Ctrl_status nf_read_capacity (U32  *u32_nb_sector )
{
   Status_bool status_bool=nf_verify();

   *u32_nb_sector = nf_get_sectors_number()-1;
   return ( status_bool==PASS ) ? CTRL_GOOD : CTRL_FAIL;
}


Bool  nf_wr_protect ( void )
{
    return FALSE;
}

#if 0
Bool  nf_removal ( void )
{
    return TRUE;
}
#endif


//! Returns a pointer on the internal buffer address.
//!
//! This function is used for test only.
//!
//! @param none
//!
//! @return pointer on an internal buffer of 2112 bytes.
//!
#if 0
U8*  nf_get_buffer_addr         ( void ) { return g_page_buffer; }
#endif


//! Returns the total number of sectors that can be used on
//! the memory.
//!
//! This number is computed during the power on, after a scan
//! of the memory.
//!
//! @param none
//!
//! @return Number of sectors.
//!
U32  nf_get_sectors_number      ( void )
{
   return
      (U32)g_n_export_blocks
   << (G_SHIFT_BLOCK_PAGE +G_SHIFT_PAGE_BYTE -S_SHIFT_SECTOR_BYTE)
   ;
}



U32 nf_block_2_page(U16 block_addr)
{
   return (U32)block_addr<<G_SHIFT_BLOCK_PAGE;
}



//! This function initializes the Nand Flash for a read operation.
//!
//! @param log_sector   Logical sector address to start read
//! @param nb_sector    Number of sectors to transfer
//! @param sense        NF_READ for a read, NF_WRITE for a write
//!
//! @return CTRL_GOOD if ok, CTRL_FAIL if read outside memory
//!
Ctrl_status nf_10( U32 log_sector , U16 n_sectors, Nf_sense sense )
{
   if ( !g_nf_init )
      while(1);   // You shall call once mem_test_unit_ready() before.

   // Test that the logical sector address is valid
   //
   if ( 0==n_sectors )                                   { return CTRL_GOOD; }
   if ( (log_sector+n_sectors)>nf_get_sectors_number() ) { return CTRL_FAIL; }

   trace("nf_10 ["); trace_hex32(log_sector); trace("-"); trace_hex32(log_sector+n_sectors-1);
   trace( (NF_READ==sense) ? "] Read" : "] Write" );
   trace("\n\r");
   s_n_sectors       = n_sectors;
   s_curr_log_sector = log_sector;
   trace("nf_10 s_curr_log_sector="); trace_hex32(s_curr_log_sector); trace_nl();
   s_state           = (NF_READ==sense) ? STATE_READ_INIT : STATE_WRITE_INIT;
   s_save_log_addr   = log_sector + n_sectors;
   g_fatal           = FALSE;
   s_mem             = TRUE;
   s_start           = TRUE;
   return CTRL_GOOD;
}



//_____ P R I V A T E    F U N C T I O N S _________________________________
//


//! This function interrupts the current transfer and save the value necessary to restart it later.
//!
//! @param  u16_nb_sector_remaining     number of sector remaining after the stop
//!
void  nf_dfc_read_standby(U16 u16_nb_sector_remaining)
{
//   not tested since abort is not possible on 1st silicon
   s_save_log_addr-= u16_nb_sector_remaining;
   s_save_n_sector = u16_nb_sector_remaining;
   nf_dfc_read_stop( u16_nb_sector_remaining );
   s_mem             = FALSE;
   s_start           = FALSE;
   s_save2_log_addr = s_save_log_addr;
   s_save2_n_sector = s_save_n_sector;
}



//! This function restarts the transfer which was interrupted.
//!
void  nf_dfc_read_restart(void)
{
//   not tested since abort is not possible on 1st silicon
   nf_10( s_save2_log_addr , s_save2_n_sector, NF_READ );
}



//! This function interrupts the current transfer and save the value necessary to restart it later.
//!
//! @param  u16_nb_sector_remaining     number of sector remaining after the stop
//!
//void  nf_dfc_write_standby(U16 u16_nb_sector_remaining)
//{
//   not tested
//   ... lot of stuff to do...
//   Determiner ou on en est rest

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -