nf_drv.c

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

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