nf_drv.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00015 
00016 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted provided that the following conditions are met:
00020  *
00021  * 1. Redistributions of source code must retain the above copyright notice,
00022  * this list of conditions and the following disclaimer.
00023  *
00024  * 2. Redistributions in binary form must reproduce the above copyright notice,
00025  * this list of conditions and the following disclaimer in the documentation
00026  * and/or other materials provided with the distribution.
00027  *
00028  * 3. The name of ATMEL may not be used to endorse or promote products derived
00029  * from this software without specific prior written permission.
00030  *
00031  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00032  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00033  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00034  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00035  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00036  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00037  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00038  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00039  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00040  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00041  */
00042 
00043 
00044 //_____  I N C L U D E S ___________________________________________________
00045 #define  _nfc_drv_c_
00046 
00047 #include  "config.h"          // general project configuration file
00048 #include  "conf_nf.h"         // global NAND Flash configuration file
00049 #include  "nf.h"              // NAND Flash informations (structure, parameters)
00050 #include  "nf_drv.h"          // declarations of constants, low levels routines, public prototypes
00051 
00052 //_____ D E C L A R A T I O N ______________________________________________
00053 //
00054 
00055 #ifndef __GNUC__
00056   __no_init volatile xdata Byte nf_send_cmd  At(NF_CMD_LATCH_ENABLE_ADD);  // Command
00057   __no_init volatile xdata Byte nf_send_add  At(NF_ADD_LATCH_ENABLE_ADD);  // Address
00058   __no_init volatile xdata Byte nf_data      At(NF_ADDRESS_CMD_DATA);      // Data
00059 #else
00060   volatile unsigned char nf_send_cmd  __attribute__ ((section (".nf_cmd")));
00061   volatile unsigned char nf_send_add  __attribute__ ((section (".nf_add")));
00062   volatile unsigned char nf_data      __attribute__ ((section (".nf_dat")));
00063 #endif
00064 
00065 #ifndef NF_XMCR_MODULE_SHARED
00066    #warning NF_XMCR_MODULE_SHARED must be defined to ENABLE if XMCR module is shared with other hardware peripherals
00067    #define NF_XMCR_MODULE_SHARED       DISABLED
00068 #endif
00069 
00070 #define     BAD_BLOCK_OFFSET     0
00071 #ifndef __GNUC__
00072   extern   U16 bad_block_table[100];
00073 #else
00074   U16 bad_block_table[100];
00075 #endif
00076 
00077 #if( NF_BAD_CONFIG==(FALSE) )
00078 
00079 
00080 //_____ D E C L A R A T I O N ______________________________________________
00081 
00082 void nfc_select_dev( U8 dev )
00083 {
00084    if(0==dev)
00085    {
00086       Nandflash1_unselect();
00087       Nandflash0_select();
00088    }else{
00089       Nandflash0_unselect();
00090       Nandflash1_select();
00091    }
00092 }
00093 
00094 
00105 #if (NF_AUTO_DETECT_2KB==FALSE) && (NF_AUTO_DETECT_512B==FALSE)
00106 U8 nfc_check_type( U8 nb_dev )
00107 {
00108    U8 i_dev;
00109    if( 2 < nb_dev )
00110       nb_dev = 2; // Only 1 or 2 for this driver
00111 
00112 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00113    nf_XMCR_enable();
00114 #endif
00115    nfc_init(        nb_dev, 0 );
00116    nfc_reset_nands( nb_dev ); // Reset all the NF devices
00117 
00118    // Test NF configuration
00119    //
00120    for( i_dev=0 ; i_dev<nb_dev ; i_dev++ )
00121    {
00122       Nfc_action( NFC_ACT_DEV_SELECT, i_dev);
00123       nfc_wait_busy();
00124       Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_CELOW);
00125       Nfc_set_cmd(NF_READ_ID_CMD);
00126       Nfc_set_adc( 0 );
00127       if(( Nfc_rd_data_fetch_next()!=G_DEV_MAKER  )
00128       || ( Nfc_rd_data_fetch_next()!=G_DEV_ID     ))
00129       {
00130          return i_dev;
00131       }
00132       if( G_CE_TOGGLE )
00133       {
00134          // disable CE Low
00135          Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_NOP);
00136       }
00137    }
00138 
00139 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00140    nf_XMCR_disable();
00141 #endif
00142    return nb_dev;
00143 }
00144 #endif
00145 
00146 
00151 void nfc_reset_nands( U8 nb_dev )
00152 {
00153    U8 i_dev;
00154    Mcu_set_sfr_page_nfc();
00155    for( i_dev=0 ; i_dev<nb_dev ; i_dev++ )
00156    {
00157       Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00158       // The wait is mandatory here since the function is used to wait any
00159       // pending internal programmation (Cache Program cmd).
00160       nfc_wait_busy();
00161       Nfc_set_cmd(NF_RESET_CMD);
00162       nfc_wait_busy();
00163    }
00164 }
00165 
00166 
00169 
00170 
00171 void nf_XMCR_enable( void )
00172 {
00173 #if (NF_CLE_ALE_MANUAL == ENABLED)
00174   XMCRB |= ((1<<XMM2) | (1<<XMM1) | (1<<XMM0));   // limit XRAM interface to A7 (release PC0..7)
00175 #else
00176   XMCRB |= ((1<<XMM2) | (1<<XMM1));                // limit XRAM interface to A9 (release PC2..7)
00177 #endif  
00178   XMCRA |= (1<<SRE);                  // enable the external memory
00179 }
00180 
00181 
00184 void nf_XMCR_disable( void )
00185 {
00186   Nandflash0_unselect();
00187   Nandflash1_unselect();
00188   XMCRA &= ~(1<<SRE);  // disable the external memory
00189 }
00190 
00191 
00192 
00193 
00194 
00195 
00202 Status_bool nfc_check_status( void )
00203 {
00204    Mcu_set_sfr_page_nfc();
00205    nfc_wait_busy(); // Send a status command and wait the completion of the last command
00206    if ( (Nfc_rd_data()&NF_MASK_STATUS_FAIL)==0 ) { return PASS; } // I/O 0   Pass:0  Fail:1
00207    else                                          { return FAIL; }
00208 }
00209 
00219 // TODO: Improve the argument list: 6 bytes are needed
00220 void nfc_open_page_read( U32 page_addr, U16 byte_addr)
00221 {
00222    Mcu_set_sfr_page_nfc();
00223    nfc_wait_busy();
00224    Nfc_open_page_read( page_addr, byte_addr);
00225 }
00226 
00227 
00228 
00238 void nfc_open_page_write( U32 page_addr, U16 byte_addr)
00239 {
00240    Mcu_set_sfr_page_nfc();
00241    Nfc_open_page_write( page_addr, byte_addr);
00242 }
00243 
00244 
00245 
00254 void nfc_mark_bad_block(U32 page_addr)
00255 {
00256    U8  n_bytes;
00257    U8  i_byte;
00258    U8  i_page;
00259 
00260    Mcu_set_sfr_page_nfc();
00261 
00262    n_bytes= ( Is_nf_512() )
00263    ?  16  // 512B page access
00264    :  64  // 2KB  page access
00265    ;
00266 
00267    // Erasing the block is mandatory to prevent partial programming
00268    // (some 512B NF does support partial prog, but not after a copy back command).
00269    nfc_erase_block( page_addr, TRUE );
00270    for ( i_page=(U8)1<<G_SHIFT_BLOCK_PAGE ; i_page!=0 ; i_page--, page_addr++ )
00271    {
00272       nfc_open_page_write( page_addr, NF_SPARE_POS-8 );
00273       Nfc_wr_data('A'); Nfc_wr_data('t');
00274       Nfc_wr_data('m'); Nfc_wr_data('e');
00275       Nfc_wr_data('l'); Nfc_wr_data(' ');
00276       Nfc_wr_data(' '); Nfc_wr_data(' ');
00277       for ( i_byte=n_bytes ; i_byte!=0 ; i_byte-=4 )
00278       {
00279          Nfc_wr_data(0);
00280          Nfc_wr_data(0);
00281          Nfc_wr_data(0);
00282          Nfc_wr_data(0);
00283       }
00284       Nfc_set_cmd(NF_PAGE_PROGRAM_CMD); // Confirm programmation
00285    }
00286 }
00287 
00288 
00289 
00301 void nfc_erase_block( U32 page_addr, U8 force_erase )
00302 {
00303    Mcu_set_sfr_page_nfc();
00304    if (FALSE == force_erase)
00305    {
00306       nfc_open_page_read( page_addr, NF_SPARE_POS + G_OFST_BLK_STATUS );
00307       if( (Nfc_rd_data() != 0xFF) ) return;    // The block is bad. We can not erase it
00308    }
00309    nfc_wait_busy();
00310    Nfc_unprotect_all_flash();                    // WP may be actif due to block protection
00311    Nfc_set_cmd (NF_BLOCK_ERASE_CMD);             // Auto Block Erase Setup
00312    Nfc_set_adr( LSB0(page_addr) );
00313    Nfc_set_adr( LSB1(page_addr) );
00314    if (3 == G_N_ROW_CYCLES)
00315    {
00316       Nfc_set_adr( MSB1(page_addr) );
00317    }
00318    Nfc_set_cmd(NF_BLOCK_ERASE_CONFIRM_CMD);      // Erase command
00319 }
00320 
00321 
00322 
00332 void nfc_read_spare_byte(
00333    U8 _MEM_TYPE_SLOW_ * p_byte
00334 ,  U8  n_byte
00335 ,  U32 page_addr)
00336 {
00337    U8  i;
00338 
00339    Mcu_set_sfr_page_nfc();
00340    nfc_open_page_read( page_addr, NF_SPARE_POS);
00341 
00342    for ( i=0 ; i!=n_byte ; i++ )
00343    {
00344       p_byte[i] = Nfc_rd_data_fetch_next();
00345    }
00346 }
00347 
00352 void nfc_wait_busy( void )
00353 {
00354    register int Reg;
00355    Nfc_set_cmd(NF_READ_STATUS_CMD);
00356    Reg = Nfc_rd_status();
00357    if( Is_nf_2k() )
00358    {
00359       if( G_CACHE_PROG )
00360       {
00361          while( (Nfc_rd_status() & NF_MASK_STATUS_T_RDY_2KB )==0 );
00362          while( (Nfc_rd_status() & NF_MASK_STATUS_T_RDY_2KB )==0 );
00363       }
00364       else
00365       {
00366          while( (Nfc_rd_status() & NF_MASK_STATUS_READY     )==0 );
00367          while( (Nfc_rd_status() & NF_MASK_STATUS_READY     )==0 );
00368       }
00369    }
00370    if( Is_nf_512() )
00371    {
00372       while( (Nfc_rd_status() & NF_MASK_STATUS_T_RDY_512B )==0 );
00373       while( (Nfc_rd_status() & NF_MASK_STATUS_T_RDY_512B )==0 );
00374    }
00375 }
00376 
00377 
00378 
00379 
00380 
00381 #if (NF_DETECTION_ID==ENABLE) || (NF_AUTO_DETECT_2KB==TRUE) || (NF_AUTO_DETECT_512B==TRUE)
00382 
00396 U32 nfc_read_id( U8 read_id_cmd, U8 nf_num )
00397 {
00398    U32 ret;
00399 
00400    Mcu_set_sfr_page_nfc();
00401    Nfc_action(NFC_ACT_DEV_SELECT, nf_num);
00402    nfc_wait_busy();
00403    Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_CELOW);
00404    Nfc_set_cmd (read_id_cmd);
00405    Nfc_set_adc( 0 );
00406 
00407    MSB0(ret)= Nfc_rd_data_fetch_next(); // Maker Code
00408    MSB1(ret)= Nfc_rd_data_fetch_next(); // Device Id
00409    MSB2(ret)= Nfc_rd_data_fetch_next(); // extra
00410    MSB3(ret)= Nfc_rd_data_fetch_next(); // extra (Multi Plane Support)
00411 
00412    Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_NOP);
00413    return ret;
00414 }
00415 
00416 
00422 static Bool nfc_nf_is_ready( void )
00423 {
00424    register Reg;
00425    U8 u8_timeout;
00426 
00427    Nfc_set_cmd( NF_READ_STATUS_CMD );  // send status for each read, because the NF must be in reset sequence
00428    Reg = Nfc_rd_status();            // active first read
00429 
00430    for (u8_timeout=NF_MAX_RB_TIMEOUT ; u8_timeout!=0 ; u8_timeout--)
00431    {
00432       if(( (Nfc_rd_status() & NF_MASK_STATUS_READY) !=0 )    // the busy pin is not tested, and the bit ready may be wrong penddind the rise of busy pin
00433       && ( (Nfc_rd_status() & NF_MASK_STATUS_READY) !=0 ) )  // To not read a wrong status, we check the status after 6 cycles (300ns)
00434       {
00435             return TRUE;  // NF READY
00436       }
00437    }
00438    return FALSE;          // TIMEOUT
00439 }
00440 
00441 
00448 U8  nfc_detect( void )
00449 {
00450    U32   u32_nf_ids;
00451    U8    u8_i, u8_conf;
00452 
00453 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00454    nf_XMCR_enable();
00455 #endif
00456 
00457    // Init the Nand Flash Controller
00458    nfc_init(        NF_MAX_DEVICES, 0 );
00459    nfc_reset_nands( NF_MAX_DEVICES ); // Reset all the NF devices
00460 
00461    // Check the presence of device 0
00462    if ( FALSE == nfc_nf_is_ready() )
00463    {
00464       #if (NF_XMCR_MODULE_SHARED == ENABLED)
00465          nf_XMCR_disable();
00466       #endif
00467       return NO_NF_CONNECTED;
00468    }
00469 
00470    // Read the Nand Flash IDs of device 0
00471    u32_nf_ids = nfc_read_id( NF_READ_ID_CMD, 0 );
00472 
00473    // Identify the Nand Flash (device 0)
00474    for( u8_i=0 ; u8_i < (sizeof(nf_list_id)/sizeof(St_nf_id)) ; u8_i++)
00475    {
00476       if((nf_list_id[u8_i].manuf == MSB0(u32_nf_ids))
00477       && (nf_list_id[u8_i].dev   == MSB1(u32_nf_ids)))
00478          break; // here, ID is know
00479    }
00480    if( u8_i == (sizeof(nf_list_id)/sizeof(St_nf_id)) )
00481    {
00482       #if (NF_XMCR_MODULE_SHARED == ENABLED)
00483          nf_XMCR_disable();
00484       #endif
00485       return NF_UNKNOW;
00486    }
00487 
00488    // Set NF configuration parameters for initialisation and access
00489 #if (NF_GENERIC_DRIVER==TRUE)
00490 #  error Test me...
00491    g_shift_page_byte    =;
00492    g_shift_block_page   =;
00493 #endif
00494 
00495 #if (NF_GENERIC_DRIVER==TRUE) || (NF_AUTO_DETECT_2KB==TRUE) ||(NF_AUTO_DETECT_512B==TRUE)
00496 
00497    // Record info
00498    u8_conf     =  nf_list_id[u8_i].conf;
00499    g_dev_maker =  MSB0(u32_nf_ids); // Device maker
00500    g_dev_id    =  MSB1(u32_nf_ids); // Device ID
00501 
00502    // Search the number of block of device
00503    for( u8_i=0 ; u8_i < (sizeof(nf_list_link_id_block)/sizeof(St_nf_link_id_block)) ; u8_i++)
00504    {
00505       if( nf_list_link_id_block[u8_i].dev_id == g_dev_id )
00506          break; // ID found
00507    }
00508    if( u8_i == (sizeof(nf_list_link_id_block)/sizeof(St_nf_link_id_block)) )
00509       while(1);   // Error in NF definition
00510 
00511    g_n_zones            =  nf_list_link_id_block[u8_i].nb_zones;
00512 #if (NF_AUTO_DETECT_2KB==TRUE)
00513    if( 1 == g_n_zones )
00514       g_n_row_cycles    =  2;
00515    else
00516       g_n_row_cycles    =  3;
00517 #endif
00518 #if (NF_AUTO_DETECT_512B==TRUE)
00519    if( 2 >= g_n_zones )
00520       g_n_row_cycles    =  2;
00521    else
00522       g_n_row_cycles    =  3;
00523 #endif
00524    g_n_blocks           =  g_n_zones*1024L;
00525 
00526    g_copy_back_cont     = nf_list_conf[u8_conf].copy_back_cont   ;
00527    g_copy_back_discont  = nf_list_conf[u8_conf].copy_back_discont;
00528    g_cache_program      = nf_list_conf[u8_conf].cache_program    ;
00529    g_ce_toggle             = nf_list_conf[u8_conf].ce_toggle;
00530 /*   
00531    g_clock_dfc_nfc      = (nf_list_conf[u8_conf].dfc_nfc_clock<<5) & MSK_DNFCKS;
00532 
00533    Mcu_set_sfr_page_nfc();
00534    Nfc_set_read_timing((U8)nf_list_conf[u8_conf].timing_read );
00535    if( !g_ce_toggle )
00536    {
00537       // Enable CE low
00538       Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_CELOW);
00539    }
00540 */
00541 #endif
00542 
00543 #if (NF_XMCR_MODULE_SHARED == ENABLED)
00544    nf_XMCR_disable();
00545 #endif
00546    return u8_i;
00547 }
00548 
00549 #endif
00550 
00557 void nfc_copy_back_init( U32 page_addr )
00558 {
00559    Mcu_set_sfr_page_nfc();
00560    nfc_wait_busy();
00561    Nfc_unprotect_all_flash(); // WP may be actif due to block protection
00562    Nfc_set_cmd(NF_READ_CMD);
00563    Nfc_set_adc( 0 );
00564    Nfc_set_adc( 0 );
00565    Nfc_set_adr( LSB0(page_addr) );
00566    Nfc_set_adr( LSB1(page_addr) );
00567    if ( 3==G_N_ROW_CYCLES )
00568    {
00569       Nfc_set_adr( MSB1(page_addr) );
00570    }
00571    Nfc_set_cmd(NF_COPY_BACK_CMD);
00572    nfc_wait_busy();
00573 }
00574 
00575 
00582 #if (0)
00583 void nfc_copy_back_conf( U32 page_addr )
00584 {
00585    Mcu_set_sfr_page_nfc();
00586    nfc_wait_busy();
00587    Nfc_unprotect_all_flash();                              // WP may be actif due to block protection
00588    Nfc_set_cmd(NF_RANDOM_DATA_INPUT_CMD);
00589    Nfc_set_adc( 0 );
00590    Nfc_set_adc( 0 );
00591    Nfc_set_adr( LSB0(page_addr) );
00592    Nfc_set_adr( LSB1(page_addr) );
00593    if ( 3==G_N_ROW_CYCLES )
00594    {
00595       Nfc_set_adr( MSB1(page_addr) );
00596    }
00597    Nfc_set_cmd(NF_PAGE_PROGRAM_CMD);
00598 }
00599 #endif
00600 
00601 #endif // NF_BAD_CONFIG
00602 
00610 #if 0
00611 void nfc_print_block(U16 block_addr, U8 dev_id)
00612 {
00613    _MEM_TYPE_SLOW_ U32 page_addr=(U32)block_addr*((U8)1<<G_SHIFT_BLOCK_PAGE);
00614    _MEM_TYPE_SLOW_ U16 n_bytes;
00615    _MEM_TYPE_SLOW_ U16 i_byte;
00616    _MEM_TYPE_SLOW_ U8  i_page;
00617 
00618    Mcu_set_sfr_page_nfc();
00619    trace("\n\rDisplay block 0x");
00620    trace_hex( MSB(block_addr) );
00621    trace_hex( LSB(block_addr) );
00622 
00623    n_bytes= ( Is_nf_512() )
00624    ?  512   // 512B page access
00625    :  2048  // 2KB  page access
00626    ;
00627    Nfc_action(NFC_ACT_DEV_SELECT, dev_id);
00628    //for ( i_page=(U8)1<<G_SHIFT_BLOCK_PAGE ; i_page!=0 ; i_page--, page_addr++ )
00629    for ( i_page=0 ; i_page<64 ; i_page++, page_addr++ )
00630    {
00631       trace("\n\rOpening page 0x");
00632       trace_hex( MSB0(page_addr) );
00633       trace_hex( MSB1(page_addr) );
00634       trace_hex( MSB2(page_addr) );
00635       trace_hex( MSB3(page_addr) );
00636       #if 0
00637       nfc_open_page_read( page_addr, 0 );
00638       i_byte=Nfc_rd_data_fetch_next();
00639       for ( i_byte=0 ; i_byte<n_bytes ; )
00640       {
00641          if      ( !(i_byte%32) )
00642          {
00643             trace("\n\r0x");
00644             trace_hex( MSB(i_byte) );
00645             trace_hex( LSB(i_byte) );
00646             trace(" 0x");
00647          }
00648          else if ( !(i_byte%16) ) trace("   ");
00649          else if ( !(i_byte% 8) ) trace(" ");
00650          trace_hex( Nfc_rd_data_fetch_next() );
00651          trace_hex( Nfc_rd_data_fetch_next() );
00652          trace_hex( Nfc_rd_data_fetch_next() );
00653          trace_hex( Nfc_rd_data_fetch_next() );
00654          i_byte+=4;
00655       }
00656       #else
00657       nfc_open_page_read( page_addr, n_bytes );
00658       i_byte=Nfc_rd_data_fetch_next();
00659       #endif
00660       trace("\n\rSpare zone: 0x");
00661       for ( i_byte=4*4 ; i_byte!=0 ; i_byte-- )
00662       { // discard spare zone
00663          if( i_byte%4==0 ) trace_nl();
00664          trace_hex( Nfc_rd_data_fetch_next() );
00665          trace_hex( Nfc_rd_data_fetch_next() );
00666          trace_hex( Nfc_rd_data_fetch_next() );
00667          trace_hex( Nfc_rd_data_fetch_next() );
00668       }
00669       trace("\n\r");
00670    }
00671    trace("\n\rOther way to access spare zone: 0x");
00672    page_addr=(U32)block_addr*((U8)1<<G_SHIFT_BLOCK_PAGE);
00673    nfc_open_page_read( page_addr, NF_SPARE_POS );
00674    i_byte=Nfc_rd_data_fetch_next();
00675    {
00676       for ( i_byte=4*4 ; i_byte!=0 ; i_byte-- )
00677       { // discard spare zone
00678          trace_hex( Nfc_rd_data_fetch_next() );
00679          trace_hex( Nfc_rd_data_fetch_next() );
00680          trace_hex( Nfc_rd_data_fetch_next() );
00681          trace_hex( Nfc_rd_data_fetch_next() );
00682       }
00683       trace("\n\r");
00684    }
00685 }
00686 #endif

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