#include "config.h"#include "conf_nf.h"#include "nf.h"#include "nf_drv.h"#include "nf_mngt.h"#include "lib_mcu/debug.h"
Go to the source code of this file.
Defines | |
| #define | _TRACE_ (DISABLE) |
| #define | OFST (2*(i_dev + u16_tmp*NF_N_DEVICES)) |
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 | ut_nfc_erase_all (void) |
| static void | nf_init_buffer (void) |
| Clears the internal buffer. | |
| static Status_bool | nf_scan (void) |
| Scan the memory and looks for sub-LUT, free-blocks block and recovery blocks. | |
| static Status_bool | nf_rebuild (void) |
| static Bool | is_nf_invalid (void) |
| static U16 | nf_fetch_free_block (U8 i_dev) |
| Returns the first free block seen, scanning downstream. | |
| static U8 | nf_refine_index (U16 block_addr, U8 inc, U8 pattern) |
| Refines the position of the 'block' index according to a particular pattern. | |
| void | nf_init (void) |
| Initializes the nand flash memory driver. | |
| Status_bool | nf_verify_resume (void) |
| Ensure that the memory is in a good state before starting to use it. | |
| void | nf_cleanup_memory (void) |
| Cleanup the memory by erasing all the management blocks. | |
Variables | |
| _MEM_TYPE_SLOW_ U8 | g_n_zones |
| _MEM_TYPE_SLOW_ U16 | g_n_blocks |
| _MEM_TYPE_SLOW_ U8 | g_page_buffer [((2048)+(2048)/32)] |
| _MEM_TYPE_BIT_ bit | g_nf_init |
| _MEM_TYPE_SLOW_ U16 | g_last_sub_lut_log_sz |
| _MEM_TYPE_SLOW_ U16 | g_sub_lut_log_sz |
| Bool | g_is_found_lut |
| Bool | g_is_found_fbb |
| Bool | g_fatal |
| _MEM_TYPE_SLOW_ U8 | g_n_real_sub_lut |
| _MEM_TYPE_SLOW_ U16 | g_curr_block_addr [NF_N_DEVICES] |
| _MEM_TYPE_SLOW_ U8 | g_byte [16] |
| _MEM_TYPE_SLOW_ U8 | g_n_sub_lut |
| _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_SLOW_ U8 | s_nfd_rev |
| _MEM_TYPE_SLOW_ U16 | g_nf_first_block |
| static _MEM_TYPE_SLOW_ U8 | s_n_quarantine_blocks [NF_N_DEVICES] |
| static _MEM_TYPE_SLOW_ U16 | s_n_invalid_blocks [NF_N_DEVICES] |
| _MEM_TYPE_SLOW_ U16 | g_n_export_blocks |
| _MEM_TYPE_SLOW_ U16 | g_n_free_blocks |
| _MEM_TYPE_SLOW_ U16 | g_fbb_block_addr |
| _MEM_TYPE_SLOW_ U8 | g_fbb_block_index |
| _MEM_TYPE_SLOW_ U32 | g_last_log_sector |
| _MEM_TYPE_SLOW_ U32 | g_copy_src |
| _MEM_TYPE_SLOW_ U16 | g_block_to_kill [NF_N_DEVICES] |
| _MEM_TYPE_FAST_ U32 | g_phys_page_addr [NF_N_DEVICES] |
| _MEM_TYPE_FAST_ U8 | g_curr_dev_id |
| _MEM_TYPE_MEDFAST_ U16 | g_log_block_id |
| _MEM_TYPE_SLOW_ Cache_lut | g_cache_lut |
| _MEM_TYPE_SLOW_ Cache_fbb | g_cache_fbb |
Definition in file nf_unusual.c.
| #define _TRACE_ (DISABLE) |
Definition at line 49 of file nf_unusual.c.
| #define OFST (2*(i_dev + u16_tmp*NF_N_DEVICES)) |
Referenced by nf_rebuild().
| __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 ut_nfc_erase_all | ( | void | ) | [static] |
Definition at line 917 of file nf_unusual.c.
References _MEM_TYPE_SLOW_, FALSE, G_N_BLOCKS, NF_N_DEVICES, NF_SHIFT_BLOCK_PAGE, NFC_ACT_DEV_SELECT, Nfc_action, and nfc_erase_block().
Referenced by nf_verify_resume().
00918 { 00919 _MEM_TYPE_SLOW_ U8 i_dev =0; 00920 _MEM_TYPE_SLOW_ U16 i_block=0; 00921 _MEM_TYPE_SLOW_ U32 page_addr; 00922 00923 for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00924 { 00925 // Select the devices 00926 // 00927 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00928 00929 for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ ) 00930 { 00931 page_addr= (U32)i_block<<NF_SHIFT_BLOCK_PAGE; 00932 nfc_erase_block( page_addr, FALSE ) ; 00933 } 00934 } 00935 }
| static void nf_init_buffer | ( | void | ) | [static] |
Clears the internal buffer.
Definition at line 127 of file nf_unusual.c.
References NF_FULL_PAGE_BUFFER_SIZE.
Referenced by nf_rebuild().
00128 { 00129 U16 u16_tmp; 00130 for ( u16_tmp=NF_FULL_PAGE_BUFFER_SIZE ; u16_tmp!=0 ; u16_tmp-=2 ) 00131 { 00132 g_page_buffer[u16_tmp-1]=0xFF; 00133 g_page_buffer[u16_tmp-2]=0xFF; 00134 } 00135 }
| static Status_bool nf_scan | ( | void | ) | [static] |
Scan the memory and looks for sub-LUT, free-blocks block and recovery blocks.
| none |
Definition at line 300 of file nf_unusual.c.
References FAIL, FALSE, G_N_BLOCKS, G_OFST_BLK_STATUS, LSB, MSB, nf_block_2_page(), NF_N_DEVICES, nf_refine_index(), NF_SUBLUT_SIZE, NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_DATA, NFC_BLK_ID_FBB, NFC_BLK_ID_QUARANTINE, NFC_BLK_ID_SUBLUT, NFC_OFST_6_FBB_VALID, nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_2_BYTE_2, NFC_SPARE_OFST_3_BYTE_3, NFC_SPARE_OFST_4_BYTE_4, NFC_SPARE_OFST_6_LBA, NFC_SPARE_OFST_EXPORT, PASS, S_MNGT_DEV, trace(), trace_hex(), trace_hex16(), trace_nl(), trace_u32(), and TRUE.
Referenced by nf_verify_resume().
00301 { 00302 U8 i_dev =0; 00303 U16 i_block=0; 00304 U8 n_quarantine_blocks=0; 00305 U16 n_invalid_blocks=0; 00306 00307 g_last_sub_lut_log_sz =(U16)-1; 00308 g_sub_lut_log_sz =(U16)NF_SUBLUT_SIZE/NF_N_DEVICES; 00309 00310 00311 // Initialize the recovery structure. This should be done by the startup ! 00312 // 00313 g_is_found_lut =FALSE; 00314 g_is_found_fbb =FALSE; 00315 g_fatal =FALSE; 00316 g_n_real_sub_lut=0; 00317 00318 // Scan all the devices and looks for: 00319 // - the sub-LUT blocks 00320 // - the recovery block 00321 // - the free-blocks block 00322 // 00323 for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00324 { 00325 n_invalid_blocks = 0; 00326 n_quarantine_blocks= 0; 00327 g_curr_block_addr[i_dev]= G_N_BLOCKS -1; // points on the last block 00328 00329 trace("Device "); trace_hex(i_dev); trace("\n\r"); 00330 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00331 00332 for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ ) 00333 { 00334 nfc_read_spare_byte( g_byte, 16, nf_block_2_page(i_block) ); 00335 if ( g_byte[G_OFST_BLK_STATUS]!=0xFF ) 00336 { 00337 n_invalid_blocks +=1 ; 00338 trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): bad Block\n\r"); 00339 continue; // The block is bad 00340 } 00341 00342 if(( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_SUBLUT ) 00343 && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_FBB ) 00344 && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_QUARANTINE ) 00345 && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_DATA )) 00346 { 00347 n_invalid_blocks +=1; 00348 trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): Unknown\n\r"); 00349 continue; 00350 } 00351 else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_QUARANTINE ) 00352 { 00353 n_quarantine_blocks +=1; 00354 trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): Quarantine\n\r"); 00355 continue; 00356 } 00357 else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_SUBLUT ) 00358 { 00359 n_invalid_blocks +=1; 00360 if ( i_dev==S_MNGT_DEV ) 00361 { 00362 U8 sub_lut_id = g_byte[NFC_SPARE_OFST_2_BYTE_2]; 00363 g_n_sub_lut = g_byte[NFC_SPARE_OFST_4_BYTE_4]; 00364 g_is_found_lut = TRUE; 00365 g_n_real_sub_lut++; 00366 g_lut_block_addr[sub_lut_id] = i_block; 00367 if ( sub_lut_id==(g_n_sub_lut-1) ) 00368 { 00369 MSB(g_last_sub_lut_log_sz)= g_byte[NFC_SPARE_OFST_6_LBA ]; 00370 LSB(g_last_sub_lut_log_sz)= g_byte[NFC_SPARE_OFST_6_LBA+1]; 00371 } 00372 g_lut_block_index[sub_lut_id]= nf_refine_index(i_block, 1, NFC_BLK_ID_SUBLUT); 00373 trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): SUB-LUT (id ");trace_hex(sub_lut_id);trace(" ofst "); trace_hex(g_lut_block_index[sub_lut_id]); trace(")\n\r"); 00374 continue ; 00375 } 00376 else 00377 { // LUT found on bad NF 00378 g_fatal=TRUE; 00379 break; 00380 } 00381 } 00382 00383 else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_FBB ) 00384 { 00385 n_invalid_blocks +=1; 00386 if ( i_dev==S_MNGT_DEV ) 00387 { 00388 if ( TRUE==g_is_found_fbb ) 00389 { 00390 g_fatal=TRUE; // already found 00391 break; 00392 } 00393 g_fbb_block_addr = i_block; 00394 g_fbb_block_index = nf_refine_index(i_block, 1, NFC_BLK_ID_FBB); 00395 nfc_read_spare_byte( g_byte, 16, nf_block_2_page(i_block) + (U32)g_fbb_block_index ); // Reload 00396 if( NFC_OFST_6_FBB_VALID!=g_byte[NFC_SPARE_OFST_6_LBA] ) 00397 { 00398 g_fatal=TRUE; // FBB not valid. Force rebuild 00399 break; 00400 } 00401 00402 MSB(g_n_free_blocks) = g_byte[NFC_SPARE_OFST_2_BYTE_2]; 00403 LSB(g_n_free_blocks) = g_byte[NFC_SPARE_OFST_3_BYTE_3]; 00404 s_nfd_rev = g_byte[NFC_SPARE_OFST_4_BYTE_4]; 00405 MSB(g_n_export_blocks) = g_byte[NFC_SPARE_OFST_EXPORT]; 00406 LSB(g_n_export_blocks) = g_byte[NFC_SPARE_OFST_EXPORT+1]; 00407 trace(" g_n_free_blocks="); trace_hex16(g_n_free_blocks); trace_nl(); 00408 trace(" g_n_export_blocks="); trace_hex16(g_n_export_blocks); trace_nl(); 00409 g_is_found_fbb=TRUE; 00410 trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): FBB (ofst "); trace_hex( g_fbb_block_index ); trace(")\n\r"); 00411 continue ; 00412 } 00413 else 00414 { 00415 g_fatal=TRUE; 00416 break; 00417 } 00418 } 00419 } // for ( i_block 00420 00421 // A fatal error on one device is enough to cleanup all the devices ! 00422 // 00423 s_n_invalid_blocks[ i_dev]= n_invalid_blocks; 00424 s_n_quarantine_blocks[i_dev]= n_quarantine_blocks; 00425 00426 if ( TRUE==g_fatal ) { break; } 00427 } // for ( i_dev 00428 00429 return (g_fatal==TRUE) ? FAIL: PASS; 00430 } // nf_scan
| static Status_bool nf_rebuild | ( | void | ) | [static] |
Rebuild the memory and create LUT, Recovery and Free-blocks blocks.
TBD
It uses s_n_invalid_blocks (number of invalid blocks) and g_curr_block_addr (current block address of each device).
Definition at line 487 of file nf_unusual.c.
References _MEM_TYPE_SLOW_, Align_down, Assert, FAIL, FALSE, G_N_BLOCKS, G_OFST_BLK_STATUS, LSB, Max, MSB, N_SUBLUT, nf_block_2_page(), nf_copy_tail(), nf_fetch_free_block(), nf_init_buffer(), NF_LOW_N_FREE_THRESHOLD, NF_N_DEVICES, NF_PAGE_BUFFER_SIZE, NF_SHIFT_PAGE_BYTE, NF_SHIFT_SUBLUT_PHYS, NF_SPARE_POS, NF_SUBLUT_SIZE, nf_write_fbb(), nf_write_lut(), NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_DATA, nfc_erase_block(), nfc_mark_bad_block(), NFC_OFST_3_DATA_DST, nfc_open_page_read(), Nfc_rd_data_fetch_next, nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_3_BYTE_3, NFC_SPARE_OFST_6_LBA, OFST, PASS, S_MNGT_DEV, S_SHIFT_LOG_BLOCK_SECTOR, SIZE_BLOCK_PAGE, SIZE_PAGE_SECTOR, trace(), trace_hex(), trace_hex16(), trace_hex32(), trace_nl(), and TRUE.
Referenced by nf_verify_resume().
00488 { 00489 Status_bool status_bool=PASS; 00490 Bool b_duplicate; 00491 U8 i_sub_lut; 00492 U8 i_dev =0; 00493 _MEM_TYPE_SLOW_ U16 i_block=0; 00494 _MEM_TYPE_SLOW_ U16 u16_tmp; 00495 _MEM_TYPE_SLOW_ U16 sub_lut_log_sz; 00496 _MEM_TYPE_SLOW_ U16 log_block_addr; 00497 _MEM_TYPE_SLOW_ U16 log_block_addr_min; 00498 _MEM_TYPE_SLOW_ U16 log_block_addr_max; 00499 00500 // Refine the computation 00501 // 00502 s_n_invalid_blocks[S_MNGT_DEV] += 00503 1 // Need a block for the Free-blocks block 00504 + (G_N_BLOCKS*NF_N_DEVICES)/NF_SUBLUT_SIZE // and one for each sub-LUT 00505 ; 00506 00507 // Take the max number of invalid blocks of each devices 00508 // 00509 u16_tmp=s_n_invalid_blocks[0] ; 00510 for ( i_dev=1 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00511 { 00512 u16_tmp=Max( u16_tmp, s_n_invalid_blocks[i_dev] ); 00513 } 00514 00515 // Take the max number of quarantine blocks of each devices 00516 // 00517 i_sub_lut=s_n_quarantine_blocks[0] ; 00518 for ( i_dev=1 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00519 { 00520 i_sub_lut=Max( i_sub_lut, s_n_quarantine_blocks[i_dev] ); 00521 } 00522 00523 sub_lut_log_sz = (U16)NF_N_DEVICES*(G_N_BLOCKS -g_nf_first_block -u16_tmp); 00524 00525 // Finally compute the number of exportable physical blocks and free blocks 00526 // 00527 Assert( u16_tmp<(G_N_BLOCKS -g_nf_first_block) ); 00528 g_n_export_blocks= (U16)( ((U32)( (U32)sub_lut_log_sz ) * 1000) / 1024); 00529 g_n_export_blocks= Align_down( g_n_export_blocks, NF_N_DEVICES); 00530 00531 g_n_free_blocks = (U16)sub_lut_log_sz - g_n_export_blocks; 00532 g_n_free_blocks -= (U16)NF_N_DEVICES*i_sub_lut; 00533 00534 if( g_n_free_blocks<=NF_LOW_N_FREE_THRESHOLD ) 00535 { 00536 while(1); // TBD 00537 } 00538 00539 Assert( g_n_free_blocks>0 ); 00540 Assert( g_n_free_blocks<(1L<<NF_SHIFT_PAGE_BYTE) ); // limit the free blocks in order to fit in 1 page 00541 00542 // Compute the number of needed sub-LUT 00543 // Affect to each management block a free block address 00544 // 00545 Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV); 00546 g_fbb_block_addr = nf_fetch_free_block(S_MNGT_DEV); 00547 nfc_erase_block( nf_block_2_page( g_fbb_block_addr ), TRUE ); 00548 g_n_sub_lut= 0; 00549 u16_tmp = g_n_export_blocks; 00550 //#error il faut positionner les index(LUT, FBB, RCV...) 00551 while(1) 00552 { 00553 Assert( g_n_sub_lut<N_SUBLUT ); 00554 g_lut_block_addr [g_n_sub_lut]=nf_fetch_free_block(S_MNGT_DEV); 00555 g_lut_block_index[g_n_sub_lut]=0; 00556 nfc_erase_block( nf_block_2_page( g_lut_block_addr [g_n_sub_lut] ), TRUE ); 00557 g_n_sub_lut++; 00558 if( u16_tmp>NF_SUBLUT_SIZE ) u16_tmp-=NF_SUBLUT_SIZE; 00559 else break; 00560 } 00561 g_last_sub_lut_log_sz=u16_tmp/NF_N_DEVICES; 00562 00563 // Build the sub-LUTs 00564 // 00565 for ( i_sub_lut=0 ; i_sub_lut<g_n_sub_lut ; ) 00566 { 00567 U8 n_sublut_in_buf = g_n_sub_lut - i_sub_lut; // Count remaining sublut to build 00568 00569 log_block_addr_max = 00570 log_block_addr_min = (U16)i_sub_lut<<(NF_SHIFT_SUBLUT_PHYS-NF_SHIFT_N_DEVICES); // first included 00571 00572 if( n_sublut_in_buf>(NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE)) ) 00573 { 00574 n_sublut_in_buf = NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE); 00575 log_block_addr_max += ((U16)n_sublut_in_buf)*g_sub_lut_log_sz; // last not included 00576 } 00577 else 00578 { 00579 log_block_addr_max += ((U16)n_sublut_in_buf-1)*g_sub_lut_log_sz +g_last_sub_lut_log_sz; // last not included 00580 } 00581 00582 nf_init_buffer(); 00583 00584 // Report affected logical blocks 00585 // 00586 u16_tmp=g_n_export_blocks/NF_N_DEVICES; // Number of logical blocks used for the mass storage 00587 00588 b_duplicate=FALSE; 00589 00590 for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00591 { 00592 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00593 00594 g_block_to_kill[i_dev]=0xFFFF; 00595 00596 for ( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ ) 00597 { 00598 nfc_read_spare_byte( g_byte, 8, nf_block_2_page(i_block) ); 00599 if(( 0xFF !=g_byte[G_OFST_BLK_STATUS ] ) // The block is bad 00600 || ( NFC_BLK_ID_DATA!=g_byte[NFC_SPARE_OFST_1_BLK_ID ] ) // or is not a data block 00601 || ( ( 0xFF ==g_byte[NFC_SPARE_OFST_6_LBA ] ) // or is not affected 00602 && ( 0xFF ==g_byte[NFC_SPARE_OFST_6_LBA+1 ] ) 00603 ) 00604 ) { 00605 continue; 00606 } 00607 00608 MSB(log_block_addr) = g_byte[NFC_SPARE_OFST_6_LBA ]; 00609 LSB(log_block_addr) = g_byte[NFC_SPARE_OFST_6_LBA+1]; 00610 00611 if( log_block_addr>=u16_tmp ) 00612 { // The LBA seems bad: it does not fit in any LUT. This happens when unplugging the player. 00613 // Block is erased. 00614 // Anyway, stay in the loop to track similar problems. 00615 nfc_erase_block( nf_block_2_page(i_block), TRUE ); 00616 status_bool=FAIL; 00617 } 00618 00619 if(( log_block_addr>=log_block_addr_min ) 00620 && ( log_block_addr< log_block_addr_max )) 00621 { 00622 U16 ofst=2*((U16)i_dev + (log_block_addr%((U16)NF_PAGE_BUFFER_SIZE/2/NF_N_DEVICES))*NF_N_DEVICES) ; 00623 if( 00624 ( 0xFF==g_page_buffer[ ofst ] ) 00625 && ( 0xFF==g_page_buffer[ ofst +1 ] ) 00626 ) 00627 { // no redundant phys blocks 00628 Assert( ( ofst +1 ) < NF_PAGE_BUFFER_SIZE ); 00629 g_page_buffer[ ofst ] = MSB(i_block); 00630 g_page_buffer[ ofst +1 ] = LSB(i_block); 00631 } 00632 else 00633 { // A duplicated logical block is detected. This happens when unplugging the player. 00634 // Anyway, stay in the loop to track any other redundant blocks, for that sub-LUT. 00635 _MEM_TYPE_SLOW_ U16 tmp_addr; 00636 MSB(tmp_addr)=g_page_buffer[ ofst ]; 00637 LSB(tmp_addr)=g_page_buffer[ ofst +1 ]; 00638 //trace("Dupl "); trace_hex32(tmp_addr); trace("-"); trace_hex32(i_block);; trace("\n\r"); 00639 00640 if(0xFFFF!=g_block_to_kill[i_dev]) 00641 { // !!! There are more than 1 duplicated block on the device. This should never happen... 00642 nfc_erase_block( nf_block_2_page(g_block_to_kill[i_dev]), TRUE ); 00643 return FAIL; 00644 } 00645 00646 b_duplicate=TRUE; 00647 g_log_block_id=log_block_addr; 00648 00649 nfc_open_page_read( 00650 nf_block_2_page(i_block) 00651 , NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3 00652 ); 00653 if( NFC_OFST_3_DATA_DST!=Nfc_rd_data_fetch_next() ) 00654 { 00655 trace("1. Src block="); trace_hex16(i_block); trace_nl(); 00656 trace("1. Dst block="); trace_hex16(tmp_addr); trace_nl(); 00657 //nfc_print_block(i_block, 0); 00658 //nfc_print_block(tmp_addr, 0); 00659 //while(1); 00660 g_block_to_kill[i_dev]=i_block; // source block 00661 g_phys_page_addr[i_dev] = nf_block_2_page( tmp_addr ); // recipient block 00662 } 00663 else 00664 { 00665 trace("2. Src block="); trace_hex16(tmp_addr); trace_nl(); 00666 trace("2. Dst block="); trace_hex16(i_block); trace_nl(); 00667 //nfc_print_block(tmp_addr, 0); 00668 //nfc_print_block(i_block, 0); 00669 //while(1); 00670 g_block_to_kill[i_dev]= tmp_addr ; // source block 00671 g_page_buffer[ ofst ]=MSB(i_block); 00672 g_page_buffer[ ofst +1 ]=LSB(i_block); 00673 g_phys_page_addr[i_dev] = nf_block_2_page( i_block ); // recipient block 00674 } 00675 } 00676 } 00677 } // for ( i_block ../.. 00678 } // for ( i_dev ../.. 00679 00680 if( b_duplicate ) 00681 { 00682 U8 i_page; 00683 U8 i_sect; 00684 00685 trace("recovery\n\r"); 00686 // Test that recovery can be done 00687 for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00688 { 00689 if( 0xFFFF==g_block_to_kill[i_dev] ) 00690 { // !Ooops... we can not recover from that case since there are duplication 00691 // only on on device 00692 for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00693 { 00694 if( 0xFFFF!=g_block_to_kill[i_dev] ) 00695 { 00696 nfc_erase_block( nf_block_2_page(g_block_to_kill[i_dev]), TRUE ); 00697 } 00698 } 00699 return FAIL; 00700 } 00701 } 00702 00703 // Initialize variable for nf_copy_tail 00704 g_curr_dev_id=0; 00705 g_last_log_sector= ((U32)g_log_block_id) << S_SHIFT_LOG_BLOCK_SECTOR; 00706 00707 // Look for last written sector 00708 for( i_page=0 ; i_page<SIZE_BLOCK_PAGE ; i_page++ ) 00709 { 00710 Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id); // open the current device 00711 for( i_sect=0 ; i_sect<SIZE_PAGE_SECTOR ; i_sect++ ) 00712 { 00713 nfc_open_page_read( 00714 g_phys_page_addr[g_curr_dev_id] 00715 , NF_SPARE_POS + (((U16)i_sect)*16) + NFC_SPARE_OFST_6_LBA 00716 ); 00717 if(( 0xFF==Nfc_rd_data_fetch_next() ) 00718 && ( 0xFF==Nfc_rd_data_fetch_next() )) 00719 goto recovery_exit; 00720 else 00721 { 00722 g_last_log_sector++; 00723 trace("g_last_log_sector="); trace_hex32(g_last_log_sector); trace_nl(); 00724 } 00725 } 00726 g_phys_page_addr[g_curr_dev_id]++; // update the current physical page of the current device 00727 g_curr_dev_id++; // update the current device 00728 if( g_curr_dev_id==NF_N_DEVICES ) { g_curr_dev_id=0; } 00729 trace("g_curr_dev_id="); trace_hex(g_curr_dev_id); trace_nl(); 00730 trace("g_phys_page_addr="); trace_hex32(g_phys_page_addr[g_curr_dev_id]); trace_nl(); 00731 } 00732 recovery_exit: 00733 trace("recovery stop on g_last_log_sector="); trace_hex32(g_last_log_sector); trace_nl(); 00734 trace("g_curr_dev_id="); trace_hex(g_curr_dev_id); trace_nl(); 00735 trace("g_phys_page_addr="); trace_hex32(g_phys_page_addr[g_curr_dev_id]); trace_nl(); 00736 //while(1); 00737 nf_copy_tail(); 00738 return FAIL; 00739 } 00740 00741 // At least one redundant have been found: the LUT must be rebuilt since the fetch of free block 00742 // may not have seen that affected block (redundant) are in fact free. 00743 if( PASS!=status_bool ) { return FAIL; } 00744 00745 // Affect a free physical block to the logical block 00746 // 00747 for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00748 { 00749 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00750 00751 for(u16_tmp=0 00752 ; u16_tmp<(log_block_addr_max-log_block_addr_min) 00753 ; u16_tmp++ ) 00754 { 00755 U16 ofst=2*((U16)i_dev + u16_tmp*NF_N_DEVICES); 00756 if(( 0xFF==g_page_buffer[ofst ] ) 00757 && ( 0xFF==g_page_buffer[ofst+1] )) 00758 { 00759 i_block=nf_fetch_free_block(i_dev); 00760 Assert( ofst+1<NF_PAGE_BUFFER_SIZE); 00761 g_page_buffer[ofst ] = MSB(i_block); 00762 g_page_buffer[ofst+1] = LSB(i_block); 00763 } 00764 } 00765 } // for ( i_dev ../.. 00766 00767 // Each sub-LUT will fit in a physical page and will be of the same size 00768 // except the last one which contains less 00769 // 00770 for( ; n_sublut_in_buf!=0 ; n_sublut_in_buf--, i_sub_lut++ ) 00771 { 00772 sub_lut_log_sz= ( i_sub_lut==(g_n_sub_lut-1) ) ? g_last_sub_lut_log_sz : g_sub_lut_log_sz ; 00773 00774 // Write the sub-LUT in the page 00775 // 00776 status_bool = nf_write_lut(i_sub_lut%(NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE)), i_sub_lut, sub_lut_log_sz); 00777 if ( PASS!=status_bool ) 00778 { 00779 nfc_mark_bad_block( nf_block_2_page( g_lut_block_addr[i_sub_lut] ) ); 00780 return FAIL; 00781 } 00782 } 00783 } 00784 00785 //#error: si recovery, il faut effacer la lut en question. Il faut donc la reconstruire. 00786 // Pour cela, il faut trouver des blocs libres. 00787 // 1ere methode: effacer aussi le free-blocks block et le reconstruire, ainsi que la sub-LUT 00788 // 2eme methode: marquer les free block pour les reconnaitre et reconstruire la sub lut 00789 00790 // Build the free-blocks block 00791 // First, fill the internal buffer with the free blocks 00792 // 00793 for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00794 { 00795 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00796 00797 for ( u16_tmp=0 ; u16_tmp<(g_n_free_blocks/NF_N_DEVICES) ; u16_tmp++ ) 00798 { 00799 // This define is better than using a variable that holds the expression... 00800 #define OFST (2*(i_dev + u16_tmp*NF_N_DEVICES)) 00801 i_block=nf_fetch_free_block(i_dev); 00802 nfc_erase_block( nf_block_2_page(i_block), TRUE ); 00803 Assert( OFST <NF_PAGE_BUFFER_SIZE); 00804 Assert( OFST +1<NF_PAGE_BUFFER_SIZE); 00805 Assert( i_block>=g_nf_first_block ); 00806 Assert( i_block< G_N_BLOCKS ); 00807 g_page_buffer[OFST ] = MSB(i_block); 00808 g_page_buffer[OFST +1] = LSB(i_block); 00809 #undef OFST 00810 } 00811 } 00812 00813 // Then write the buffer in the free-blocks block 00814 // Note that the list of free-blocks holds on one page only; the 00815 // algo is thus made for both 512B and 2kB pages. 00816 // 00817 g_fbb_block_index=0; 00818 status_bool = nf_write_fbb(); 00819 if ( PASS!=status_bool ) 00820 { 00821 nfc_mark_bad_block( nf_block_2_page( g_fbb_block_addr ) ); 00822 return FAIL; 00823 } 00824 00825 //#error Effacer les free blocks !!!!!! 00826 //#error il faut determiner s_lut_index[all] pour les sub-lut existantes 00827 //#error si il existe un bloc de recovery, alors la lut associée n'est plus valide 00828 //#error rendre parametrable la taille du buffer (actuellement 2k). Si <512 et no partial prog: fatal error 00829 00830 //nf_init_buffer(); // Cleanup the buffer 00831 return PASS; 00832 }
| static Bool is_nf_invalid | ( | void | ) | [static] |
Test if the memory needs to be rebuilt.
| recovery_params | internal structure used to hold the last pointer position |
Definition at line 441 of file nf_unusual.c.
References FALSE, NFC_OFST_4_FBB_DRIVER_RELEASE, and TRUE.
Referenced by nf_verify_resume().
00442 { 00443 if( // If we do not find everything 00444 ( FALSE==g_is_found_lut ) 00445 || ( FALSE==g_is_found_fbb ) 00446 ) { 00447 g_fatal=TRUE; 00448 } 00449 00450 // Test LUT coherency 00451 // 00452 if(( TRUE ==g_is_found_lut ) 00453 && ( g_n_sub_lut!=g_n_real_sub_lut )) 00454 { 00455 g_fatal=TRUE; 00456 } 00457 00458 //#error se proteger si le nombre de devices changent alors que lut, recovery et free blocs sont déjà créés sur le bloc MNGT. 00459 if ( (U16)-1==g_n_export_blocks ) { g_fatal=TRUE; } 00460 if ( 0==g_n_export_blocks ) { g_fatal=TRUE; } 00461 if ( (U16)-1==g_last_sub_lut_log_sz ) { g_fatal=TRUE; } 00462 00463 // Test Nand Flash driver release. 00464 // 00465 if ( s_nfd_rev!=NFC_OFST_4_FBB_DRIVER_RELEASE ) 00466 { 00467 g_fatal=TRUE; 00468 } 00469 00470 return g_fatal; 00471 }
Returns the first free block seen, scanning downstream.
It uses g_curr_block_addr (current block address of each device).
| i_dev | device number on which we look for a free block |
Definition at line 844 of file nf_unusual.c.
References Assert, FALSE, G_OFST_BLK_STATUS, nf_block_2_page(), NFC_BLK_ID_DATA, NFC_BLK_ID_FBB, NFC_BLK_ID_SUBLUT, nfc_erase_block(), nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_6_LBA, and TRUE.
Referenced by nf_rebuild().
00845 { 00846 00847 U16 block_addr= g_curr_block_addr[i_dev]; 00848 00849 while ( block_addr>=g_nf_first_block ) 00850 { 00851 nfc_read_spare_byte( g_byte, 8, nf_block_2_page( block_addr ) ); 00852 if(( 0xFF ==g_byte[G_OFST_BLK_STATUS ] ) // the block is valid 00853 && ( NFC_BLK_ID_DATA==g_byte[NFC_SPARE_OFST_1_BLK_ID ] ) // the block is a data block 00854 && ( 0xFF ==g_byte[NFC_SPARE_OFST_6_LBA ] ) // and is not affected 00855 && ( 0xFF ==g_byte[NFC_SPARE_OFST_6_LBA+1 ] )) 00856 { 00857 // Since we rebuild the flash, we should not see any of these blocks 00858 // 00859 Assert( NFC_BLK_ID_SUBLUT!=g_byte[NFC_SPARE_OFST_1_BLK_ID] ); 00860 Assert( NFC_BLK_ID_FBB !=g_byte[NFC_SPARE_OFST_1_BLK_ID] ); 00861 00862 // Find a free and valid block addr. Store the current position 00863 // 00864 g_curr_block_addr[i_dev] = block_addr-1; 00865 return block_addr; 00866 } 00867 block_addr-=1 ; 00868 } 00869 // This situation is dramatic: it should never happen ! 00870 // Force Rebuild on next startup 00871 nfc_erase_block( nf_block_2_page( g_fbb_block_addr ), TRUE ); 00872 while(1); 00873 Assert( FALSE ) ; // Not enough free blocks: fatal error! 00874 }
Refines the position of the 'block' index according to a particular pattern.
This allow to find exactely where are stored the last sub-LUT, Free_blocks or Recovery entry. The index is roughly initialized at the beginning of the block that holds the 'pattern' at the location 1 of the spare zone. The function parses the block until the pattern is no more found.
| block_addr | physical block address | |
| inc | increment | |
| pattern | pattern which is scanned |
Definition at line 891 of file nf_unusual.c.
References _MEM_TYPE_SLOW_, Assert, G_SHIFT_BLOCK_PAGE, nf_block_2_page(), NF_SPARE_POS, nfc_open_page_read(), Nfc_rd_data, NFC_SPARE_OFST_1_BLK_ID, and SIZE_BLOCK_PAGE.
Referenced by nf_scan().
00895 { 00896 _MEM_TYPE_SLOW_ U8 u8_tmp; 00897 _MEM_TYPE_SLOW_ U8 val=0; 00898 do 00899 { 00900 val+= inc; // Assume that the pattern has already be seen previously 00901 if( val>=SIZE_BLOCK_PAGE ) 00902 { break; } 00903 nfc_open_page_read( 00904 nf_block_2_page(block_addr) + val 00905 , NF_SPARE_POS+NFC_SPARE_OFST_1_BLK_ID 00906 ); 00907 u8_tmp = Nfc_rd_data(); 00908 } while( pattern==u8_tmp ); 00909 val-= inc; // come back to last valid entry 00910 Assert( val<(1<<G_SHIFT_BLOCK_PAGE) ); // The offset shall not be outside the block 00911 return val; 00912 }
| void nf_init | ( | void | ) |
Initializes the nand flash memory driver.
The device identification is performed to initialize the driver accordingly
| none |
Definition at line 148 of file nf_unusual.c.
References FALSE, g_n_row_cycles, g_ofst_blk_status, G_SHIFT_BLOCK_PAGE, g_shift_block_page, G_SHIFT_PAGE_BYTE, g_shift_page_byte, Is_nf_2k, Is_nf_512, NF_SHIFT_BLOCK_PAGE, NF_SHIFT_PAGE_BYTE, NF_SHIFT_SECTOR_BYTE, s_shift_log_block_sector, s_shift_log_page_sector, S_SHIFT_SECTOR_BYTE, and s_shift_sector_byte.
00149 { 00150 g_nf_init=FALSE; 00151 // s_pending_write=FALSE; 00152 00153 #if (NF_GENERIC_DRIVER==TRUE) 00154 #error Check this init... 00155 g_n_zones = NF_N_ZONES; 00156 g_n_blocks = NF_N_BLOCKS; 00157 g_shift_block_page = NF_SHIFT_BLOCK_PAGE; 00158 g_shift_page_byte = NF_SHIFT_PAGE_BYTE; 00159 s_shift_sector_byte = NF_SHIFT_SECTOR_BYTE; 00160 g_n_row_cycles = NF_N_ROW_CYCLES; 00161 00162 if ( Is_nf_2k() ) // 2KB pages 00163 { 00164 g_ofst_blk_status = 0; 00165 } 00166 if ( Is_nf_512() ) // 512B pages 00167 { 00168 g_ofst_blk_status = 5; 00169 } 00170 00171 s_shift_log_page_sector = G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE + NF_SHIFT_N_DEVICES; 00172 s_shift_log_block_sector = s_shift_log_page_sector + G_SHIFT_BLOCK_PAGE; 00173 #endif 00174 00175 g_cache_lut.ctrl.valid = FALSE; g_cache_lut.ctrl.dirty = FALSE; 00176 g_cache_fbb.ctrl.valid = FALSE; g_cache_fbb.ctrl.dirty = FALSE; 00177 g_last_log_sector= 0xFFFFFFFF; 00178 }
| Status_bool nf_verify_resume | ( | void | ) |
Ensure that the memory is in a good state before starting to use it.
The function will scan the memory, test if the memory is valid, clean it if it has to and rebuild all the management blocks. This function shall be called prior to any use of the memory after a power-up.
| none |
Definition at line 193 of file nf_unusual.c.
References FAIL, FALSE, is_nf_invalid(), Nf_check_fbb, Nf_check_lut, nf_cleanup_memory(), nf_rebuild(), nf_scan(), PASS, TRUE, and ut_nfc_erase_all().
00194 { 00195 U8 u8_nb_loop; 00196 Bool status_bool; 00197 00198 00199 #if (ERASING_ALL==ENABLE) 00200 ut_nfc_erase_all(); 00201 #endif 00202 00203 status_bool = nf_scan(); 00204 00205 if(( PASS!=status_bool ) 00206 || ( is_nf_invalid() ) // The NF is not cleanly built 00207 ) { 00208 // The NF seems not cleanly built, or not built at all. 00209 // 00210 u8_nb_loop = 0; 00211 while( 1 ) 00212 { 00213 u8_nb_loop++; 00214 if( u8_nb_loop > 2 ) 00215 { 00216 status_bool=FAIL; 00217 break; // Error NF access or control 00218 } 00219 nf_cleanup_memory(); 00220 if( PASS != nf_scan() ) 00221 continue; 00222 if( PASS != nf_rebuild() ) 00223 continue; 00224 status_bool = PASS; 00225 break; 00226 } 00227 } 00228 if (status_bool==PASS) 00229 { 00230 g_nf_init = TRUE; 00231 Nf_check_lut(); 00232 Nf_check_fbb( FALSE ); 00233 } 00234 00235 return status_bool; 00236 }
| void nf_cleanup_memory | ( | void | ) |
Cleanup the memory by erasing all the management blocks.
The sub-LUT blocks, the recovery block and the free-blocks block will be erased on any devices.
| none |
Definition at line 247 of file nf_unusual.c.
References FAIL, G_N_BLOCKS, nf_block_2_page(), NF_N_DEVICES, NF_SPARE_POS, NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_FBB, NFC_BLK_ID_SUBLUT, nfc_check_status(), nfc_erase_block(), nfc_mark_bad_block(), nfc_open_page_read(), Nfc_rd_data, Nfc_rd_data_fetch_next, and TRUE.
00248 { 00249 U8 i_dev =0; 00250 U16 i_block=0; 00251 U8 block_valid; 00252 U8 block_id; 00253 00254 // Scan all the devices and looks for: 00255 // - the sub-LUT 00256 // - the recovery block 00257 // - the free-blocks block 00258 // 00259 for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ ) 00260 { 00261 // Select the devices 00262 // 00263 Nfc_action(NFC_ACT_DEV_SELECT, i_dev); 00264 00265 for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ ) 00266 { 00267 00268 nfc_open_page_read( nf_block_2_page(i_block), NF_SPARE_POS); 00269 block_valid = Nfc_rd_data_fetch_next(); 00270 block_id = Nfc_rd_data() ; 00271 00272 if ( block_valid!=0xFF ) 00273 { 00274 continue; // The block is bad 00275 } 00276 00277 if(( NFC_BLK_ID_SUBLUT==block_id ) 00278 || ( NFC_BLK_ID_FBB ==block_id )) 00279 { 00280 nfc_erase_block( nf_block_2_page(i_block), TRUE ) ; 00281 if ( FAIL==nfc_check_status() ) 00282 { 00283 nfc_mark_bad_block( nf_block_2_page(i_block) ); 00284 } 00285 } 00286 } // for( i_block... 00287 } // for( i_dev... 00288 } // nf_cleanup_memory
| _MEM_TYPE_SLOW_ U16 g_n_blocks |
| _MEM_TYPE_SLOW_ U8 g_page_buffer[((2048)+(2048)/32)] |
| _MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz |
| _MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz |
Definition at line 79 of file nf_unusual.c.
Definition at line 80 of file nf_unusual.c.
| _MEM_TYPE_SLOW_ U8 g_n_real_sub_lut |
Definition at line 82 of file nf_unusual.c.
| _MEM_TYPE_SLOW_ U16 g_curr_block_addr[NF_N_DEVICES] |
Definition at line 83 of file nf_unusual.c.
Definition at line 84 of file nf_unusual.c.
| _MEM_TYPE_SLOW_ U8 g_n_sub_lut |
| _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))] |
Definition at line 88 of file nf_unusual.c.
| _MEM_TYPE_SLOW_ U16 g_nf_first_block |
_MEM_TYPE_SLOW_ U8 s_n_quarantine_blocks[NF_N_DEVICES] [static] |
Definition at line 90 of file nf_unusual.c.
_MEM_TYPE_SLOW_ U16 s_n_invalid_blocks[NF_N_DEVICES] [static] |
Definition at line 91 of file nf_unusual.c.
| _MEM_TYPE_SLOW_ U16 g_n_export_blocks |
| _MEM_TYPE_SLOW_ U16 g_n_free_blocks |
| _MEM_TYPE_SLOW_ U16 g_fbb_block_addr |
| _MEM_TYPE_SLOW_ U8 g_fbb_block_index |
| _MEM_TYPE_SLOW_ U32 g_last_log_sector |
| _MEM_TYPE_SLOW_ U32 g_copy_src |
| _MEM_TYPE_SLOW_ U16 g_block_to_kill[NF_N_DEVICES] |
| _MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES] |
| _MEM_TYPE_FAST_ U8 g_curr_dev_id |
| _MEM_TYPE_MEDFAST_ U16 g_log_block_id |
| _MEM_TYPE_SLOW_ Cache_lut g_cache_lut |
| _MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb |
1.5.3