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 49 of file nf_mngt.c.

#define NF_ECC_MNGT   (DISABLE)

Definition at line 50 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 116 of file nf_mngt.c.

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

enum Nf_translate_mode

Enumerator:
NF_TRANS_NORMAL 
NF_TRANS_FLUSH 
NF_TRANS_SWAP 

Definition at line 166 of file nf_mngt.c.

00167 {
00168    NF_TRANS_NORMAL  // make simple translation.
00169 ,  NF_TRANS_FLUSH   // make simple translation. Force flush of LUT and FBB caches.
00170 ,  NF_TRANS_SWAP    // Swap blocks LUT <-> FBB
00171 } 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 1740 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().

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

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 844 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().

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

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 877 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().

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

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

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

References 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().

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

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 487 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().

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

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 629 of file nf_mngt.c.

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

Referenced by nf_write_10().

00630 {
00631    U8 j;
00632    for (j = 8*nb_sectors ; j != 0 ; j--)        // 8 * 64 bytes = 512 bytes
00633    {
00634       while(!Is_usb_read_enabled())
00635       {
00636          if(!Is_usb_endpoint_enabled())
00637            return; // USB Reset
00638       }
00639       Disable_interrupt();                      // Global disable.
00640 
00641       Nf_wr_byte(Usb_read_byte());              // write 64 bytes to the card
00642       Nf_wr_byte(Usb_read_byte());
00643       Nf_wr_byte(Usb_read_byte());
00644       Nf_wr_byte(Usb_read_byte());
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 
00706       Usb_ack_receive_out();           // USB EPOUT read acknowledgement.
00707       Enable_interrupt();              // Global re-enable.
00708    }
00709 }

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 537 of file nf_mngt.c.

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

Referenced by nf_read_10().

00538 {
00539  U8 j;
00540 
00541    for (j = 8*nb_sectors; j != 0; j--)                      // 8 * 64 bytes = 512 bytes
00542    {
00543       Disable_interrupt();
00544 
00545       Usb_write_byte(Nf_rd_byte());                         // read 64 bytes from card
00546       Usb_write_byte(Nf_rd_byte());
00547       Usb_write_byte(Nf_rd_byte());
00548       Usb_write_byte(Nf_rd_byte());
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       Enable_interrupt();
00610 
00611       Usb_send_in();                            // validate transfer
00612       while(Is_usb_write_enabled()==FALSE)
00613       {
00614          if(!Is_usb_endpoint_enabled())
00615             return; // USB Reset
00616       }
00617    }
00618 }

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 721 of file nf_mngt.c.

References _MEM_TYPE_SLOW_, 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().

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

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 199 of file nf_mngt.c.

Referenced by nf_read_capacity(), and nf_test_unit_ready().

00200 {
00201    if ( g_nf_init ) return PASS;
00202 
00203    return nf_verify_resume();
00204 }

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 215 of file nf_mngt.c.

Referenced by main().

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

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 240 of file nf_mngt.c.

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

Bool nf_wr_protect ( void   ) 

Definition at line 259 of file nf_mngt.c.

00260 {
00261     return FALSE;
00262 }

Bool nf_removal ( void   ) 

Definition at line 264 of file nf_mngt.c.

00265 {
00266     return TRUE;
00267 }

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 293 of file nf_mngt.c.

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

00294 {
00295    return
00296       (U32)g_n_export_blocks
00297    << (G_SHIFT_BLOCK_PAGE +G_SHIFT_PAGE_BYTE -S_SHIFT_SECTOR_BYTE)
00298    ;
00299 }

Here is the caller graph for this function:

U32 nf_block_2_page ( U16  block_addr  ) 

Definition at line 303 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().

00304 {
00305    return (U32)block_addr<<G_SHIFT_BLOCK_PAGE;
00306 }

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 317 of file nf_mngt.c.

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

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 381 of file nf_mngt.c.

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

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 767 of file nf_mngt.c.

Referenced by nf_ram_2_nf(), and nf_write_10().

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

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

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

Referenced by nf_cache_lut_flush(), and nf_rebuild().

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

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

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

Referenced by nf_cache_fbb_flush(), and nf_rebuild().

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

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

Here is the call graph for this function:

static void nf_check_lut ( void   )  [static]

Definition at line 1511 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.

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

Here is the call graph for this function:

void nf_copy_tail ( void   ) 

Definition at line 1555 of file nf_mngt.c.

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

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

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 1660 of file nf_mngt.c.

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

01661 {
01662   U8 _MEM_TYPE_SLOW_ * tempbuf = datbuf;
01663   U8 i = loop;
01664 
01665   while (i != 0)
01666   {
01667      Nf_wr_byte(*(tempbuf)); tempbuf++;
01668      Nf_wr_byte(*(tempbuf)); tempbuf++;
01669      Nf_wr_byte(*(tempbuf)); tempbuf++;
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      i--;
01684   }
01685 }

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 1696 of file nf_mngt.c.

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

01697 {
01698   U8 _MEM_TYPE_SLOW_ * tempbuf = datbuf;
01699   U8 i = loop;
01700 
01701   while (i != 0)
01702   {
01703      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01704      *(tempbuf) = Nf_rd_byte(); tempbuf++;
01705      *(tempbuf) = Nf_rd_byte(); tempbuf++;
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      i--;
01720   }
01721 }

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 1856 of file nf_mngt.c.

Referenced by nf_copy_tail(), and nf_open_write().

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

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 2018 of file nf_mngt.c.

Referenced by nf_translate().

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

Here is the caller graph for this function:

void nf_erase_all_blocks ( void   ) 

Definition at line 2088 of file nf_mngt.c.

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

02089 {
02090   U16 i_block;
02091 
02092   for (i_block = G_N_BLOCKS ; i_block != 0 ; i_block--)
02093   {
02094     nfc_erase_block( nf_block_2_page(i_block), TRUE );
02095   }
02096 }

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 2114 of file nf_mngt.c.

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

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 2183 of file nf_mngt.c.

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


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 95 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_shift_block_page

Definition at line 96 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_ofst_blk_status

Definition at line 97 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_shift_sector_byte [static]

Definition at line 98 of file nf_mngt.c.

Referenced by nf_init().

_MEM_TYPE_SLOW_ U8 s_shift_log_page_sector [static]

Definition at line 99 of file nf_mngt.c.

Referenced by nf_init().

_MEM_TYPE_SLOW_ U8 s_shift_log_block_sector [static]

Definition at line 100 of file nf_mngt.c.

Referenced by nf_init().

Bool g_fatal

Definition at line 104 of file nf_mngt.c.

Bool s_mem [static]

Definition at line 107 of file nf_mngt.c.

Bool s_start [static]

Definition at line 111 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_copy_src

Definition at line 113 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_nf_first_block = 0

Definition at line 114 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_lut g_cache_lut

Definition at line 126 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb

Definition at line 127 of file nf_mngt.c.

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

Definition at line 130 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 s_save_log_addr [static]

Definition at line 134 of file nf_mngt.c.

_MEM_TYPE_BIT_ bit g_nf_init

Definition at line 138 of file nf_mngt.c.

_MEM_TYPE_MEDFAST_ U16 g_log_block_id

Definition at line 139 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_export_blocks = 0xFFFF

Definition at line 140 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_free_blocks

Definition at line 141 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_n_sub_lut

Definition at line 142 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz

Definition at line 143 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz

Definition at line 144 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_fbb_block_addr

Definition at line 145 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_fbb_block_index

Definition at line 146 of file nf_mngt.c.

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

Definition at line 147 of file nf_mngt.c.

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

Definition at line 148 of file nf_mngt.c.

_MEM_TYPE_FAST_ U16 s_n_sectors [static]

Definition at line 150 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 s_nb_sectors_step [static]

Definition at line 151 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_curr_dev_id

Definition at line 152 of file nf_mngt.c.

_MEM_TYPE_FAST_ U16 s_curr_n_byte [static]

Definition at line 153 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 s_curr_log_sector [static]

Definition at line 154 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_last_log_sector = 0xFFFFFFFF

Definition at line 155 of file nf_mngt.c.

_MEM_TYPE_FAST_ Nf_state s_state [static]

Definition at line 156 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_block_to_kill[NF_N_DEVICES]

Definition at line 158 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES]

Definition at line 159 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_save_phys_page_addr

Definition at line 161 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_save_curr_dev_id

Definition at line 162 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_next_phys_page_addr

Definition at line 164 of file nf_mngt.c.


Generated on Fri Oct 31 14:31:36 2008 for ATMEL by  doxygen 1.5.3