//! \brief Read the ID of the Nand-Flash //! //! \param read_id_cmd Read_id command (NF_READ_ID_CMD, NF_READ_ID2_CMD) //! \param nf_num Nand Flash number //! //! \return : //! MSB0(ret) (MSB) is the Maker Code, //! MSB1(ret) is the Device Id, //! MSB2(ret) is 3rd byte returned, //! MSB3(ret) (LSB) is 4th byte returned. //! //! \pre <code>nf_init()</code> should have been called before. //! U32 nf_read_id( U8 read_id_cmd, U8 nf_num ) { U32 ret; nf_select( nf_num ); nf_wait_busy(); //nf_force_CE(); nf_wr_cmd (read_id_cmd); nf_wr_addr( 0 ); MSB0(ret)= nf_rd_data(); // Maker Code MSB1(ret)= nf_rd_data(); // Device Id MSB2(ret)= nf_rd_data(); // extra MSB3(ret)= nf_rd_data(); // extra (Multi Plane Support) //Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_NOP); return ret; }
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"); } }
/*! \brief Main function. */ int main(void) { bool valid_block_found[NF_N_DEVICES]; U32 u32_nf_ids, i_dev, i_block; U8 maker_id, device_id, byte3; U32 i, time_s, time_e; U8 data; // start init sysclk_init(); // Enable clock for require module sysclk_enable_hsb_module(SYSCLK_EBI); sysclk_enable_pbb_module(SYSCLK_SMC_REGS); sysclk_enable_pbb_module(SYSCLK_HMATRIX); // Initialize the board. // The board-specific conf_board.h file contains the configuration of the board // initialization. board_init(); init_stdio(); #ifdef NF_ADDON // addon nandflash board for EVK1104 (not mounted by default) // Unselect NF on board gpio_set_gpio_pin(AVR32_PIN_PX53); gpio_set_gpio_pin(AVR32_PIN_PX52); #endif nf_init(sysclk_get_cpu_hz()); nf_unprotect(); printf("\x0C"); printf("Nand Flash example.\r\n===================\r\n\r\n"); // - Simple test of the NF communication through the SMC. // - Find all bad blocks. // - Find a valid block for the remaining tests. nf_reset_nands(NF_N_DEVICES); printf("\tDetecting Nand Flash device(s).\r\n"); for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) { // Performs some init here... valid_block_found[i_dev] = false; // Test Maker and Device ids u32_nf_ids = nf_read_id( NF_READ_ID_CMD, i_dev ); maker_id = MSB0(u32_nf_ids); device_id = MSB1(u32_nf_ids); byte3 = MSB3(u32_nf_ids); printf("\t\tNF %ld: [Maker=0x%02x] [Device=0x%02x] [byte3=0x%02x]\r\n", i_dev, maker_id, device_id, byte3); if( maker_id==M_ID_MICRON ) { printf("\t\t Micron chip"); if( (device_id==0xDA) && (byte3==0x15) ) printf("- MT29F2G08AACWP device\r\n"); else if( (device_id==0xDA) && (byte3==0x95) ) printf("- MT29F2G08AADWP device\r\n"); else { printf("- *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n"); return -1; } } else { printf("\t\t *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n"); return -1; } } printf("\r\n\tTesting bad blocks.\r\n"); for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) { printf("\t\tNF %ld:\r\n", i_dev); nf_select(i_dev); for( i_block=0 ; i_block<G_N_BLOCKS ; i_block++ ) { nf_open_page_read( nf_block_2_page(i_block), NF_SPARE_POS + G_OFST_BLK_STATUS ); if( (nf_rd_data()!=0xFF) ) { // The block is bad. printf("\t\t\tBlock %ld (0x%lx) is bad.\r\n", i_block, i_block); } else { if( !valid_block_found[i_dev] ) { valid_block_found[i_dev]= true; valid_block_addr[i_dev] = i_block; printf("\t\t\tFirst valid block is at address %ld (0x%lx).\r\n", i_block, i_block); } } } } for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) if( !valid_block_found[i_dev] ) { printf("Error %d\r\n", __LINE__); return 0; } // - Ensure good NF behaviour through simple commands. // Erase, Program, Read // - Measures NF timings. printf("\r\n\tMeasuring NF timings.\r\n"); for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) { printf("\t\tNF %ld:\r\n", i_dev); nf_select(i_dev); nf_erase_block( nf_block_2_page(valid_block_addr[0]), false); time_s = Get_sys_count(); nf_wait_busy(); time_e = Get_sys_count(); // Verify that the block is erased. nf_open_page_read( nf_block_2_page(valid_block_addr[0]), 0); for( i= 0; i<2048 ; i++ ) { data = nf_rd_data(); if( data!=0xFF ) { printf("\tError: offset %d is not erased (read %d).\r\n", (U8)i, data); return 0; } } printf("\t\t\tTime to erase a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz())); nf_open_page_write( nf_block_2_page(valid_block_addr[0]), 0); for( i=0 ; i<2048 ; i++ ) nf_wr_data(i%256); nf_wr_cmd(NF_PAGE_PROGRAM_CMD); time_s = Get_sys_count(); nf_wait_busy(); time_e = Get_sys_count(); printf("\t\t\tTime to program a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz())); time_s = Get_sys_count(); nf_open_page_read( nf_block_2_page(valid_block_addr[0]), 0); time_e = Get_sys_count(); printf("\t\t\tTime to access to a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz())); for( i= 0; i<2048 ; i++ ) { data = nf_rd_data(); if( data!= i%256) { printf("\tError: expect %d, read %d\r\n", (U8)i, data); return 0; } } } printf("Example DONE\r\n"); return 0; }