nf_mngt.c File Reference

#include "config.h"
#include "conf_nf.h"
#include "nf.h"
#include "nf_drv.h"
#include "nf_mngt.h"
#include "lib_mcu/usb/usb_drv.h"
#include "lib_mcu/debug.h"

Include dependency graph for nf_mngt.c:

Go to the source code of this file.

Defines

#define _TRACE_   (DISABLE)
#define NF_ECC_MNGT   (DISABLE)
#define U16_FBB_OFST   ((U16)NF_N_DEVICES*g_cache_fbb.p + S_MNGT_DEV)

Enumerations

enum  Nf_state {
  STATE_READ_INIT = 0, STATE_READ_RESUME_PAGE, STATE_WRITE_INIT, STATE_WRITE_RESUME_PAGE,
  STATE_COMPLETE
}
enum  Nf_translate_mode { NF_TRANS_NORMAL, NF_TRANS_FLUSH, NF_TRANS_SWAP }

Functions

__no_init volatile
xdata Byte
nf_send_cmd 
At (0x3900)
__no_init volatile
xdata Byte
nf_send_add 
At (0x3A00)
__no_init volatile
xdata Byte nf_data 
At (0x3800)
static void nf_translate (Nf_translate_mode mode)
 Translate a logical sector to physical parameters.
static Status_bool nf_open_read (bit check_pending_write)
 Prepare a read session on the flash memory.
static Status_bool nf_open_write (bit check_pending_write)
 Prepare a write session on the flash memory.
static void nf_cache_lut_refill (U16 log_block_id)
 Reload the LUT cache memory, starting from the specified logical block number given.
static void nf_cache_lut_flush (void)
 Flushes the LUT cache into a new LUT entry.
static void nf_erase_old_blocks (void)
 Erase the source blocks.
U8 nf_xfer_update_vars (void)
 This function update transfer variables, check if operation (read/write) is finished This function may be used either with READ and WRITE operations.
void nf_write_sector_from_usb (U8 nb_sectors)
 This function transfers USB data to the NF page The number of sectors to be read can be 1 up to 4 (more than 1 is available only for memories with 2kb pages).
void nf_read_sector_to_usb (U8 nb_sectors)
 This function transfers a page content (NF) to the USB macro The number of sectors to be read can be 1 up to 4 (more than 1 is available only for memories with 2kb pages).
void nf_update_spare_zone (U8 sect_start, U8 nb_sect)
 This function updates the spare zone of each page that has been finished to be written.
Status_bool nf_verify (void)
 Ensure that the memory is in a good state before starting to use it.
Ctrl_status nf_test_unit_ready (void)
 Initializes the NF driver on the first USB Test Unit Ready.
Ctrl_status nf_read_capacity (U32 *u32_nb_sector)
 Returns the address of the last valid logical sector.
Bool nf_wr_protect (void)
Bool nf_removal (void)
U32 nf_get_sectors_number (void)
 Returns a pointer on the internal buffer address.
U32 nf_block_2_page (U16 block_addr)
Ctrl_status nf_read_10 (U32 log_sector, U16 n_sectors)
 This function initializes the Nand Flash for a read operation.
Ctrl_status nf_write_10 (U32 log_sector, U16 n_sectors)
 This function initializes the Nand Flash for a write operation.
Ctrl_status nf_dfc_write_stop (U16 u16_nb_sector_remaining)
 This function must be called when a write10 operation (from USB) is finished Last page written is programmed and environment is saved.
void nf_cache_fbb_refill (void)
 Reload the FBB cache memory, starting from 0.
Status_bool nf_write_lut (U8 pos, U8 i_sub_lut, U16 sub_lut_log_sz)
 Writes a LUT in memory from a buffer.
void nf_cache_fbb_flush (Bool b_ecc_err)
 Flushes the FBB cache into a new FBB entry.
Status_bool nf_write_fbb (void)
 Writes the Free-blocks block into the Nand Flash.
static void nf_check_fbb (Bool b_ecc_err)
static void nf_check_lut (void)
void nf_copy_tail (void)
void nf_download (U8 _MEM_TYPE_SLOW_ *datbuf, U8 loop)
 Download packets of 16 bytes from RAM to the NAND Flash.
void nf_upload (U8 _MEM_TYPE_SLOW_ *datbuf, U8 loop)
 Upload packets of 16 bytes from the NAND Flash to RAM.
void nf_copy (U32 copy_dst)
 Copy a NF page to a new one.
void nf_swap (U8 dev_id, U8 u8_ofst_lut, U8 u8_ofst_fbb)
 Swap 2 blocks from the LUT and the FBB.
void nf_usb_stop (void)
 This function perform a last copy tail if required, when USB enters suspend or is disconnected This function may be declared in "conf_usb.h" for "Usb_suspend_action()" and "Usb_vbus_off_action()" /!\ "g_last_log_sector" must be initialized to "0xFFFFFFFF" at startup to avoid spurious writes on during USB plug-in.
void nf_erase_all_blocks (void)
Ctrl_status nf_ram_2_nf (U32 addr, U8 *ram)
 This fonction initialise the memory for a write operation from ram buffer.
Ctrl_status nf_nf_2_ram (U32 addr, U8 *ram)
 This fonction read 1 sector from NF to ram buffer.

Variables

_MEM_TYPE_SLOW_ U8 g_n_zones
_MEM_TYPE_SLOW_ U16 g_n_blocks
_MEM_TYPE_FAST_ U8 g_n_row_cycles
_MEM_TYPE_SLOW_ U8 g_copy_back_cont
_MEM_TYPE_SLOW_ U8 g_copy_back_discont
_MEM_TYPE_FAST_ U8 g_shift_page_byte
_MEM_TYPE_FAST_ U8 g_shift_block_page
_MEM_TYPE_SLOW_ U8 g_ofst_blk_status
static _MEM_TYPE_SLOW_ U8 s_shift_sector_byte
static _MEM_TYPE_SLOW_ U8 s_shift_log_page_sector
static _MEM_TYPE_SLOW_ U8 s_shift_log_block_sector
Bool g_fatal
static Bool s_mem
static Bool s_start
_MEM_TYPE_SLOW_ U32 g_copy_src
_MEM_TYPE_SLOW_ U16 g_nf_first_block = 0
_MEM_TYPE_SLOW_ Cache_lut g_cache_lut
_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb
_MEM_TYPE_SLOW_ U8 g_page_buffer [((2048)+(2048)/32)]
static
_MEM_TYPE_SLOW_ U32 
s_save_log_addr
_MEM_TYPE_BIT_ bit g_nf_init
_MEM_TYPE_MEDFAST_ U16 g_log_block_id
_MEM_TYPE_SLOW_ U16 g_n_export_blocks = 0xFFFF
_MEM_TYPE_SLOW_ U16 g_n_free_blocks
_MEM_TYPE_SLOW_ U8 g_n_sub_lut
_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz
_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz
_MEM_TYPE_SLOW_ U16 g_fbb_block_addr
_MEM_TYPE_SLOW_ U8 g_fbb_block_index
_MEM_TYPE_SLOW_ U16 g_lut_block_addr [(NF_N_DEVICES *(8 *1024)/(512/2))]
_MEM_TYPE_SLOW_ U8 g_lut_block_index [(NF_N_DEVICES *(8 *1024)/(512/2))]
static
_MEM_TYPE_FAST_ U16 
s_n_sectors
static _MEM_TYPE_FAST_ U8 s_nb_sectors_step
_MEM_TYPE_FAST_ U8 g_curr_dev_id
static
_MEM_TYPE_FAST_ U16 
s_curr_n_byte
static
_MEM_TYPE_FAST_ U32 
s_curr_log_sector
_MEM_TYPE_SLOW_ U32 g_last_log_sector = 0xFFFFFFFF
static
_MEM_TYPE_FAST_
Nf_state 
s_state
_MEM_TYPE_SLOW_ U16 g_block_to_kill [NF_N_DEVICES]
_MEM_TYPE_FAST_ U32 g_phys_page_addr [NF_N_DEVICES]
_MEM_TYPE_SLOW_ U32 g_save_phys_page_addr
_MEM_TYPE_SLOW_ U8 g_save_curr_dev_id
_MEM_TYPE_FAST_ U32 g_next_phys_page_addr


Detailed Description

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.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file nf_mngt.c.


Define Documentation

#define _TRACE_   (DISABLE)

Definition at line 52 of file nf_mngt.c.

#define NF_ECC_MNGT   (DISABLE)

Definition at line 53 of file nf_mngt.c.

#define U16_FBB_OFST   ((U16)NF_N_DEVICES*g_cache_fbb.p + S_MNGT_DEV)

Referenced by nf_cache_lut_flush().


Enumeration Type Documentation

enum Nf_state

Enumerator:
STATE_READ_INIT 
STATE_READ_RESUME_PAGE 
STATE_WRITE_INIT 
STATE_WRITE_RESUME_PAGE 
STATE_COMPLETE 

Definition at line 119 of file nf_mngt.c.

00120 {
00121    STATE_READ_INIT=0       // The very first open_read must be done
00122 ,  STATE_READ_RESUME_PAGE  // A page has been read
00123 ,  STATE_WRITE_INIT        // The very first open_write must be done
00124 ,  STATE_WRITE_RESUME_PAGE // A page has been written
00125 ,  STATE_COMPLETE          // The read or write session is over.
00126 } Nf_state;

enum Nf_translate_mode

Enumerator:
NF_TRANS_NORMAL 
NF_TRANS_FLUSH 
NF_TRANS_SWAP 

Definition at line 169 of file nf_mngt.c.

00170 {
00171    NF_TRANS_NORMAL  // make simple translation.
00172 ,  NF_TRANS_FLUSH   // make simple translation. Force flush of LUT and FBB caches.
00173 ,  NF_TRANS_SWAP    // Swap blocks LUT <-> FBB
00174 } Nf_translate_mode;


Function Documentation

__no_init volatile xdata Byte nf_send_cmd At ( 0x3900   ) 

__no_init volatile xdata Byte nf_send_add At ( 0x3A00   ) 

__no_init volatile xdata Byte nf_data At ( 0x3800   ) 

static void nf_translate ( Nf_translate_mode  mode  )  [static]

Translate a logical sector to physical parameters.

This function translates the logical sector address to a physical page number. Then, the block used are swapped with free blocks. The LUT and FBB caches are used for that purpose. Assumption is made that there is at least 2 free entries in the FBB cache: one to swap the LUT blocks, and another one to recycle the FBB block itself (if needed).

Parameters:
modify_lut FALSE for simple translation, TRUE if LUT shall be modified (write session) <global parameters>="">
Returns:
none

Definition at line 1743 of file nf_mngt.c.

References _MEM_TYPE_MEDFAST_, FALSE, G_SHIFT_PAGE_BYTE, Min, nf_block_2_page(), nf_cache_fbb_flush(), nf_cache_fbb_refill(), nf_cache_lut_flush(), nf_cache_lut_refill(), Nf_check_fbb, Nf_check_lut, NF_N_DEVICES, nf_swap(), NF_TRANS_FLUSH, NF_TRANS_SWAP, S_SHIFT_LOG_BLOCK_SECTOR, S_SHIFT_LOG_PAGE_SECTOR, S_SHIFT_SECTOR_BYTE, SIZE_BLOCK_PAGE, SIZE_PAGE_SECTOR, trace(), trace_hex32(), trace_nl(), trace_u8(), and TRUE.

Referenced by nf_dfc_write_stop(), nf_open_read(), nf_open_write(), nf_ram_2_nf(), and nf_write_10().

01744 {
01745    _MEM_TYPE_MEDFAST_ U8  u8_tmp   = (s_curr_log_sector & (SIZE_PAGE_SECTOR -1) );
01746    _MEM_TYPE_MEDFAST_ U8  u8_shift;
01747    _MEM_TYPE_MEDFAST_ U8  u8_curr_page;
01748    _MEM_TYPE_MEDFAST_ U8  u8_last_page;
01749 
01750    // Here begins the translation:
01751    // logical sector number (s_curr_log_sector):
01752    //
01753    // -> logical block number       (g_log_block_id)
01754    // -> device number              (g_curr_dev_id)
01755    // -> position in page           (s_curr_n_byte)
01756    // -> nb of sectors in first page(s_nb_sectors_step)
01757    //
01758    g_log_block_id    =  s_curr_log_sector >> S_SHIFT_LOG_BLOCK_SECTOR;
01759    g_curr_dev_id     = (s_curr_log_sector >> (G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE)) % NF_N_DEVICES;
01760    s_curr_n_byte     = ((U16)u8_tmp) << S_SHIFT_SECTOR_BYTE;
01761    s_nb_sectors_step = SIZE_PAGE_SECTOR - u8_tmp;
01762    s_nb_sectors_step = Min(s_n_sectors, s_nb_sectors_step); // Adapt if nb sector to read is lower than a page
01763 
01764 //   Nfc_put_lba(g_log_block_id);
01765 
01766    Nf_check_fbb( FALSE );
01767    Nf_check_lut();
01768 
01769    if ( TRUE==g_cache_lut.ctrl.valid )
01770    {
01771       if( NF_TRANS_FLUSH==mode )
01772       {
01773          if ( TRUE==g_cache_lut.ctrl.dirty )
01774          {
01775             nf_cache_lut_flush();
01776             nf_cache_lut_refill(g_log_block_id);
01777          }
01778       }
01779 
01780       if(( g_log_block_id<g_cache_lut.first )
01781       || ( g_log_block_id>g_cache_lut.last  ))
01782       { // MISS: need to refill the cache
01783 
01784          if ( TRUE==g_cache_lut.ctrl.dirty ) { nf_cache_lut_flush(); }
01785          nf_cache_lut_refill(g_log_block_id);
01786       }
01787    }
01788    else { nf_cache_lut_refill(g_log_block_id); } // The cache is not valid. Just re-fill it.
01789 
01790 
01791 
01792    if ( TRUE==g_cache_fbb.ctrl.valid )
01793    {
01794       if( NF_TRANS_FLUSH==mode )
01795       {
01796          if ( TRUE==g_cache_fbb.ctrl.dirty )
01797          {
01798             nf_cache_fbb_flush( FALSE );
01799             nf_cache_fbb_refill();
01800          }
01801       }
01802    }
01803    else { nf_cache_fbb_refill(); }
01804 
01805 
01806 
01807    u8_curr_page = (g_log_block_id-g_cache_lut.first)*NF_N_DEVICES;
01808    u8_last_page = (U16)g_cache_fbb.p*NF_N_DEVICES;
01809 
01810    for( u8_tmp=0 ; u8_tmp<NF_N_DEVICES ; u8_tmp++, u8_curr_page++, u8_last_page++)
01811    {
01812       if( NF_TRANS_SWAP==mode )
01813       {
01814          nf_swap(u8_tmp, u8_curr_page, u8_last_page);
01815       }
01816 
01817       g_phys_page_addr[u8_tmp] = nf_block_2_page( g_cache_lut.mem[u8_curr_page] ); // ... Then adapt it to page number
01818    }
01819 
01820    if( NF_TRANS_SWAP==mode )
01821    {
01822       g_cache_fbb.p++;
01823       if( g_cache_fbb.p==(g_cache_fbb.max-1) )
01824       { // Only 1 remaining entry in FBB cache
01825          nf_cache_fbb_flush( FALSE ); // No dirty test, since we know that the cache is dirty
01826          nf_cache_fbb_refill();
01827       }
01828    }
01829    else
01830    {
01831       // Build the physical memory address
01832       //
01833       u8_shift =                                          // page offset is
01834          ( s_curr_log_sector >> S_SHIFT_LOG_PAGE_SECTOR ) // convert sector id to page id
01835       &  ( SIZE_BLOCK_PAGE  -1                          ) // modulo number of phys pages in a phys block
01836       ;
01837 
01838       for ( u8_tmp=0 ; u8_tmp<NF_N_DEVICES ; u8_tmp++ )
01839       {
01840          if ( u8_tmp<g_curr_dev_id ) { g_phys_page_addr[u8_tmp] +=  u8_shift + 1 ; } // already read
01841          else                        { g_phys_page_addr[u8_tmp] +=  u8_shift     ; } // to be read
01842       }
01843    }
01844 
01845    g_next_phys_page_addr=g_phys_page_addr[g_curr_dev_id];
01846    trace("nf_translate;g_phys_page_addr["); trace_u8(g_curr_dev_id); trace("] = "); trace_hex32(g_phys_page_addr[g_curr_dev_id]); trace_nl();
01847 }

Here is the call graph for this function:

Here is the caller graph for this function:

static Status_bool nf_open_read ( bit  check_pending_write  )  [static]

Prepare a read session on the flash memory.

This function translate the logical sector address to a physical page number. The LUT cache is used.

Parameters:
s_curr_log_sector static that should be initialized before
Returns:
a status: PASS if the function has been succesfully executed;

Definition at line 847 of file nf_mngt.c.

References nf_copy_tail(), NF_TRANS_FLUSH, nf_translate(), and PASS.

Referenced by nf_nf_2_ram(), and nf_read_10().

00848 {
00849    if(( check_pending_write   )
00850    && ( 0xFFFFFFFF!=g_last_log_sector ))
00851    {
00852       nf_copy_tail();
00853    }
00854 
00855    // Both LUT and FBB caches are flushed. Why?
00856    // - Avoid LUT/FBB caches flush and refill during audio playback
00857    // - Avoid recovery on power-on
00858    nf_translate( NF_TRANS_FLUSH );
00859 
00860    return PASS;
00861 }

Here is the call graph for this function:

Here is the caller graph for this function:

static Status_bool nf_open_write ( bit  check_pending_write  )  [static]

Prepare a write session on the flash memory.

This function translates the logical sector address to a physical page number. Then, the block used are swapped with free blocks. The LUT and FBB caches are used for that purpose. The head of the used block(s) are copied into the free block(s). Assumption is made that there is at least 2 free entries in the FBB cache: one to swap the LUT blocks, and another one to recycle the FBB block itself (if needed).

Parameters:
static that should be initialized before
Returns:
a status: PASS if the function has been succesfully executed;

Definition at line 880 of file nf_mngt.c.

References _MEM_TYPE_SLOW_, nf_block_2_page(), nf_copy(), nf_copy_tail(), nf_download(), NF_N_DEVICES, NF_PAGE_PROGRAM_CMD, NF_SPARE_POS, NF_TRANS_SWAP, nf_translate(), nf_upload(), NFC_ACT_DEV_SELECT, Nfc_action, NFC_OFST_3_DATA_SRC, NFC_OFST_6_FBB_INVALID, nfc_open_page_read(), nfc_open_page_write(), Nfc_set_cmd, NFC_SPARE_OFST_3_BYTE_3, NFC_SPARE_OFST_6_LBA, Nfc_wr_data, PASS, S_MNGT_DEV, S_SHIFT_LOG_PAGE_SECTOR, SIZE_BLOCK_PAGE, SIZE_PAGE_SECTOR, and SIZE_SECTOR_BYTE.

Referenced by nf_ram_2_nf(), and nf_write_10().

00881 {
00882    U8  u8_tmp;
00883    _MEM_TYPE_SLOW_ U8  u8_curr_page;
00884    _MEM_TYPE_SLOW_ U8  u8_last_page;
00885    U16 u16_tmp;
00886 
00887    if(( check_pending_write   )
00888    && ( 0xFFFFFFFF!=g_last_log_sector ))
00889    {
00890       nf_copy_tail();
00891    }
00892 
00893    nf_translate( NF_TRANS_SWAP );
00894 
00895    // both FBB and LUT blocks are invalid
00896    // Mark FBB only. Warning: Partial Prog
00897    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
00898    nfc_open_page_write(
00899       nf_block_2_page( g_fbb_block_addr )  // base address
00900    +  (U32)g_fbb_block_index               // offset to Free-blocks block entry
00901    ,  NF_SPARE_POS+NFC_SPARE_OFST_6_LBA );
00902    Nfc_wr_data( NFC_OFST_6_FBB_INVALID );                         // 6- FBB-LUTs are invalid
00903    Nfc_set_cmd( NF_PAGE_PROGRAM_CMD );                            // Warning: Partial Programming
00904 
00905    // Mark sources blocks (recovery). Warning: Partial Prog
00906    for( u8_tmp=0 ; u8_tmp<NF_N_DEVICES ; u8_tmp++ )
00907    {
00908       Nfc_action(NFC_ACT_DEV_SELECT, u8_tmp);
00909       nfc_open_page_write(
00910          nf_block_2_page( g_block_to_kill[u8_tmp] )
00911       ,  NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3 );
00912       Nfc_wr_data( NFC_OFST_3_DATA_SRC );                         // 3- [SW] Mark as source block (recovery) (HW capability not used)
00913       Nfc_set_cmd( NF_PAGE_PROGRAM_CMD );                         // Warning: Partial Programming
00914    }
00915 
00916    // Copy the head of the buffer
00917    //
00918    // for each logical page (current included)
00919    u8_last_page= (s_curr_log_sector >>S_SHIFT_LOG_PAGE_SECTOR) & (SIZE_BLOCK_PAGE -1);
00920    for(  u8_curr_page=0
00921    ;     u8_curr_page <= u8_last_page
00922    ;     u8_curr_page++ )
00923    {
00924       // If the last page (current)
00925       if ( u8_last_page==u8_curr_page ) { u8_tmp = g_curr_dev_id; } // then copy this physical page only for the device before the current device
00926       else                              { u8_tmp = NF_N_DEVICES;  } // else copy this physical page for all device
00927 
00928       while( u8_tmp!=0 ) // for each device
00929       {
00930          u8_tmp--;
00931          Nfc_action(NFC_ACT_DEV_SELECT, u8_tmp);
00932 
00933          g_copy_src= nf_block_2_page( g_block_to_kill[u8_tmp] ) + u8_curr_page;
00934          nf_copy(g_phys_page_addr[u8_tmp]);
00935          g_phys_page_addr[u8_tmp]++;
00936       }
00937       // end of loop, for each device
00938    }
00939    // end of loop, for each logical page
00940 
00941    u16_tmp=
00942       (SIZE_SECTOR_BYTE)                          // size (unit byte) of the sector (spare zone excluded)
00943    *  (  s_curr_log_sector                        // current sector in physical page
00944       &  (SIZE_PAGE_SECTOR -1)
00945       );
00946 
00947    Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);
00948    if( u16_tmp )
00949    {
00950       //** copy the head of the current physical page
00951       nfc_open_page_read( nf_block_2_page( g_block_to_kill[g_curr_dev_id] ) + u8_last_page, 0 );
00952       // copy the head page of the old block in buffer
00953       nf_upload(g_page_buffer, (U8)(u16_tmp/16));
00954    }
00955 
00956    // copy the buffer in the head page of the new block
00957    nfc_open_page_write( g_phys_page_addr[g_curr_dev_id], 0 );
00958 
00959    // write the first byte to the current byte position in the physical page
00960    nf_download(g_page_buffer, (U8)(u16_tmp/16));
00961    // END of the copy head
00962 
00963    return PASS;
00964 } // nf_open_write

Here is the call graph for this function:

Here is the caller graph for this function:

static void nf_cache_lut_refill ( U16  log_block_id  )  [static]

Reload the LUT cache memory, starting from the specified logical block number given.

The cache is filled with physical blocks. The cache does only work inside a sub-LUT. If the logical number is 'near' to the end of the sub-LUT, the cache starts before the logical number, in order to be filled untill the end of the sub-LUT.

Parameters:
log_block_id logical block number.
Returns:
nothing

Definition at line 980 of file nf_mngt.c.

References _MEM_TYPE_SLOW_, Assert, CACHE_LUT_SIZE, FALSE, G_N_BLOCKS, LSB, MSB, nf_block_2_page(), NF_CACHE_LUT_LOG_SZ, NF_N_DEVICES, NF_SHIFT_SUBLUT_PHYS, NFC_ACT_DEV_SELECT, Nfc_action, nfc_open_page_read(), Nfc_rd_data_fetch_next, S_MNGT_DEV, SIZE_PAGE_BYTE, trace(), trace_hex16(), trace_hex32(), trace_nl(), and TRUE.

Referenced by nf_translate(), and nf_usb_stop().

00981 {
00982    U8  u8_tmp;
00983    U8  sub_lut_id;
00984 
00985    U16 byte_addr;
00986    _MEM_TYPE_SLOW_ U32 page_addr;
00987    _MEM_TYPE_SLOW_ U16 sub_lut_log_sz;    // size of the sub-LUT. Unit in logical blocks.
00988    _MEM_TYPE_SLOW_ U16 sub_lut_log_first; // number of the first logical block of the sub-lut.
00989 
00990    Assert( g_cache_lut.ctrl.dirty==FALSE ); // No refill if the cache is dirty
00991 
00992    sub_lut_id        = log_block_id>>(    NF_SHIFT_SUBLUT_PHYS - NF_SHIFT_N_DEVICES);
00993    sub_lut_log_sz    = ( sub_lut_id==(g_n_sub_lut-1) ? g_last_sub_lut_log_sz : g_sub_lut_log_sz );
00994    sub_lut_log_first = (U16)sub_lut_id<<( NF_SHIFT_SUBLUT_PHYS - NF_SHIFT_N_DEVICES);
00995 
00996    trace("nf_cache_lut_refill;"); trace_hex16(g_lut_block_addr[sub_lut_id]);trace_nl();
00997 
00998    if (sub_lut_log_sz<NF_CACHE_LUT_LOG_SZ)
00999    {  // The cache is bigger than the sub LUT
01000       g_cache_lut.first = log_block_id;                               // First included
01001       g_cache_lut.last  = log_block_id + (sub_lut_log_sz-1);          // Last included
01002    }
01003    else if ( (log_block_id+NF_CACHE_LUT_LOG_SZ) <= (sub_lut_log_first+sub_lut_log_sz) )
01004    {  // The cache is done starting from the logical block number
01005       g_cache_lut.first = log_block_id;                               // First included
01006       g_cache_lut.last  = log_block_id + (NF_CACHE_LUT_LOG_SZ-1);     // Last included
01007    }
01008    else
01009    {  // The cache is done starting from the last logical block of the sub-LUT
01010       g_cache_lut.last  = sub_lut_log_first +sub_lut_log_sz -1;       // Last included
01011       g_cache_lut.first = g_cache_lut.last - (NF_CACHE_LUT_LOG_SZ-1); // First included
01012    }
01013 
01014    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01015 
01016    page_addr =
01017       nf_block_2_page( g_lut_block_addr[sub_lut_id]) // base address
01018    +  (U32)(g_lut_block_index[sub_lut_id])           // offset to sub-LUT
01019    ;
01020    byte_addr = ( (g_cache_lut.first-sub_lut_log_first)*NF_N_DEVICES*2 ); // logical position of the block
01021    Assert( byte_addr<SIZE_PAGE_BYTE );
01022 
01023    nfc_open_page_read( page_addr, byte_addr);
01024    trace_hex32(page_addr); trace(";"); trace_hex16(byte_addr);trace_nl();
01025    for ( u8_tmp=0 ; u8_tmp<(g_cache_lut.last+1-g_cache_lut.first)*NF_N_DEVICES ; u8_tmp++ )
01026    { // fill the cache buffer
01027       Assert( u8_tmp<CACHE_LUT_SIZE);
01028       MSB(g_cache_lut.mem[u8_tmp]) = Nfc_rd_data_fetch_next();
01029       LSB(g_cache_lut.mem[u8_tmp]) = Nfc_rd_data_fetch_next();
01030       trace_hex16(g_cache_lut.mem[u8_tmp]);
01031       trace("-");
01032       Assert( g_cache_lut.mem[u8_tmp]>=g_nf_first_block );
01033       Assert( g_cache_lut.mem[u8_tmp]< G_N_BLOCKS       );
01034    }
01035    trace_nl();
01036    g_cache_lut.ctrl.valid = TRUE;
01037 } // end of nf_cache_lut_refill

Here is the call graph for this function:

Here is the caller graph for this function:

static void nf_cache_lut_flush ( void   )  [static]

Flushes the LUT cache into a new LUT entry.

A copy of the current LUT is made in a new page, taking into account the last LUT modification in its cache. If the block containing the LUT is full, a new block is taken from the FBB.

Parameters:
none 
Returns:
nothing

Definition at line 1099 of file nf_mngt.c.

References _debug, _MEM_TYPE_SLOW_, Assert, CACHE_LUT_SIZE, FALSE, G_N_BLOCKS, G_SHIFT_BLOCK_PAGE, LSB, MSB, nf_block_2_page(), nf_cache_fbb_flush(), nf_cache_fbb_refill(), Nf_check_fbb, Nf_check_lut, NF_N_DEVICES, NF_PAGE_BUFFER_SIZE, NF_SHIFT_SUBLUT_PHYS, NF_SUBLUT_SIZE, nf_write_lut(), NFC_ACT_DEV_SELECT, Nfc_action, nfc_erase_block(), nfc_open_page_read(), Nfc_rd_data_fetch_next, S_MNGT_DEV, trace(), trace_hex16(), trace_nl(), TRUE, and U16_FBB_OFST.

Referenced by nf_translate(), and nf_usb_stop().

01100 {
01101    _MEM_TYPE_SLOW_ U32  page_addr;
01102    U16  byte_addr;
01103    _MEM_TYPE_SLOW_ U16  sub_lut_log_sz;
01104    _MEM_TYPE_SLOW_ U8   sub_lut_id;
01105    U8   u8_tmp;
01106 
01107    Assert(TRUE==g_cache_lut.ctrl.valid);
01108    Assert(TRUE==g_cache_lut.ctrl.dirty);
01109 
01110    sub_lut_id     = g_cache_lut.first>>(NF_SHIFT_SUBLUT_PHYS-NF_SHIFT_N_DEVICES);
01111    sub_lut_log_sz = ( sub_lut_id==(g_n_sub_lut-1) ) ? g_last_sub_lut_log_sz : g_sub_lut_log_sz ;
01112 
01113    trace("nf_cache_lut_flush;"); trace_hex16(g_lut_block_addr[sub_lut_id]);trace_nl();
01114 
01115    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01116 
01117    page_addr=
01118       nf_block_2_page( g_lut_block_addr[sub_lut_id] )  // base address
01119    +  (U32)(g_lut_block_index[sub_lut_id])             // offset to sub-LUT
01120    ;
01121 
01122    nfc_open_page_read( page_addr, 0);
01123 
01124    for ( byte_addr=0 /* used as block address! */ ; byte_addr<(sub_lut_log_sz*NF_N_DEVICES) ; )
01125    {  // Read the LUT stored in Nand
01126       g_page_buffer[2*byte_addr   ] = Nfc_rd_data_fetch_next();
01127       g_page_buffer[2*byte_addr +1] = Nfc_rd_data_fetch_next();
01128 #if (_ASSERT_==ENABLE)
01129       MSB(_debug)= g_page_buffer[2*byte_addr   ];
01130       LSB(_debug)= g_page_buffer[2*byte_addr +1];
01131       Assert( _debug>=g_nf_first_block );
01132       Assert( _debug< G_N_BLOCKS       );
01133 #endif
01134       byte_addr ++;
01135    }
01136 
01137    // Modify the page
01138    //
01139    byte_addr = // logical position of the block
01140       (  g_cache_lut.first                               // Absolute logical block number...
01141       &  ( (U16)NF_SUBLUT_SIZE/NF_N_DEVICES -1)          // ...Modulo the number of logical block in a LUT
01142       )
01143    *  NF_N_DEVICES*2;
01144 
01145    Assert( byte_addr<2048 );
01146 
01147    for ( u8_tmp=0 ; u8_tmp<(g_cache_lut.last+1-g_cache_lut.first)*NF_N_DEVICES ; u8_tmp++ )
01148    {  // flush the cache buffer in the buffer
01149       Assert( u8_tmp<CACHE_LUT_SIZE );
01150       Assert( byte_addr<(NF_PAGE_BUFFER_SIZE-1) );
01151       Assert( g_cache_lut.mem[u8_tmp]>=g_nf_first_block );
01152       Assert( g_cache_lut.mem[u8_tmp]< G_N_BLOCKS       );
01153       g_page_buffer[byte_addr++] = MSB(g_cache_lut.mem[u8_tmp]) ;
01154       g_page_buffer[byte_addr++] = LSB(g_cache_lut.mem[u8_tmp]) ;
01155    }
01156 
01157    // Program the page
01158    //
01159    g_lut_block_index[sub_lut_id]++;
01160 
01161    if ( g_lut_block_index[sub_lut_id] ==  (1<<G_SHIFT_BLOCK_PAGE) )
01162    { // Need a new block for the flush
01163       _MEM_TYPE_SLOW_ U16 u16_swap;
01164 
01165       if ( FALSE==g_cache_fbb.ctrl.valid ) { nf_cache_fbb_refill(); }
01166 
01167 #define U16_FBB_OFST   ((U16)NF_N_DEVICES*g_cache_fbb.p + S_MNGT_DEV)
01168       Assert( g_cache_fbb.mem[U16_FBB_OFST]>=g_nf_first_block );
01169       Assert( g_cache_fbb.mem[U16_FBB_OFST]< G_N_BLOCKS       );
01170       u16_swap                      = g_lut_block_addr[ sub_lut_id] ;
01171       g_lut_block_addr[ sub_lut_id] = g_cache_fbb.mem[U16_FBB_OFST] ;
01172       g_cache_fbb.mem[U16_FBB_OFST] = u16_swap ;
01173       g_lut_block_index[sub_lut_id] = 0;
01174 #undef U16_FBB_OFST
01175 
01176       trace("nf_cache_lut_flush;swap;"); trace_hex16(g_lut_block_addr[sub_lut_id]);trace_nl();
01177       g_cache_fbb.ctrl.dirty=TRUE;
01178 
01179       nf_write_lut(0, sub_lut_id, sub_lut_log_sz); // TODO: we should test the status returned
01180 
01181       nfc_erase_block( nf_block_2_page( u16_swap ), TRUE );
01182 
01183       g_cache_fbb.p++;
01184       if( g_cache_fbb.p==(g_cache_fbb.max-1) )
01185       { // Only 1 remaining entry in FBB cache
01186          nf_cache_fbb_flush( FALSE ); // No dirty test, since we know that the cache is dirty
01187          nf_cache_fbb_refill();
01188       }
01189    }
01190    else
01191    {
01192       nf_write_lut(0, sub_lut_id, sub_lut_log_sz); // TODO: we should test the status returned
01193    }
01194 
01195    g_cache_lut.ctrl.dirty=FALSE;
01196 
01197    Nf_check_fbb( FALSE );
01198    Nf_check_lut();
01199 } // end of nf_cache_lut_flush

Here is the call graph for this function:

Here is the caller graph for this function:

static void nf_erase_old_blocks ( void   )  [static]

Erase the source blocks.

Parameters:
none 
Returns:
none

Definition at line 819 of file nf_mngt.c.

References i, nf_block_2_page(), NF_N_DEVICES, NFC_ACT_DEV_SELECT, Nfc_action, nfc_erase_block(), trace(), trace_hex16(), trace_nl(), and TRUE.

Referenced by nf_copy_tail(), nf_dfc_write_stop(), and nf_write_10().

00820 {
00821    U8  i;
00822 
00823    // Delete old blocks
00824    //
00825    for ( i=0 ; i<NF_N_DEVICES ; i++ )
00826    {
00827       Nfc_action(NFC_ACT_DEV_SELECT, i);
00828       trace("nf_erase_old_blocks;"); trace_hex16(g_block_to_kill[i]);trace_nl();
00829       nfc_erase_block( nf_block_2_page(g_block_to_kill[i]), TRUE );
00830    }
00831 }

Here is the call graph for this function:

Here is the caller graph for this function:

U8 nf_xfer_update_vars ( void   ) 

This function update transfer variables, check if operation (read/write) is finished This function may be used either with READ and WRITE operations.

Parameters:
none 
Returns:
TRUE if operation complete, FALSE if read/write to be continued

Definition at line 490 of file nf_mngt.c.

References FALSE, NF_N_DEVICES, SIZE_PAGE_SECTOR, STATE_COMPLETE, and TRUE.

Referenced by nf_nf_2_ram(), nf_ram_2_nf(), nf_read_10(), and nf_write_10().

00491 {
00492    if ( // Are we processing the last page ?
00493       (  (s_curr_log_sector & (SIZE_PAGE_SECTOR-1))
00494       +  s_n_sectors
00495       )
00496    <  SIZE_PAGE_SECTOR
00497    ) {
00498       s_state = STATE_COMPLETE;
00499       return TRUE;
00500    }
00501 
00502    // Update position variables
00503    s_n_sectors       -= s_nb_sectors_step;
00504    s_curr_log_sector += s_nb_sectors_step;
00505    s_curr_n_byte = 0;
00506    if (s_n_sectors < SIZE_PAGE_SECTOR)
00507      s_nb_sectors_step = (U8) (s_n_sectors);   // next page must be read as partial (not all sectors remaining)
00508    else
00509      s_nb_sectors_step = SIZE_PAGE_SECTOR;     // next page to be read considered as entire (all sectors requested)
00510 
00511    // Save current parameters
00512    g_save_curr_dev_id    = g_curr_dev_id;
00513    g_save_phys_page_addr = g_phys_page_addr[g_curr_dev_id];
00514 
00515    // Fetch the next device id
00516    //
00517    g_phys_page_addr[g_curr_dev_id]+=1;
00518    g_curr_dev_id ++;
00519    if( g_curr_dev_id==NF_N_DEVICES ) { g_curr_dev_id=0; }
00520 
00521    g_next_phys_page_addr = g_phys_page_addr[g_curr_dev_id];
00522 
00523    if( s_n_sectors==0 )    // Operation complete !
00524    {
00525      s_state = STATE_COMPLETE;
00526      return TRUE;
00527    }
00528 
00529    return FALSE;
00530 }

Here is the caller graph for this function:

void nf_write_sector_from_usb ( U8  nb_sectors  ) 

This function transfers USB data to the NF page The number of sectors to be read can be 1 up to 4 (more than 1 is available only for memories with 2kb pages).

Parameters:
nb_sectors number of sectors to be read from USB (1 sector = 512 bytes)
Returns:
none

Definition at line 632 of file nf_mngt.c.

References Is_usb_endpoint_enabled, Is_usb_read_enabled, j, Nf_wr_byte, Usb_ack_receive_out, and Usb_read_byte.

Referenced by nf_write_10().

00633 {
00634    U8 j;
00635    for (j = 8*nb_sectors ; j != 0 ; j--)        // 8 * 64 bytes = 512 bytes
00636    {
00637       while(!Is_usb_read_enabled())
00638       {
00639          if(!Is_usb_endpoint_enabled())
00640            return; // USB Reset
00641       }
00642       Disable_interrupt();                      // Global disable.
00643 
00644       Nf_wr_byte(Usb_read_byte());              // write 64 bytes to the card
00645       Nf_wr_byte(Usb_read_byte());
00646       Nf_wr_byte(Usb_read_byte());
00647       Nf_wr_byte(Usb_read_byte());
00648       Nf_wr_byte(Usb_read_byte());
00649       Nf_wr_byte(Usb_read_byte());
00650       Nf_wr_byte(Usb_read_byte());
00651       Nf_wr_byte(Usb_read_byte());
00652       Nf_wr_byte(Usb_read_byte());
00653       Nf_wr_byte(Usb_read_byte());
00654       Nf_wr_byte(Usb_read_byte());
00655       Nf_wr_byte(Usb_read_byte());
00656       Nf_wr_byte(Usb_read_byte());
00657       Nf_wr_byte(Usb_read_byte());
00658       Nf_wr_byte(Usb_read_byte());
00659       Nf_wr_byte(Usb_read_byte());
00660       Nf_wr_byte(Usb_read_byte());
00661       Nf_wr_byte(Usb_read_byte());
00662       Nf_wr_byte(Usb_read_byte());
00663       Nf_wr_byte(Usb_read_byte());
00664       Nf_wr_byte(Usb_read_byte());
00665       Nf_wr_byte(Usb_read_byte());
00666       Nf_wr_byte(Usb_read_byte());
00667       Nf_wr_byte(Usb_read_byte());
00668       Nf_wr_byte(Usb_read_byte());
00669       Nf_wr_byte(Usb_read_byte());
00670       Nf_wr_byte(Usb_read_byte());
00671       Nf_wr_byte(Usb_read_byte());
00672       Nf_wr_byte(Usb_read_byte());
00673       Nf_wr_byte(Usb_read_byte());
00674       Nf_wr_byte(Usb_read_byte());
00675       Nf_wr_byte(Usb_read_byte());
00676       Nf_wr_byte(Usb_read_byte());
00677       Nf_wr_byte(Usb_read_byte());
00678       Nf_wr_byte(Usb_read_byte());
00679       Nf_wr_byte(Usb_read_byte());
00680       Nf_wr_byte(Usb_read_byte());
00681       Nf_wr_byte(Usb_read_byte());
00682       Nf_wr_byte(Usb_read_byte());
00683       Nf_wr_byte(Usb_read_byte());
00684       Nf_wr_byte(Usb_read_byte());
00685       Nf_wr_byte(Usb_read_byte());
00686       Nf_wr_byte(Usb_read_byte());
00687       Nf_wr_byte(Usb_read_byte());
00688       Nf_wr_byte(Usb_read_byte());
00689       Nf_wr_byte(Usb_read_byte());
00690       Nf_wr_byte(Usb_read_byte());
00691       Nf_wr_byte(Usb_read_byte());
00692       Nf_wr_byte(Usb_read_byte());
00693       Nf_wr_byte(Usb_read_byte());
00694       Nf_wr_byte(Usb_read_byte());
00695       Nf_wr_byte(Usb_read_byte());
00696       Nf_wr_byte(Usb_read_byte());
00697       Nf_wr_byte(Usb_read_byte());
00698       Nf_wr_byte(Usb_read_byte());
00699       Nf_wr_byte(Usb_read_byte());
00700       Nf_wr_byte(Usb_read_byte());
00701       Nf_wr_byte(Usb_read_byte());
00702       Nf_wr_byte(Usb_read_byte());
00703       Nf_wr_byte(Usb_read_byte());
00704       Nf_wr_byte(Usb_read_byte());
00705       Nf_wr_byte(Usb_read_byte());
00706       Nf_wr_byte(Usb_read_byte());
00707       Nf_wr_byte(Usb_read_byte());
00708 
00709       Usb_ack_receive_out();           // USB EPOUT read acknowledgement.
00710       Enable_interrupt();              // Global re-enable.
00711    }
00712 }

Here is the caller graph for this function:

void nf_read_sector_to_usb ( U8  nb_sectors  ) 

This function transfers a page content (NF) to the USB macro The number of sectors to be read can be 1 up to 4 (more than 1 is available only for memories with 2kb pages).

Parameters:
nb_sectors number of sectors to be read from NF (1 sector = 512 bytes)
Returns:
none

Definition at line 540 of file nf_mngt.c.

References FALSE, Is_usb_endpoint_enabled, Is_usb_write_enabled, j, Nf_rd_byte, Usb_send_in, and Usb_write_byte.

Referenced by nf_read_10().

00541 {
00542  U8 j;
00543 
00544    for (j = 8*nb_sectors; j != 0; j--)                      // 8 * 64 bytes = 512 bytes
00545    {
00546       Disable_interrupt();
00547 
00548       Usb_write_byte(Nf_rd_byte());                         // read 64 bytes from card
00549       Usb_write_byte(Nf_rd_byte());
00550       Usb_write_byte(Nf_rd_byte());
00551       Usb_write_byte(Nf_rd_byte());
00552       Usb_write_byte(Nf_rd_byte());
00553       Usb_write_byte(Nf_rd_byte());
00554       Usb_write_byte(Nf_rd_byte());
00555       Usb_write_byte(Nf_rd_byte());
00556       Usb_write_byte(Nf_rd_byte());
00557       Usb_write_byte(Nf_rd_byte());
00558       Usb_write_byte(Nf_rd_byte());
00559       Usb_write_byte(Nf_rd_byte());
00560       Usb_write_byte(Nf_rd_byte());
00561       Usb_write_byte(Nf_rd_byte());
00562       Usb_write_byte(Nf_rd_byte());
00563       Usb_write_byte(Nf_rd_byte());
00564       Usb_write_byte(Nf_rd_byte());
00565       Usb_write_byte(Nf_rd_byte());
00566       Usb_write_byte(Nf_rd_byte());
00567       Usb_write_byte(Nf_rd_byte());
00568       Usb_write_byte(Nf_rd_byte());
00569       Usb_write_byte(Nf_rd_byte());
00570       Usb_write_byte(Nf_rd_byte());
00571       Usb_write_byte(Nf_rd_byte());
00572       Usb_write_byte(Nf_rd_byte());
00573       Usb_write_byte(Nf_rd_byte());
00574       Usb_write_byte(Nf_rd_byte());
00575       Usb_write_byte(Nf_rd_byte());
00576       Usb_write_byte(Nf_rd_byte());
00577       Usb_write_byte(Nf_rd_byte());
00578       Usb_write_byte(Nf_rd_byte());
00579       Usb_write_byte(Nf_rd_byte());
00580       Usb_write_byte(Nf_rd_byte());
00581       Usb_write_byte(Nf_rd_byte());
00582       Usb_write_byte(Nf_rd_byte());
00583       Usb_write_byte(Nf_rd_byte());
00584       Usb_write_byte(Nf_rd_byte());
00585       Usb_write_byte(Nf_rd_byte());
00586       Usb_write_byte(Nf_rd_byte());
00587       Usb_write_byte(Nf_rd_byte());
00588       Usb_write_byte(Nf_rd_byte());
00589       Usb_write_byte(Nf_rd_byte());
00590       Usb_write_byte(Nf_rd_byte());
00591       Usb_write_byte(Nf_rd_byte());
00592       Usb_write_byte(Nf_rd_byte());
00593       Usb_write_byte(Nf_rd_byte());
00594       Usb_write_byte(Nf_rd_byte());
00595       Usb_write_byte(Nf_rd_byte());
00596       Usb_write_byte(Nf_rd_byte());
00597       Usb_write_byte(Nf_rd_byte());
00598       Usb_write_byte(Nf_rd_byte());
00599       Usb_write_byte(Nf_rd_byte());
00600       Usb_write_byte(Nf_rd_byte());
00601       Usb_write_byte(Nf_rd_byte());
00602       Usb_write_byte(Nf_rd_byte());
00603       Usb_write_byte(Nf_rd_byte());
00604       Usb_write_byte(Nf_rd_byte());
00605       Usb_write_byte(Nf_rd_byte());
00606       Usb_write_byte(Nf_rd_byte());
00607       Usb_write_byte(Nf_rd_byte());
00608       Usb_write_byte(Nf_rd_byte());
00609       Usb_write_byte(Nf_rd_byte());
00610       Usb_write_byte(Nf_rd_byte());
00611       Usb_write_byte(Nf_rd_byte());
00612       Enable_interrupt();
00613 
00614       Usb_send_in();                            // validate transfer
00615       while(Is_usb_write_enabled()==FALSE)
00616       {
00617          if(!Is_usb_endpoint_enabled())
00618             return; // USB Reset
00619       }
00620    }
00621 }

Here is the caller graph for this function:

void nf_update_spare_zone ( U8  sect_start,
U8  nb_sect 
)

This function updates the spare zone of each page that has been finished to be written.

Parameters:
U8 sect_start (0..3) indicates which sector has started to be written U8 nb_sect (1..4) indicates the number of sectors concerned
<global parameters>="">

Returns:
none

Definition at line 724 of file nf_mngt.c.

References _MEM_TYPE_SLOW_, i, Is_nf_2k, LSB, MSB, NF_RANDOM_DATA_INPUT_CMD, NF_SPARE_POS, NFC_BLK_ID_DATA, NFC_OFST_3_DATA_DST, Nfc_set_adc, Nfc_set_cmd, NFC_SPARE_DATA_VALID, and Nfc_wr_data.

Referenced by nf_ram_2_nf(), and nf_write_10().

00725 {
00726    // Calculate first spare zone address
00727    U8 i;
00728    _MEM_TYPE_SLOW_ U16 byte_addr = NF_SPARE_POS + ((U16)sect_start)*16;
00729 
00730   // Send command + address if 2kb' page model
00731    if (Is_nf_2k())
00732    {
00733       Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
00734       Nfc_set_adc( (byte_addr)%256 );
00735       Nfc_set_adc( (byte_addr)/256 );
00736    }
00737 
00738    // Send data (spare zone x sectors written)
00739    for( i=nb_sect ; i!=0 ; i-- )
00740    {
00741       Nfc_wr_data( 0xFF                 ); // 0- [FW] block is valid (for 2048 compatibility)
00742       Nfc_wr_data( NFC_BLK_ID_DATA      ); // 1- [FW] Free-blocks block
00743       Nfc_wr_data( 0                    ); // 2- [HW] ECC is valid
00744       Nfc_wr_data( NFC_OFST_3_DATA_DST  ); // 3- [SW] Source block (recovery) (HW capability not used)
00745       Nfc_wr_data( NFC_SPARE_DATA_VALID ); // 4- [FW] Data is valid
00746       Nfc_wr_data( 0xFF                 ); // 5- [FW] block is valid (for 512 compatibility)
00747       Nfc_wr_data( MSB(g_log_block_id)  ); // 6- [HW] LBA
00748       Nfc_wr_data( LSB(g_log_block_id)  ); // 7- [HW] LBA
00749       Nfc_wr_data( 0xFF                 ); // 8-9-10- [HW] ECC2
00750       Nfc_wr_data( 0xFF                 );
00751       Nfc_wr_data( 0xFF                 );
00752       Nfc_wr_data( 0xFF                 ); // 11-12-    [HW] LBA
00753       Nfc_wr_data( 0xFF                 );
00754       Nfc_wr_data( 0xFF                 );
00755       Nfc_wr_data( 0xFF                 );
00756       Nfc_wr_data( 0xFF                 ); // 13-14-15- [HW] ECC1
00757    }
00758 }

Here is the caller graph for this function:

Status_bool nf_verify ( void   ) 

Ensure that the memory is in a good state before starting to use it.

Parameters:
none 
Returns:
a status: PASS if the command has been succesfully executed; FAIL else

Definition at line 202 of file nf_mngt.c.

Referenced by nf_read_capacity(), and nf_test_unit_ready().

00203 {
00204    if ( g_nf_init ) return PASS;
00205 
00206    return nf_verify_resume();
00207 }

Here is the caller graph for this function:

Ctrl_status nf_test_unit_ready ( void   ) 

Initializes the NF driver on the first USB Test Unit Ready.

Parameters:
none 
Returns:
CTRL_GOOD if ok, CTRL_NO_PRESENT in case of problems.

Definition at line 218 of file nf_mngt.c.

Referenced by main().

00219 {
00220   Status_bool tmp_bool;
00221 
00222 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00223    nf_XMCR_enable();
00224 #endif
00225 
00226    tmp_bool = nf_verify();
00227 
00228 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00229    nf_XMCR_disable();
00230 #endif
00231 
00232    return ( tmp_bool==PASS ) ? CTRL_GOOD : CTRL_FAIL;
00233 }

Here is the caller graph for this function:

Ctrl_status nf_read_capacity ( U32 u32_nb_sector  ) 

Returns the address of the last valid logical sector.

Parameters:
none 
Returns:
CTRL_GOOD if ok, CTRL_NO_PRESENT in case of problems.

Definition at line 243 of file nf_mngt.c.

00244 {
00245   Status_bool status_bool;
00246 
00247 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00248    nf_XMCR_enable();
00249 #endif
00250 
00251    status_bool = nf_verify();
00252 
00253 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00254    nf_XMCR_disable();
00255 #endif
00256 
00257    *u32_nb_sector = nf_get_sectors_number()-1;
00258    return ( status_bool==PASS ) ? CTRL_GOOD : CTRL_FAIL;
00259 }

Bool nf_wr_protect ( void   ) 

Definition at line 262 of file nf_mngt.c.

00263 {
00264     return FALSE;
00265 }

Bool nf_removal ( void   ) 

Definition at line 267 of file nf_mngt.c.

00268 {
00269     return TRUE;
00270 }

U32 nf_get_sectors_number ( void   ) 

Returns a pointer on the internal buffer address.

This function is used for test only.

Parameters:
none 
Returns:
pointer on an internal buffer of 2112 bytes. 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.

Parameters:
none 
Returns:
Number of sectors.

Definition at line 296 of file nf_mngt.c.

Referenced by nf_read_10(), nf_read_capacity(), and nf_write_10().

00297 {
00298    return
00299       (U32)g_n_export_blocks
00300    << (G_SHIFT_BLOCK_PAGE +G_SHIFT_PAGE_BYTE -S_SHIFT_SECTOR_BYTE)
00301    ;
00302 }

Here is the caller graph for this function:

U32 nf_block_2_page ( U16  block_addr  ) 

Definition at line 306 of file nf_mngt.c.

Referenced by nf_cache_fbb_flush(), nf_cache_fbb_refill(), nf_cache_lut_flush(), nf_cache_lut_refill(), nf_check_fbb(), nf_check_lut(), nf_cleanup_memory(), nf_copy_tail(), nf_erase_all_blocks(), nf_erase_old_blocks(), nf_fetch_free_block(), nf_open_write(), nf_rebuild(), nf_refine_index(), nf_scan(), nf_translate(), nf_write_fbb(), and nf_write_lut().

00307 {
00308    return (U32)block_addr<<G_SHIFT_BLOCK_PAGE;
00309 }

Here is the caller graph for this function:

Ctrl_status nf_read_10 ( U32  log_sector,
U16  n_sectors 
)

This function initializes the Nand Flash for a read operation.

Parameters:
log_sector Logical sector address to start read
nb_sector Number of sectors to transfer
Returns:
CTRL_GOOD if ok, CTRL_FAIL if read outside memory

Definition at line 320 of file nf_mngt.c.

00321 {
00322   U8  status;
00323   
00324    if ( !g_nf_init )
00325       while(1);   // You shall call once mem_test_unit_ready() before.
00326 
00327    // Test that the logical sector address is valid
00328    //
00329    if ( 0==n_sectors )                                   { return CTRL_GOOD; }
00330    if ( (log_sector+n_sectors)>nf_get_sectors_number() ) { return CTRL_FAIL; }
00331 
00332 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00333    nf_XMCR_enable();
00334 #endif
00335 
00336    s_n_sectors       = n_sectors;
00337    s_curr_log_sector = log_sector;
00338    trace("rd;"); trace_hex32(s_curr_log_sector); trace(";"); trace_hex16(s_n_sectors); trace_nl();
00339    s_save_log_addr   = log_sector + n_sectors;
00340    g_fatal           = FALSE;
00341    s_mem             = TRUE;
00342    s_start           = TRUE;
00343 
00344    // First read operation
00345    Nf_access_signal_on();
00346    nf_open_read(TRUE);
00347    Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);
00348    nfc_open_page_read( g_phys_page_addr[g_curr_dev_id], s_curr_n_byte );
00349    nf_read_sector_to_usb(s_nb_sectors_step);
00350    status = nf_xfer_update_vars();
00351 
00352    // Next read operations
00353    while (status == FALSE)    // exit when last page read
00354    {
00355       if (!(LSB0(g_next_phys_page_addr) & (SIZE_BLOCK_PAGE-1))    // new block
00356       && (g_curr_dev_id==0                                  ))    // on device 0. Should this case be implicit ? If yes, we can remove it.
00357       {
00358          nf_open_read(FALSE);
00359       }
00360       Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);
00361       Nfc_open_page_read( g_next_phys_page_addr, s_curr_n_byte ); // Use macro for fast execution
00362       nf_read_sector_to_usb(s_nb_sectors_step);                   // read the concerned sectors of the selected page
00363       status = nf_xfer_update_vars();                             // check if last page or not
00364    }
00365 
00366    Nf_access_signal_off();
00367 
00368 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00369    nf_XMCR_disable();
00370 #endif
00371 
00372    return CTRL_GOOD;
00373 }

Ctrl_status nf_write_10 ( U32  log_sector,
U16  n_sectors 
)

This function initializes the Nand Flash for a write operation.

Parameters:
log_sector Logical sector address to start read
nb_sector Number of sectors to transfer
Returns:
CTRL_GOOD if ok, CTRL_FAIL if read outside memory

Definition at line 384 of file nf_mngt.c.

00385 {
00386   U8 status;
00387   Ctrl_status tmp_bool;
00388 
00389    // Test that the logical sector address is valid
00390    if ( 0==n_sectors )                                   { return CTRL_GOOD; }
00391    if ( (log_sector+n_sectors)>nf_get_sectors_number() ) { return CTRL_FAIL; }
00392 
00393 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00394    nf_XMCR_enable();
00395 #endif
00396 
00397    s_n_sectors       = n_sectors;
00398    s_curr_log_sector = log_sector;
00399    s_save_log_addr   = log_sector + n_sectors;
00400    g_fatal           = FALSE;
00401    s_mem             = TRUE;
00402    s_start           = TRUE;
00403 
00404    trace("wr;"); trace_hex32(s_curr_log_sector); trace(";"); trace_hex16(s_n_sectors); trace_nl();
00405    
00406    // First write operation
00407    Nf_access_signal_on();
00408    if(( s_curr_log_sector==g_last_log_sector )                                           // New write is just after to the last write
00409    && (!(  ( 0==((U16)g_last_log_sector & ( ((U16)1<<(S_SHIFT_LOG_BLOCK_SECTOR)) -1)))   // Not on a logical block boundary
00410       && ( g_curr_dev_id==0                                                        ))))
00411    {
00412       trace("continue");trace_nl();
00413       nf_translate( NF_TRANS_NORMAL );
00414       Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);  // open the current device
00415       nfc_open_page_write( g_next_phys_page_addr, s_curr_n_byte );
00416    }
00417    else
00418    {      
00419       nf_open_write( TRUE );
00420    }
00421    nf_write_sector_from_usb(s_nb_sectors_step);    // s_nb_sectors_step has been calculated in nf_translate()
00422    if (Is_nf_2k())
00423    {
00424       nf_update_spare_zone((U8)(1<<(G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE))-s_nb_sectors_step, s_nb_sectors_step);    // update the spare zone once the page has been filled in
00425    }
00426    else
00427    {
00428      nf_update_spare_zone(0, 1);    // update the spare zone once the page has been filled in
00429    }
00430    g_last_log_sector  = s_curr_log_sector + s_nb_sectors_step;    // Memorize next logical sector to be managed
00431    status = nf_xfer_update_vars();
00432 
00433    // Next write operations
00434    while (status == FALSE)    // exit when operation finished
00435    {
00436       if(!(LSB0(g_next_phys_page_addr) & (SIZE_BLOCK_PAGE-1))  // new block
00437       && (g_curr_dev_id==0                                  )) // on device 0.
00438       {
00439          Nfc_set_cmd(NF_PAGE_PROGRAM_CMD); // Program the page
00440          nf_erase_old_blocks();
00441          nf_open_write( FALSE );
00442       }
00443       else
00444       {
00445          if( G_CACHE_PROG )
00446          {
00447             Nfc_set_cmd(NF_CACHE_PROGRAM_CMD);
00448          }else{
00449             Nfc_set_cmd(NF_PAGE_PROGRAM_CMD);
00450          }
00451          Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);
00452          Nfc_open_page_write( g_next_phys_page_addr, s_curr_n_byte ); // Use macro for fast execution
00453       }
00454       nf_write_sector_from_usb(s_nb_sectors_step);
00455       if (Is_nf_2k())
00456       {
00457          nf_update_spare_zone(0, s_nb_sectors_step);
00458       }
00459       else
00460       {
00461          nf_update_spare_zone(0, 1);    // update the spare zone once the page has been filled in
00462       }
00463       g_last_log_sector  = s_curr_log_sector + s_nb_sectors_step;    // Memorize next logical sector to be managed
00464       status = nf_xfer_update_vars();  // check if last block or not
00465    }
00466 
00467    tmp_bool = nf_dfc_write_stop(0);   // ends write operations with "nf_dfc_write_stop(0)" that save the current environnement
00468    Nf_access_signal_off();
00469 
00470 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00471    nf_XMCR_disable();
00472 #endif
00473 
00474    return tmp_bool;
00475 }

Ctrl_status nf_dfc_write_stop ( U16  u16_nb_sector_remaining  ) 

This function must be called when a write10 operation (from USB) is finished Last page written is programmed and environment is saved.

Parameters:
log_sector Logical sector address to start read
nb_sector Number of sectors to transfer
Returns:
CTRL_GOOD if ok, CTRL_FAIL if read outside memory

Definition at line 770 of file nf_mngt.c.

Referenced by nf_ram_2_nf(), and nf_write_10().

00771 {
00772    Nfc_set_cmd(NF_PAGE_PROGRAM_CMD); // Program the page
00773    // Note that if the page is not completely filled in yet but still programmed, the next copy tail will allow partial page program
00774 
00775    // retreive exact logical/physical position (in case that transfer
00776    // did not perform the exact number of sectors)
00777    s_curr_log_sector = s_save_log_addr - u16_nb_sector_remaining;
00778    if( 0!=u16_nb_sector_remaining )
00779    {
00780       nf_translate( NF_TRANS_NORMAL );
00781    }
00782    g_last_log_sector  = s_curr_log_sector; // Memorize next logical sector to be managed
00783 
00784    // Test if transfer stop at end of logical blocks.
00785    if( s_n_sectors==0 )
00786    {
00787       if(!(LSB0(g_next_phys_page_addr) & (SIZE_BLOCK_PAGE-1))  // new block
00788       && (g_curr_dev_id==0                                  )) // on device 0.
00789      {
00790          // Delete old blocks
00791          //
00792          nf_erase_old_blocks();
00793       }
00794    }
00795    trace("nf_dfc_write_stop;"); trace_hex32(g_last_log_sector); trace_nl();
00796 
00797    // Ensure that all internal programming are complete, since we are
00798    // using cache programming (WP may be asserted for icons or fonts
00799    // loading). Moreover, on some NFs (ST, Samsung)
00800    // it is necessary to reset the devices after copy-back commands
00801    // If not, strange behaviour may happen: no busy when opening
00802    // a page for reading...
00803    nfc_reset_nands( NF_N_DEVICES ); // Reset all the NF devices
00804 
00805    Nf_check_fbb( FALSE );
00806    Nf_check_lut();
00807 
00808    return CTRL_GOOD;
00809 } // end of nf_dfc_write_stop

Here is the caller graph for this function:

void nf_cache_fbb_refill ( void   ) 

Reload the FBB cache memory, starting from 0.

The cache is filled with physical blocks.

Parameters:
none 
Returns:
nothing

Definition at line 1049 of file nf_mngt.c.

Referenced by nf_cache_lut_flush(), nf_translate(), and nf_usb_stop().

01050 {
01051    U8  u8_tmp;
01052    U16 byte_addr;
01053    _MEM_TYPE_SLOW_ U32 page_addr;
01054 
01055    Assert(g_cache_fbb.ctrl.dirty==FALSE); // No refill if the cache is dirty
01056    g_cache_fbb.p   = 0;
01057 
01058    trace("nf_cache_fbb_refill;"); trace_hex16(g_fbb_block_addr);trace_nl();
01059 
01060    // Ensure that the cache is bigger than the real number of free blocks
01061    //
01062    g_cache_fbb.max = Min(NF_CACHE_FBB_LOG_SZ, (g_n_free_blocks>>NF_SHIFT_N_DEVICES) ); // Last included
01063 
01064    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01065 
01066    page_addr =
01067       nf_block_2_page( g_fbb_block_addr  ) // base address
01068    +  (U32)g_fbb_block_index               // offset to Free-blocks block entry
01069    ;
01070    byte_addr=0;
01071 
01072    nfc_open_page_read(page_addr, 0);
01073 
01074    for ( u8_tmp=0 ; u8_tmp<g_cache_fbb.max*NF_N_DEVICES ; u8_tmp++ )
01075    { // fill the cache buffer
01076       Assert( u8_tmp<CACHE_FBB_SIZE);
01077       MSB(g_cache_fbb.mem[u8_tmp]) = Nfc_rd_data_fetch_next();
01078       LSB(g_cache_fbb.mem[u8_tmp]) = Nfc_rd_data_fetch_next();
01079       Assert( g_cache_fbb.mem[u8_tmp]>=g_nf_first_block );
01080       Assert( g_cache_fbb.mem[u8_tmp]< G_N_BLOCKS       );
01081       byte_addr+=2;
01082       Assert( byte_addr<SIZE_PAGE_BYTE); // Should stay in the page. Algo limitation.
01083    }
01084    g_cache_fbb.ctrl.valid = TRUE;
01085 } // end of nf_cache_fbb_refill

Here is the caller graph for this function:

Status_bool nf_write_lut ( U8  pos,
U8  i_sub_lut,
U16  sub_lut_log_sz 
)

Writes a LUT in memory from a buffer.

Parameters:
pos offset of the lub-lut in the buffer
i_sub_lut id of the sub-LUT
sub_lut_log_sz Size of the sub-LUT, in logical block unit
Returns:
nothing

Definition at line 1213 of file nf_mngt.c.

Referenced by nf_cache_lut_flush(), and nf_rebuild().

01217 {
01218    U16  block_addr; // Physical block number
01219    U8 _MEM_TYPE_SLOW_ * p_buf=g_page_buffer + (U16)pos*((U16)1<<(G_SHIFT_PAGE_BYTE));
01220 
01221    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01222    // The buffer is built as:
01223    // |    512    |    512    |    512    |    512    |
01224    //
01225    // The page is built as:
01226    // |    512    |    512    |    512    |    512    |SZ|
01227    //
01228    // The LUT fits in a physical page.
01229    //
01230    nfc_open_page_write(
01231       nf_block_2_page( g_lut_block_addr[i_sub_lut] ) // base address
01232    +  (U32)(g_lut_block_index[i_sub_lut])            // offset to sub-LUT
01233    ,  0 );
01234 
01235    trace("nf_write_lut;");trace_hex16(g_lut_block_addr[i_sub_lut]); trace(";"); trace_hex16(g_lut_block_index[i_sub_lut]);trace_nl();
01236    for( block_addr=0 ; block_addr<((U16)1<<(G_SHIFT_PAGE_BYTE-1)) ; block_addr+=1 )
01237    {
01238       if ( block_addr<(sub_lut_log_sz*NF_N_DEVICES) )
01239       {
01240 #if (_ASSERT_==ENABLE)
01241          Assert(           ( block_addr*2)<(NF_PAGE_BUFFER_SIZE-1) );
01242          MSB(_debug)= p_buf[ block_addr*2   ] ;
01243          LSB(_debug)= p_buf[ block_addr*2 +1] ;
01244          Assert( _debug>=g_nf_first_block );
01245          Assert( _debug< G_N_BLOCKS       );
01246 #endif
01247          Nfc_wr_data( p_buf[ block_addr*2   ] );
01248          Nfc_wr_data( p_buf[ block_addr*2 +1] );
01249          trace_hex(p_buf[ block_addr*2   ]);
01250          trace_hex(p_buf[ block_addr*2 +1]);
01251          trace("-");
01252       }
01253       else
01254       {
01255          Nfc_wr_data( 0xFF );
01256          Nfc_wr_data( 0xFF );
01257          trace("FFFF-");
01258       }
01259    }
01260    trace_nl();
01261 
01262    // Write the spare information
01263    //
01264    Nfc_wr_data( 0xFF              );                              // 0- block is valid (for 2048 compatibility)
01265    Nfc_wr_data( NFC_BLK_ID_SUBLUT );                              // 1- sub-LUT
01266    Nfc_wr_data( i_sub_lut         );                              // 2- sub-LUT id
01267    Nfc_wr_data( 0xFF              );                              // 3- unused
01268    Nfc_wr_data( g_n_sub_lut       );                              // 4- number of sub-LUT
01269    Nfc_wr_data( 0xFF              );                              // 5- block is valid (for 512 compatibility)
01270    Nfc_wr_data( MSB(sub_lut_log_sz) );                            // 6-7 Number of log blocks in sub-LUT
01271    Nfc_wr_data( LSB(sub_lut_log_sz) );
01272    Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); // 8-9-10-   ECC2
01273    Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF );                      // 11-12-    LBA
01274    Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); // 13-14-15- ECC1
01275 
01276    Nfc_set_cmd( NF_PAGE_PROGRAM_CMD );
01277    if ( FAIL==nfc_check_status() ) { return FAIL; }
01278 
01279    return PASS;
01280 } // end of nf_write_lut

Here is the caller graph for this function:

void nf_cache_fbb_flush ( Bool  b_ecc_err  ) 

Flushes the FBB cache into a new FBB entry.

A copy of the current FBB is made in a new page, taking into account the last FBB modification in its cache. If the block containing the FBB is full, a new block is taken from the FBB itself.

Parameters:
b_ecc_err FALSE: normal operation, b_ecc_err TRUE: remove a block from list (p)
Returns:
nothing

Definition at line 1295 of file nf_mngt.c.

Referenced by nf_cache_lut_flush(), nf_translate(), and nf_usb_stop().

01296 {
01297    _MEM_TYPE_SLOW_ U32  page_addr;
01298    _MEM_TYPE_SLOW_ U16  byte_addr;
01299    _MEM_TYPE_SLOW_ U16 u16_delete=0;
01300    _MEM_TYPE_SLOW_ U16  u16_tmp;
01301    U8   u8_tmp;
01302    _MEM_TYPE_SLOW_ U8   u8_pos;
01303    Bool bool_delete=FALSE;
01304 
01305    Assert(TRUE==g_cache_fbb.ctrl.valid);
01306    Assert(TRUE==g_cache_fbb.ctrl.dirty);
01307    // Assert(g_cache_fbb.p==(g_cache_fbb.max-1)); This is no more the case for ECC error not correctable
01308 
01309    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01310 
01311    trace("nf_cache_fbb_flush;"); trace_hex16(g_fbb_block_addr);trace_nl();
01312 
01313    page_addr=
01314       nf_block_2_page( g_fbb_block_addr  )  // base address
01315    +  (U32)g_fbb_block_index                // offset to page
01316    ;
01317 
01318    g_fbb_block_index++;
01319 
01320    if ( g_fbb_block_index ==  (1<<G_SHIFT_BLOCK_PAGE)/(1<<0) )
01321    {  // Need to recycle the FBB block itself, using a free-block ! This is always possible
01322       // since there is always a free block (.p=.max-1) specially for that purpose.
01323       byte_addr = ((U16)NF_N_DEVICES*g_cache_fbb.p + S_MNGT_DEV);
01324 
01325       Assert( g_cache_fbb.mem[byte_addr]>=g_nf_first_block );
01326       Assert( g_cache_fbb.mem[byte_addr]< G_N_BLOCKS       );
01327       u16_delete                 = g_fbb_block_addr           ;
01328       g_fbb_block_addr           = g_cache_fbb.mem[byte_addr] ;
01329       g_cache_fbb.mem[byte_addr] = u16_delete;
01330       g_fbb_block_index = 0;
01331 
01332       trace("nf_cache_fbb_flush;swap;"); trace_hex16(g_fbb_block_addr);trace_nl();
01333       
01334       // g_cache_fbb.ctrl.dirty=TRUE; This is already the case !
01335 
01336       g_cache_fbb.p++;
01337       bool_delete=TRUE;
01338    }
01339 
01340    if( !b_ecc_err )  { u8_pos = g_cache_fbb.p;   }
01341    else              { u8_pos = g_cache_fbb.max; }
01342 
01343    byte_addr = ((U16)NF_N_DEVICES*2*u8_pos);
01344 
01345    Assert( byte_addr<SIZE_PAGE_BYTE );
01346 
01347    nfc_open_page_read( page_addr, byte_addr);
01348 
01349    Assert( g_cache_fbb.p<=(g_n_free_blocks/NF_N_DEVICES) );
01350    for (
01351       u16_tmp=0
01352    ;  u16_tmp<((g_n_free_blocks/NF_N_DEVICES)-u8_pos)*NF_N_DEVICES*2
01353    ; )
01354    {  // Move the free-blocks after <pos> to the beginning of the buffer.
01355       Assert( u16_tmp<(NF_PAGE_BUFFER_SIZE-3) );
01356       g_page_buffer[u16_tmp++] = Nfc_rd_data_fetch_next();
01357       g_page_buffer[u16_tmp++] = Nfc_rd_data_fetch_next();
01358 #if (_ASSERT_==ENABLE)
01359       MSB(_debug)= g_page_buffer[u16_tmp-2];
01360       LSB(_debug)= g_page_buffer[u16_tmp-1];
01361       Assert( _debug>=g_nf_first_block );
01362       Assert( _debug< G_N_BLOCKS       );
01363 #endif
01364    }
01365 
01366    for ( u8_tmp=0 ; u8_tmp<(u8_pos*NF_N_DEVICES); u8_tmp++ )
01367    {  // Then add the cache content
01368       Assert( u8_tmp < CACHE_FBB_SIZE );
01369       Assert( u16_tmp< NF_FULL_PAGE_BUFFER_SIZE );
01370 #if (_ASSERT_==ENABLE)
01371       // When coming from ECC 2-bits error, an entry has been removed
01372       // from the cache, so the last entry is 0xffff
01373       if( !b_ecc_err )
01374       {
01375          Assert( g_cache_fbb.mem[u8_tmp]>=g_nf_first_block );
01376          Assert( g_cache_fbb.mem[u8_tmp]< G_N_BLOCKS       );
01377       }
01378 #endif
01379       g_page_buffer[u16_tmp++] = MSB(g_cache_fbb.mem[u8_tmp]);
01380       g_page_buffer[u16_tmp++] = LSB(g_cache_fbb.mem[u8_tmp]);
01381    }
01382 #if (_ASSERT_==ENABLE)
01383    // Ensure that, when there is no fbb recycle, the blocks in the cache at
01384    // position p are identical to the blocks in the beginning of the new line.
01385    if( (FALSE==bool_delete) && ( !b_ecc_err ))
01386    {
01387       for ( u8_tmp=0 ; u8_tmp<NF_N_DEVICES ; u8_tmp++ )
01388       {
01389          MSB(_debug)= g_page_buffer[u8_tmp*2   ];
01390          LSB(_debug)= g_page_buffer[u8_tmp*2 +1];
01391          Assert( _debug==g_cache_fbb.mem[(g_cache_fbb.p)*NF_N_DEVICES + u8_tmp] );
01392       }
01393    }
01394 #endif
01395 
01396    nf_write_fbb(); // Should test the result
01397    Nf_check_fbb( b_ecc_err );
01398    Nf_check_lut();
01399 
01400    if( TRUE==bool_delete )
01401    {
01402       nfc_erase_block( nf_block_2_page( u16_delete ), TRUE );
01403    }
01404 
01405    Assert( u16_tmp==(g_n_free_blocks*2) ); // All the list should have been processed
01406    g_cache_fbb.ctrl.dirty=FALSE;
01407 } // end of nf_cache_fbb_flush

Here is the caller graph for this function:

Status_bool nf_write_fbb ( void   ) 

Writes the Free-blocks block into the Nand Flash.

Parameters:
none 
Returns:
nothing

Definition at line 1417 of file nf_mngt.c.

Referenced by nf_cache_fbb_flush(), and nf_rebuild().

01418 {
01419    U16 u16_tmp;
01420 
01421    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01422    nfc_open_page_write(
01423       nf_block_2_page( g_fbb_block_addr )  // base address
01424    +  (U32)g_fbb_block_index               // offset to Free-blocks block entry
01425    , 0 );
01426    for ( u16_tmp=0 ; u16_tmp<((U16)1<<(G_SHIFT_PAGE_BYTE-1)) ; )
01427    {
01428       if ( u16_tmp<g_n_free_blocks )
01429       {
01430          Nfc_wr_data( g_page_buffer[2*u16_tmp   ] );
01431          Nfc_wr_data( g_page_buffer[2*u16_tmp +1] );
01432       }
01433       else
01434       {
01435          Nfc_wr_data( 0xFF );
01436          Nfc_wr_data( 0xFF );
01437       }
01438       u16_tmp++;
01439    }
01440    // Write the spare information
01441    //
01442    Nfc_wr_data( 0xFF );                                           // 0- block is valid (for 2048 compatibility)
01443    Nfc_wr_data( NFC_BLK_ID_FBB );                                 // 1- Free-blocks block
01444    Nfc_wr_data( MSB(g_n_free_blocks));                            // 2-3 Number of free blocks
01445    Nfc_wr_data( LSB(g_n_free_blocks));
01446    Nfc_wr_data( NFC_OFST_4_FBB_DRIVER_RELEASE );                  // 4- Nand-Flash driver ID
01447    Nfc_wr_data( 0xFF );                                           // 5- block is valid (for 512 compatibility)
01448    Nfc_wr_data( NFC_OFST_6_FBB_VALID );                           // 6- FBB-LUTs valid
01449    Nfc_wr_data( 0xFF );                                           // 7- Unused
01450    Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); // 8-9-10-   Unused
01451    Nfc_wr_data( MSB(g_n_export_blocks));                          // 11-12- Number of exported blocks
01452    Nfc_wr_data( LSB(g_n_export_blocks));
01453    Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); Nfc_wr_data( 0xFF ); // 13-14-15- Unused
01454 
01455    Nfc_set_cmd( NF_PAGE_PROGRAM_CMD );
01456    if ( FAIL==nfc_check_status() ) { return FAIL; }
01457    return PASS;
01458 } // end of nf_write_fbb

Here is the caller graph for this function:

static void nf_check_fbb ( Bool  b_ecc_err  )  [static]

Definition at line 1463 of file nf_mngt.c.

References _debug, Assert, G_N_BLOCKS, LSB, MSB, nf_block_2_page(), NF_N_DEVICES, NFC_ACT_DEV_SELECT, Nfc_action, nfc_open_page_read(), Nfc_rd_data_fetch_next, S_MNGT_DEV, trace(), trace_hex(), trace_hex16(), trace_nl(), and trace_u16().

01464 {
01465    U16 u16_tmp;
01466 
01467    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01468    trace("nf_check_fbb\n\r");
01469    trace("g_fbb_block_addr "); trace_hex16(g_fbb_block_addr);
01470    trace("\n\rs_fbb_block_index= "); trace_hex(g_fbb_block_index); trace("\n\r");
01471    nfc_open_page_read(
01472       nf_block_2_page( g_fbb_block_addr )  // base address
01473    +  (U32)g_fbb_block_index               // offset to Free-blocks block entry
01474    , 0 );
01475    trace("n free blocks: "); trace_u16(g_n_free_blocks); trace_nl();
01476    for ( u16_tmp=0 ; u16_tmp<g_n_free_blocks ; )
01477    {
01478 #if (_TRACE_==ENABLE)
01479       if( u16_tmp>=2048 ) break;
01480       if( !(u16_tmp% 8) ) {
01481          trace("\n\r");
01482          trace_u16(u16_tmp);
01483       }
01484 #endif
01485       MSB(_debug)= Nfc_rd_data_fetch_next();
01486       LSB(_debug)= Nfc_rd_data_fetch_next();
01487       trace(" 0x"); trace_hex( MSB(_debug) ); trace_hex( LSB(_debug) );
01488       // When coming from ECC 2-bits error, an entry has been removed
01489       // from the cache, so the last entry is 0xffff
01490       if( !b_ecc_err )
01491       {
01492          Assert( _debug>=g_nf_first_block );
01493          Assert( _debug< G_N_BLOCKS       );
01494       }
01495 #if 0
01496       This tests have been commented out: when the cache are dirty, we can not just check the memory
01497       with possible protected block address (fbb, lut).
01498       Ex: FBB is dirty, a recycle have been done between on of the free block and g_lut_block_addr[x].
01499       In the FBB memory, the (new) lut address is still present, even if it is not the case in the cache.
01500       if ( (u16_tmp%NF_N_DEVICES)==S_MNGT_DEV )
01501       { // Check dangerous address collision for NF_MNGT only
01502          Assert( _debug!=g_fbb_block_addr );
01503          for ( u8_tmp=0 ; u8_tmp<g_n_sub_lut ; u8_tmp++ ) {
01504             Assert( _debug!=g_lut_block_addr[u8_tmp] );
01505          }
01506       }
01507 #endif
01508       u16_tmp++;
01509    }
01510    trace_nl();
01511 } // nf_check_fbb

Here is the call graph for this function:

static void nf_check_lut ( void   )  [static]

Definition at line 1514 of file nf_mngt.c.

References _debug, Assert, G_N_BLOCKS, LSB, MSB, nf_block_2_page(), NF_N_DEVICES, NFC_ACT_DEV_SELECT, Nfc_action, nfc_open_page_read(), Nfc_rd_data_fetch_next, and S_MNGT_DEV.

01515 {
01516    U16 u16_tmp;
01517    U8  sub_lut_id;
01518    U16 sub_lut_log_sz;
01519 
01520    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
01521    for ( sub_lut_id=0 ; sub_lut_id<g_n_sub_lut ; sub_lut_id++ )
01522    {
01523       nfc_open_page_read(
01524          nf_block_2_page( g_lut_block_addr[sub_lut_id] ) // base address
01525       +  (U32)g_lut_block_index[sub_lut_id]              // offset to LUT block entry
01526       , 0 );
01527 
01528       sub_lut_log_sz = ( sub_lut_id==(g_n_sub_lut-1) ) ? g_last_sub_lut_log_sz : g_sub_lut_log_sz ;
01529       for ( u16_tmp=0 ; u16_tmp<(sub_lut_log_sz*NF_N_DEVICES) ; )
01530       {
01531          MSB(_debug)= Nfc_rd_data_fetch_next();
01532          LSB(_debug)= Nfc_rd_data_fetch_next();
01533          Assert( _debug>=g_nf_first_block );
01534          Assert( _debug< G_N_BLOCKS       );
01535 #if 0
01536          if ( (u16_tmp%NF_N_DEVICES)==S_MNGT_DEV )
01537          { // Check dangerous address collision for NF_MNGT only
01538             Assert( _debug!=g_fbb_block_addr );
01539             for ( u8_tmp=0 ; u8_tmp<g_n_sub_lut ; u8_tmp++ ) {
01540                Assert( _debug!=g_lut_block_addr[u8_tmp] );
01541             }
01542          }
01543 #endif
01544          u16_tmp++;
01545       }
01546    }
01547 }

Here is the call graph for this function:

void nf_copy_tail ( void   ) 

Definition at line 1558 of file nf_mngt.c.

Referenced by nf_open_read(), nf_open_write(), nf_rebuild(), and nf_usb_stop().

01559 {
01560    _MEM_TYPE_SLOW_ U8  u8_tmp;
01561                    U8  u8_tmp2;
01562    _MEM_TYPE_SLOW_ U16 u16_tmp;
01563    _MEM_TYPE_SLOW_ U16 byte_addr;
01564 
01565    // Test if we do not reach the end of the logical block
01566    //
01567    if( 0!=((U16)g_last_log_sector & ( ((U16)1<<(S_SHIFT_LOG_BLOCK_SECTOR)) -1)) )
01568    {
01569       trace("nf_copy_tail;"); trace_hex32(g_last_log_sector); trace_nl();
01570       if( Is_not_nf_512() )
01571       {  // Following is not possible on 512B Nand
01572 
01573          u8_tmp = // current offset sector in the current page
01574             LSB0(g_last_log_sector)
01575          &  ( SIZE_PAGE_SECTOR-1 )
01576          ;
01577 
01578          u8_tmp2 = SIZE_PAGE_SECTOR -u8_tmp;
01579          if( 0!=u8_tmp )
01580          {  // Copy the rest of the current line
01581 
01582             byte_addr=((U16)u8_tmp) * (SIZE_SECTOR_BYTE);
01583             Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);  // open the current device
01584             nfc_open_page_read(                                                       // Open the old block at :
01585                   nf_block_2_page( g_block_to_kill[g_curr_dev_id] )                   // adresse of the beginning of the old block
01586                +  (LSB0(g_phys_page_addr[g_curr_dev_id])&(SIZE_BLOCK_PAGE -1))        // current offset page in the old and new block
01587             ,  byte_addr );                                                           // current offset sector in the current page
01588             // for each sector in the physical page
01589             u16_tmp = u8_tmp2 * SIZE_SECTOR_BYTE;
01590             g_last_log_sector += u8_tmp2;                                             // update the current logical sector
01591 
01592             // read the sector of the old page
01593             nf_upload(g_page_buffer+byte_addr, u16_tmp/16 );
01594 
01595             // Read the associated spare zone
01596             byte_addr= NF_SPARE_POS + (((U16)u8_tmp)*16);
01597             nfc_open_page_read(                                                       // Open the old block at :
01598                   nf_block_2_page( g_block_to_kill[g_curr_dev_id] )                   // adresse of the beginning of the old block
01599                +  (LSB0(g_phys_page_addr[g_curr_dev_id])&(SIZE_BLOCK_PAGE -1))        // current offset page in the old and new block
01600             ,  byte_addr );                                                           // current offset sector in the current page
01601             nf_upload(g_page_buffer+byte_addr, u8_tmp2 );
01602 
01603             byte_addr=((U16)u8_tmp) * (SIZE_SECTOR_BYTE);
01604             nfc_open_page_write( // Open the new block at the current position
01605                g_phys_page_addr[g_curr_dev_id]
01606             ,  byte_addr );
01607 
01608             // write the sector in the new page
01609             nf_download(g_page_buffer+byte_addr, (U8)(u16_tmp/16) );
01610 
01611             // write the associated spare zone
01612             byte_addr=NF_SPARE_POS + (((U16)u8_tmp)*16);
01613             Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01614             Nfc_set_adc( (byte_addr)%256 );
01615             Nfc_set_adc( (byte_addr)/256 );
01616             nf_download(g_page_buffer+byte_addr, u8_tmp2 );
01617             Nfc_set_cmd(NF_PAGE_PROGRAM_CMD);
01618 
01619             g_phys_page_addr[g_curr_dev_id]++;                                                   // update the current physical page of the current device
01620             g_curr_dev_id++;                                                                     // update the current device
01621             if( g_curr_dev_id==NF_N_DEVICES ) { g_curr_dev_id=0; }
01622          }
01623       }
01624 
01625       // then copy the rest of the logical block
01626       //
01627       while( 0!=((U16)g_last_log_sector & (((U16)1<<(S_SHIFT_LOG_BLOCK_SECTOR))-1)) )
01628       {
01629          Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);  // open the current device
01630 
01631          g_copy_src=
01632             nf_block_2_page(g_block_to_kill[g_curr_dev_id])                     // adresse of the beginning of the old block
01633          +  (LSB0(g_phys_page_addr[g_curr_dev_id])&(SIZE_BLOCK_PAGE -1))        // current offset page in the old and new block
01634          ;
01635          nf_copy(g_phys_page_addr[g_curr_dev_id]);
01636          g_phys_page_addr[g_curr_dev_id]++;
01637 
01638          g_last_log_sector+=SIZE_PAGE_SECTOR;                            // update the current logical sector
01639          g_curr_dev_id++;                                                          // update the current device
01640          if( g_curr_dev_id==NF_N_DEVICES ) { g_curr_dev_id=0; }
01641       }
01642 
01643       // Delete old blocks
01644       //
01645       nf_erase_old_blocks();
01646    }else{
01647       trace("nf_copy_tail empty??;"); trace_hex32(g_last_log_sector); trace_nl();
01648    }
01649    g_last_log_sector= 0xFFFFFFFF;
01650 }

Here is the caller graph for this function:

void nf_download ( U8 _MEM_TYPE_SLOW_ *  datbuf,
U8  loop 
)

Download packets of 16 bytes from RAM to the NAND Flash.

Parameters:
U8 * datbuf pointer to RAM U8 loop number of 16 bytes packets
<global parameters>="">

Returns:
none

Definition at line 1663 of file nf_mngt.c.

Referenced by nf_copy(), nf_copy_tail(), and nf_open_write().

01664 {
01665   U8 _MEM_TYPE_SLOW_ * tempbuf = datbuf;
01666   U8 i = loop;
01667 
01668   while (i != 0)
01669   {
01670      Nf_wr_byte(*(tempbuf)); tempbuf++;
01671      Nf_wr_byte(*(tempbuf)); tempbuf++;
01672      Nf_wr_byte(*(tempbuf)); tempbuf++;
01673      Nf_wr_byte(*(tempbuf)); tempbuf++;
01674      Nf_wr_byte(*(tempbuf)); tempbuf++;
01675      Nf_wr_byte(*(tempbuf)); tempbuf++;
01676      Nf_wr_byte(*(tempbuf)); tempbuf++;
01677      Nf_wr_byte(*(tempbuf)); tempbuf++;
01678      Nf_wr_byte(*(tempbuf)); tempbuf++;
01679      Nf_wr_byte(*(tempbuf)); tempbuf++;
01680      Nf_wr_byte(*(tempbuf)); tempbuf++;
01681      Nf_wr_byte(*(tempbuf)); tempbuf++;
01682      Nf_wr_byte(*(tempbuf)); tempbuf++;
01683      Nf_wr_byte(*(tempbuf)); tempbuf++;
01684      Nf_wr_byte(*(tempbuf)); tempbuf++;
01685      Nf_wr_byte(*(tempbuf)); tempbuf++;
01686      i--;
01687   }
01688 }

Here is the caller graph for this function:

void nf_upload ( U8 _MEM_TYPE_SLOW_ *  datbuf,
U8  loop 
)

Upload packets of 16 bytes from the NAND Flash to RAM.

Parameters:
U8 * datbuf pointer to RAM U8 loop number of 16 bytes packets
Returns:
none

Definition at line 1699 of file nf_mngt.c.

Referenced by nf_copy(), nf_copy_tail(), and nf_open_write().

01700 {
01701   U8 _MEM_TYPE_SLOW_ * tempbuf = datbuf;
01702   U8 i = loop;
01703 
01704   while (i != 0)
01705   {
01706      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01707      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01708      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01709      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01710      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01711      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01712      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01713      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01714      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01715      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01716      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01717      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01718      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01719      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01720      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01721      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01722      i--;
01723   }
01724 }

Here is the caller graph for this function:

void nf_copy ( U32  copy_dst  ) 

Copy a NF page to a new one.

This function copies a NF page into a new page. It uses the copy-back command if it is possible.

Parameters:
g_copy_src (global) Source page address
copy_dst Recipient page address

Definition at line 1859 of file nf_mngt.c.

Referenced by nf_copy_tail(), and nf_open_write().

01860 {
01861    Bool b_copy_fast;
01862    U8   zone_A, zone_B;
01863 
01864    // Compute the possibility of fast copy
01865    if( 0 == G_COPY_BACK_CONT )
01866    {
01867       b_copy_fast = 0;     // never possible
01868    }
01869    else
01870    {
01871       if( (1 == G_COPY_BACK_CONT) && (1==G_COPY_BACK_DISCONT) )
01872       {
01873          b_copy_fast = 1;  // always possible
01874       }
01875       else
01876       {
01877          // Check block address
01878          b_copy_fast = 1;  // by default possible
01879          if( 1 != G_COPY_BACK_CONT )
01880          {
01881 /*
01882             zone_A = (g_copy_src>>G_SHIFT_BLOCK_PAGE) / ((U16)G_N_BLOCKS/G_COPY_BACK_CONT);
01883             zone_B = (copy_dst  >>G_SHIFT_BLOCK_PAGE) / ((U16)G_N_BLOCKS/G_COPY_BACK_CONT);
01884 */
01885             // block_zone = page add / number of page / 1024
01886             if( Is_nf_2k() )
01887             {
01888                // block_zone = (page add >> (G_SHIFT_BLOCK_PAGE + 10)) / (G_N_ZONES/G_COPY_BACK_CONT);
01889                // block_zone = ((page add >> 16) * G_COPY_BACK_CONT) / G_N_ZONES;
01890                zone_A = (MSB1(g_copy_src)*G_COPY_BACK_CONT)/G_N_ZONES;
01891                zone_B = (MSB1(copy_dst  )*G_COPY_BACK_CONT)/G_N_ZONES;
01892             }else{
01893                // block_zone = page add >> (G_SHIFT_BLOCK_PAGE + 10) / (G_N_ZONES/G_COPY_BACK_CONT);
01894                zone_A = ((U8)(g_copy_src>>(G_SHIFT_BLOCK_PAGE + 10)) *G_COPY_BACK_CONT) /G_N_ZONES;
01895                zone_B = ((U8)(copy_dst  >>(G_SHIFT_BLOCK_PAGE + 10)) *G_COPY_BACK_CONT) /G_N_ZONES;
01896             }
01897             if( zone_A != zone_B )
01898                b_copy_fast = 0;     // no possible
01899          }
01900          if( 1 != G_COPY_BACK_DISCONT )
01901          {
01902 // define mandatory to delete compile error on MODULO 0
01903 #if (NF_GENERIC_DRIVER==TRUE) || (NF_AUTO_DETECT_2KB==TRUE) || (NF_AUTO_DETECT_512B==TRUE)
01904             zone_A = ((U16)g_copy_src>>G_SHIFT_BLOCK_PAGE) % G_COPY_BACK_DISCONT;
01905             zone_B = ((U16)copy_dst  >>G_SHIFT_BLOCK_PAGE) % G_COPY_BACK_DISCONT;
01906 #elif ( G_COPY_BACK_DISCONT != 0 )
01907             zone_A = ((U16)g_copy_src>>G_SHIFT_BLOCK_PAGE) % G_COPY_BACK_DISCONT;
01908             zone_B = ((U16)copy_dst  >>G_SHIFT_BLOCK_PAGE) % G_COPY_BACK_DISCONT;
01909 #endif
01910             if( zone_A != zone_B )
01911                b_copy_fast = 0;     // no possible
01912          }
01913       }
01914    }
01915       
01916    // Start copy
01917    if( !b_copy_fast )
01918    {
01919       // copy the page of the old block in buffer
01920       nfc_open_page_read( g_copy_src, 0 );
01921       nf_upload(                                // Works by packet of 16 bytes
01922          g_page_buffer
01923       ,     ((U16)1<<(G_SHIFT_PAGE_BYTE-4))     // Data zone (Page size / 16)
01924          +  ((U16)1<<(G_SHIFT_PAGE_BYTE-5-4))); // Spare zone (Page size / 32 / 16)
01925 
01926       // Add LBA markers to help recovery function
01927       // Need to explain a bit why LBA are written: 
01928       // nf_copy is called from copy_head and copy_tail.
01929       // - copy_head: need to write all the LBA of the pages to help recovery finding
01930       //   where the last sector is written.
01931       //   Moreover, in case that nf_copy is called from copy_head and source block at page 0
01932       //   does not contain LBA.
01933       // - copy_tail: no need to mark the last LBA of the last page to identify the source
01934       //   block since we use another method
01935       g_page_buffer[NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3] = NFC_OFST_3_DATA_DST;  // 3- [SW] Source block (recovery) (HW capability not used)
01936       g_page_buffer[NF_SPARE_POS+NFC_SPARE_OFST_6_LBA   ] = MSB(g_log_block_id);  // 6- LBA
01937       g_page_buffer[NF_SPARE_POS+NFC_SPARE_OFST_6_LBA+1 ] = LSB(g_log_block_id);  // 7- LBA
01938       if( Is_nf_2k() )
01939       {
01940          g_page_buffer[NF_SPARE_POS +16*1 +NFC_SPARE_OFST_6_LBA  ] =
01941          g_page_buffer[NF_SPARE_POS +16*2 +NFC_SPARE_OFST_6_LBA  ] =
01942          g_page_buffer[NF_SPARE_POS +16*3 +NFC_SPARE_OFST_6_LBA  ] = MSB(g_log_block_id);  // 6- LBA
01943          g_page_buffer[NF_SPARE_POS +16*1 +NFC_SPARE_OFST_6_LBA+1] =
01944          g_page_buffer[NF_SPARE_POS +16*2 +NFC_SPARE_OFST_6_LBA+1] =
01945          g_page_buffer[NF_SPARE_POS +16*3 +NFC_SPARE_OFST_6_LBA+1] = LSB(g_log_block_id);  // 7- LBA
01946       }
01947 
01948       // copy the buffer in the page of the new block
01949       nfc_open_page_write( copy_dst, 0 );
01950       nf_download(                                // Works by packet of 16 bytes
01951          g_page_buffer
01952       ,     ((U16)1<<(G_SHIFT_PAGE_BYTE-4))       // Data zone (Page size / 16)
01953          +  ((U16)1<<(G_SHIFT_PAGE_BYTE-5-4)));  // Spare zone (Page size / 32 / 16)
01954       Nfc_set_cmd(NF_PAGE_PROGRAM_CMD);
01955    }
01956    else
01957    {
01958       nfc_copy_back_init( g_copy_src );
01959 
01960       Nfc_unprotect_all_flash();                              // WP may be actif due to block protection
01961       Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01962       Nfc_set_adc( (NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3)%256 );
01963       Nfc_set_adc( (NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3)/256 );
01964       Nfc_set_adr( LSB0(copy_dst) );
01965       Nfc_set_adr( LSB1(copy_dst) );
01966       if ( 3==G_N_ROW_CYCLES )
01967       {
01968          Nfc_set_adr( MSB1(copy_dst) );
01969       }
01970 
01971       // Remove Source block mask
01972       Nfc_wr_data( NFC_OFST_3_DATA_DST );
01973 
01974       // Add LBA markers to help recovery function
01975       Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01976       Nfc_set_adc( (NF_SPARE_POS+NFC_SPARE_OFST_6_LBA)%256 );
01977       Nfc_set_adc( (NF_SPARE_POS+NFC_SPARE_OFST_6_LBA)/256 );
01978       Nfc_wr_data( MSB(g_log_block_id) );
01979       Nfc_wr_data( LSB(g_log_block_id) );
01980 
01981       if( Is_nf_2k() )
01982       {
01983          Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01984          Nfc_set_adc( (NF_SPARE_POS + 16*1 +NFC_SPARE_OFST_6_LBA)%256 );
01985          Nfc_set_adc( (NF_SPARE_POS + 16*1 +NFC_SPARE_OFST_6_LBA)/256 );
01986          Nfc_wr_data( MSB(g_log_block_id) );
01987          Nfc_wr_data( LSB(g_log_block_id) );
01988 
01989          Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01990          Nfc_set_adc( (NF_SPARE_POS + 16*2 +NFC_SPARE_OFST_6_LBA)%256 );
01991          Nfc_set_adc( (NF_SPARE_POS + 16*2 +NFC_SPARE_OFST_6_LBA)/256 );
01992          Nfc_wr_data( MSB(g_log_block_id) );
01993          Nfc_wr_data( LSB(g_log_block_id) );
01994 
01995          Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
01996          Nfc_set_adc( (NF_SPARE_POS + 16*3 +NFC_SPARE_OFST_6_LBA)%256 );
01997          Nfc_set_adc( (NF_SPARE_POS + 16*3 +NFC_SPARE_OFST_6_LBA)/256 );
01998          Nfc_wr_data( MSB(g_log_block_id) );
01999          Nfc_wr_data( LSB(g_log_block_id) );
02000       }
02001       Nfc_set_cmd(NF_PAGE_PROGRAM_CMD);
02002    }
02003 }

Here is the caller graph for this function:

void nf_swap ( U8  dev_id,
U8  u8_ofst_lut,
U8  u8_ofst_fbb 
)

Swap 2 blocks from the LUT and the FBB.

This function swaps 2 blocks: one taken into the LUT according to the LBA, and one from the FBB. This is used when modifying a block. The g_block_to_kill[] holds the block address source (LUT) that will be erased after processing.

Parameters:
dev_id Device Id of recipient page
u8_ofst_lut block offset in LUT
u8_ofst_fbb block offset in FBB
Returns:
none

Definition at line 2021 of file nf_mngt.c.

Referenced by nf_translate().

02022 {
02023    Assert( dev_id      < NF_N_DEVICES  );
02024    Assert( u8_ofst_lut < CACHE_LUT_SIZE);
02025    Assert( u8_ofst_fbb < CACHE_FBB_SIZE);
02026    Assert( g_cache_lut.mem[u8_ofst_lut]  >=g_nf_first_block );
02027    Assert( g_cache_lut.mem[u8_ofst_lut]  < G_N_BLOCKS       );
02028    Assert( g_cache_fbb.mem[u8_ofst_fbb]  >=g_nf_first_block );
02029    Assert( g_cache_fbb.mem[u8_ofst_fbb]  < G_N_BLOCKS       );
02030    g_block_to_kill[dev_id     ] = g_cache_lut.mem[u8_ofst_lut] ;
02031    g_cache_lut.mem[u8_ofst_lut] = g_cache_fbb.mem[u8_ofst_fbb] ;
02032    g_cache_fbb.mem[u8_ofst_fbb] = g_block_to_kill[dev_id]      ;
02033    trace("g_cache_lut.mem["); trace_u8(u8_ofst_lut); trace("] = "); trace_hex32(g_cache_lut.mem[u8_ofst_lut]); trace_nl();
02034    trace("g_cache_fbb.mem["); trace_u8(u8_ofst_fbb); trace("] = "); trace_hex32(g_cache_fbb.mem[u8_ofst_fbb]); trace_nl();
02035 
02036    // both FBB and LUT caches becomes invalid
02037    g_cache_lut.ctrl.dirty=TRUE;
02038    g_cache_fbb.ctrl.dirty=TRUE;
02039 }

Here is the caller graph for this function:

void nf_usb_stop ( void   ) 

This function perform a last copy tail if required, when USB enters suspend or is disconnected This function may be declared in "conf_usb.h" for "Usb_suspend_action()" and "Usb_vbus_off_action()" /!\ "g_last_log_sector" must be initialized to "0xFFFFFFFF" at startup to avoid spurious writes on during USB plug-in.

=> Don't forget to eject (windows) the peripheral from the PC before unpluggin it to avoid uncomplete writing (FAT not actualized)

Parameters:
none 
Returns:
none

Definition at line 2053 of file nf_mngt.c.

References FALSE, Nf_access_signal_off, Nf_access_signal_on, nf_cache_fbb_flush(), nf_cache_fbb_refill(), nf_cache_lut_flush(), nf_cache_lut_refill(), nf_copy_tail(), nf_XMCR_disable(), nf_XMCR_enable(), and TRUE.

02054 {
02055 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02056    nf_XMCR_enable();
02057 #endif
02058 
02059    if ( 0xFFFFFFFF!=g_last_log_sector )
02060    {
02061       Nf_access_signal_on();
02062       nf_copy_tail();
02063 
02064       if ( TRUE==g_cache_lut.ctrl.dirty )
02065       { 
02066          nf_cache_lut_flush();
02067          nf_cache_lut_refill(0);
02068       }
02069       if ( TRUE==g_cache_fbb.ctrl.dirty )
02070       {
02071          nf_cache_fbb_flush( FALSE );
02072          nf_cache_fbb_refill();
02073       }
02074       Nf_access_signal_off();
02075    }
02076 
02077 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02078    nf_XMCR_disable();
02079 #endif
02080 }

Here is the call graph for this function:

void nf_erase_all_blocks ( void   ) 

Definition at line 2091 of file nf_mngt.c.

References G_N_BLOCKS, nf_block_2_page(), nfc_erase_block(), and TRUE.

02092 {
02093   U16 i_block;
02094 
02095   for (i_block = G_N_BLOCKS ; i_block != 0 ; i_block--)
02096   {
02097     nfc_erase_block( nf_block_2_page(i_block), TRUE );
02098   }
02099 }

Here is the call graph for this function:

Ctrl_status nf_ram_2_nf ( U32  addr,
U8 ram 
)

This fonction initialise the memory for a write operation from ram buffer.

DATA FLOW is: RAM => NF

(sector = 512B)

Parameters:
addr Sector address to write
ram Ram buffer pointer
Returns:
Ctrl_status It is ready -> CTRL_GOOD A error occur -> CTRL_FAIL

Definition at line 2117 of file nf_mngt.c.

02118 {
02119   Ctrl_status tmp_bool;
02120   U16 i;
02121 
02122 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02123    nf_XMCR_enable();
02124 #endif
02125 
02126    s_n_sectors       = 1;
02127    s_curr_log_sector = addr;
02128    s_save_log_addr   = addr + 1;
02129    g_fatal           = FALSE;
02130    s_mem             = TRUE;
02131    s_start           = TRUE;
02132 
02133    // First write operation
02134    Nf_access_signal_on();
02135    if(( s_curr_log_sector==g_last_log_sector )                                           // New write is just after to the last write
02136    && (!(  ( 0==((U16)g_last_log_sector & ( ((U16)1<<(S_SHIFT_LOG_BLOCK_SECTOR)) -1)))   // Not on a logical block boundary
02137       && ( g_curr_dev_id==0                                                        ))))
02138    {
02139       nf_translate( NF_TRANS_NORMAL );
02140       Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);  // open the current device
02141       nfc_open_page_write( g_next_phys_page_addr, s_curr_n_byte );
02142    }
02143    else
02144    {      
02145       nf_open_write( TRUE );
02146    }
02147    
02148    for(i=0;i<512;i++)
02149    {
02150       Nf_wr_byte(*ram);
02151       ram++;
02152    }
02153 
02154    if (Is_nf_2k())
02155    {
02156       nf_update_spare_zone((U8)(1<<(G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE))-s_nb_sectors_step, s_nb_sectors_step);    // update the spare zone once the page has been filled in
02157    }
02158    else
02159    {
02160      nf_update_spare_zone(0, 1);    // update the spare zone once the page has been filled in
02161    }
02162    nf_xfer_update_vars();
02163 
02164    tmp_bool = nf_dfc_write_stop(0);   // ends write operations with "nf_dfc_write_stop(0)" that save the current environnement
02165    Nf_access_signal_off();
02166 
02167 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02168    nf_XMCR_disable();
02169 #endif
02170 
02171    return tmp_bool;
02172 }

Ctrl_status nf_nf_2_ram ( U32  addr,
U8 ram 
)

This fonction read 1 sector from NF to ram buffer.

DATA FLOW is: NF => RAM

(sector = 512B)

Parameters:
addr Sector address to read
ram Ram buffer pointer
Returns:
Ctrl_status It is ready -> CTRL_GOOD A error occur -> CTRL_FAIL

Definition at line 2186 of file nf_mngt.c.

02187 {
02188   U16 i;
02189 
02190 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02191    nf_XMCR_enable();
02192 #endif
02193 
02194    s_n_sectors       = 1;
02195    s_curr_log_sector = addr;
02196    s_save_log_addr   = addr + 1;
02197    g_fatal           = FALSE;
02198    s_mem             = TRUE;
02199    s_start           = TRUE;
02200 
02201    // First read operation
02202    Nf_access_signal_on();
02203    nf_open_read(TRUE);
02204    Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);
02205    nfc_open_page_read( g_phys_page_addr[g_curr_dev_id], s_curr_n_byte );
02206    s_nb_sectors_step = (U8)                              // determine number of sectors to be read
02207                        (Min(                             // on this first page
02208                              1,
02209                              ((1<<(G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE))-(s_curr_n_byte >> 9))
02210                            )
02211                        );
02212    
02213    Disable_interrupt();  
02214    for(i=0;i<512;i++)
02215    {
02216       *ram=Nf_rd_byte();
02217       ram++;
02218    }
02219    Enable_interrupt();  
02220    nf_xfer_update_vars();
02221    Nf_access_signal_off();
02222 
02223 #if (NF_XMCR_MODULE_SHARED == ENABLED)
02224    nf_XMCR_disable();
02225 #endif
02226 
02227    return CTRL_GOOD;   
02228 }


Variable Documentation

_MEM_TYPE_SLOW_ U8 g_n_zones

_MEM_TYPE_SLOW_ U16 g_n_blocks

_MEM_TYPE_FAST_ U8 g_n_row_cycles

_MEM_TYPE_SLOW_ U8 g_copy_back_cont

_MEM_TYPE_SLOW_ U8 g_copy_back_discont

_MEM_TYPE_FAST_ U8 g_shift_page_byte

Definition at line 98 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_shift_block_page

Definition at line 99 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_ofst_blk_status

Definition at line 100 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_shift_sector_byte [static]

Definition at line 101 of file nf_mngt.c.

Referenced by nf_init().

_MEM_TYPE_SLOW_ U8 s_shift_log_page_sector [static]

Definition at line 102 of file nf_mngt.c.

Referenced by nf_init().

_MEM_TYPE_SLOW_ U8 s_shift_log_block_sector [static]

Definition at line 103 of file nf_mngt.c.

Referenced by nf_init().

Bool g_fatal

Definition at line 107 of file nf_mngt.c.

Bool s_mem [static]

Definition at line 110 of file nf_mngt.c.

Bool s_start [static]

Definition at line 114 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_copy_src

Definition at line 116 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_nf_first_block = 0

Definition at line 117 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_lut g_cache_lut

Definition at line 129 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb

Definition at line 130 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_page_buffer[((2048)+(2048)/32)]

Definition at line 133 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 s_save_log_addr [static]

Definition at line 137 of file nf_mngt.c.

_MEM_TYPE_BIT_ bit g_nf_init

Definition at line 141 of file nf_mngt.c.

_MEM_TYPE_MEDFAST_ U16 g_log_block_id

Definition at line 142 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_export_blocks = 0xFFFF

Definition at line 143 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_free_blocks

Definition at line 144 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_n_sub_lut

Definition at line 145 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz

Definition at line 146 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz

Definition at line 147 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_fbb_block_addr

Definition at line 148 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_fbb_block_index

Definition at line 149 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_lut_block_addr[(NF_N_DEVICES *(8 *1024)/(512/2))]

Definition at line 150 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_lut_block_index[(NF_N_DEVICES *(8 *1024)/(512/2))]

Definition at line 151 of file nf_mngt.c.

_MEM_TYPE_FAST_ U16 s_n_sectors [static]

Definition at line 153 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 s_nb_sectors_step [static]

Definition at line 154 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_curr_dev_id

Definition at line 155 of file nf_mngt.c.

_MEM_TYPE_FAST_ U16 s_curr_n_byte [static]

Definition at line 156 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 s_curr_log_sector [static]

Definition at line 157 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_last_log_sector = 0xFFFFFFFF

Definition at line 158 of file nf_mngt.c.

_MEM_TYPE_FAST_ Nf_state s_state [static]

Definition at line 159 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_block_to_kill[NF_N_DEVICES]

Definition at line 161 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES]

Definition at line 162 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_save_phys_page_addr

Definition at line 164 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_save_curr_dev_id

Definition at line 165 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_next_phys_page_addr

Definition at line 167 of file nf_mngt.c.


Generated on Wed Sep 23 09:17:13 2009 for ATMEL by  doxygen 1.5.3