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