//! Initializes the nand flash memory driver. //! //! The device identification is performed to initialize the //! driver accordingly //! //! @param none //! //! @return none //! void nf_init ( void ) { trace("NF init\n\r"); g_nf_init=FALSE; // s_pending_write=FALSE; #if (NF_GENERIC_DRIVER==TRUE) #error Check this init... g_n_zones = NF_N_ZONES; g_n_blocks = NF_N_BLOCKS; g_shift_block_page = NF_SHIFT_BLOCK_PAGE; g_shift_page_byte = NF_SHIFT_PAGE_BYTE; s_shift_sector_byte = NF_SHIFT_SECTOR_BYTE; g_n_row_cycles = NF_N_ROW_CYCLES; if ( Is_nf_2k() ) // 2KB pages { g_ofst_blk_status = 0; } if ( Is_nf_512() ) // 512B pages { g_ofst_blk_status = 5; } s_shift_log_page_sector = G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE + NF_SHIFT_N_DEVICES; s_shift_log_block_sector = s_shift_log_page_sector + G_SHIFT_BLOCK_PAGE; #endif g_cache_lut.ctrl.valid = FALSE; g_cache_lut.ctrl.dirty = FALSE; g_cache_fbb.ctrl.valid = FALSE; g_cache_fbb.ctrl.dirty = FALSE; g_last_log_sector= 0xFFFFFFFF; }
//! \brief Mark a block as 'invalid' by clearing it entirely. //! //! \param page_addr absolute page address of the block //! //! \pre <code>nf_init()</code> should have been called before. //! The device which holds this bad block should have been selected //! before with <code>nf_select( id )</code>. //! void nf_mark_bad_block(U32 page_addr) { U8 n_bytes; U8 i_byte; U8 i_page; n_bytes= ( Is_nf_512() ) ? 16 // 512B page access : 64 // 2KB page access ; // Erasing the block is mandatory to prevent partial programming // (some 512B NF does support partial prog, but not after a copy back command). nf_erase_block( page_addr, true ); for ( i_page=(U8)1<<G_SHIFT_BLOCK_PAGE ; i_page!=0 ; i_page--, page_addr++ ) { nf_open_page_write( page_addr, NF_SPARE_POS-8 ); nf_wr_data('A'); nf_wr_data('t'); nf_wr_data('m'); nf_wr_data('e'); nf_wr_data('l'); nf_wr_data(' '); nf_wr_data(' '); nf_wr_data(' '); for ( i_byte=n_bytes ; i_byte!=0 ; i_byte-=4 ) { nf_wr_data(0); nf_wr_data(0); nf_wr_data(0); nf_wr_data(0); } nf_wr_cmd(NF_PAGE_PROGRAM_CMD); // Confirm programming } }
//! \brief Tests the true busy. Note that we test twice the ready, since there is //! an hardware minimum requirement between the end of the busy and the first //! read cycle. Since the busy is not wired, the ready is tested twice. //! void nf_wait_busy( void ) { ecchrs_freeze(&AVR32_ECCHRS); nf_wr_cmd(NF_READ_STATUS_CMD); if( Is_nf_2k() ) { if( G_CACHE_PROG ) { while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_2KB )==0 ); while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_2KB )==0 ); } else { while( (nf_rd_data() & NF_MASK_STATUS_READY )==0 ); while( (nf_rd_data() & NF_MASK_STATUS_READY )==0 ); } } if( Is_nf_512() ) { while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_512B )==0 ); while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_512B )==0 ); } ecchrs_unfreeze(&AVR32_ECCHRS); }
void nfc_print_block(U16 block_addr, U8 dev_id) { _MEM_TYPE_SLOW_ U32 page_addr=(U32)block_addr*((U8)1<<G_SHIFT_BLOCK_PAGE); _MEM_TYPE_SLOW_ U16 n_bytes; _MEM_TYPE_SLOW_ U16 i_byte; _MEM_TYPE_SLOW_ U8 i_page; trace("\n\rDisplay block 0x"); trace_hex( MSB(block_addr) ); trace_hex( LSB(block_addr) ); n_bytes= ( Is_nf_512() ) ? 512 // 512B page access : 2048 // 2KB page access ; nf_select( dev_id ); //for ( i_page=(U8)1<<G_SHIFT_BLOCK_PAGE ; i_page!=0 ; i_page--, page_addr++ ) for( i_page=0 ; i_page<64 ; i_page++, page_addr++ ) { trace("\n\rOpening page 0x"); trace_hex( MSB0(page_addr) ); trace_hex( MSB1(page_addr) ); trace_hex( MSB2(page_addr) ); trace_hex( MSB3(page_addr) ); #if 0 nf_open_page_read( page_addr, 0 ); for( i_byte=0 ; i_byte<n_bytes ; ) { if( !(i_byte%32) ) { trace("\n\r0x"); trace_hex( MSB(i_byte) ); trace_hex( LSB(i_byte) ); trace(" 0x"); } else if( !(i_byte%16) ) trace(" "); else if( !(i_byte% 8) ) trace(" "); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); i_byte+=4; } #else nf_open_page_read( page_addr, n_bytes ); #endif trace("\n\rSpare zone: 0x"); for( i_byte=4*4 ; i_byte!=0 ; i_byte-- ) { // discard spare zone if( i_byte%4==0 ) trace_nl(); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); trace_hex( nf_rd_data() ); } trace("\n\r"); } trace("\n\rOther way to access spare zone: 0x"); page_addr=(U32)block_addr*((U8)1<<G_SHIFT_BLOCK_PAGE); nf_open_page_read( page_addr, NF_SPARE_POS ); i_byte=Nfc_rd_data_fetch_next(); { for ( i_byte=4*4 ; i_byte!=0 ; i_byte-- ) { // discard spare zone trace_hex( Nfc_rd_data_fetch_next() ); trace_hex( Nfc_rd_data_fetch_next() ); trace_hex( Nfc_rd_data_fetch_next() ); trace_hex( Nfc_rd_data_fetch_next() ); } trace("\n\r"); } }