📄 sm_media.c
字号:
x_imr0 &= ~kbm_isr0_fmc_irq ;
// set direction - in
_mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
// enable buffer a (wrtog_valid=1, ramwr_tog=0) ;
// _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_wrtog_valid) ;
_mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_wrtog_valid|(_mcu_register_rd(x_ep2_ctl) & ~kbm_ep2_ctl_ramrd_tog));
// set fmc ctl reg - 1 sector
_mcu_register_wr(x_fmc_cnt3, 0x00) ;
_mcu_register_wr(x_fmc_cnt2, 0x00) ;
_mcu_register_wr(x_fmc_cnt1, 0x02) ;
_mcu_register_wr(x_fmc_cnt0, 0x00) ;
thread_set_timer(1000) ;
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
{
nand_cmd_reset_device();
return k_error ;
}
// enable blk xfer
_mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
nand_wr_va2pa() ;
// bad bad bad form.... do a while loop
while(_mcu_register_rd( x_fmc_ctl)&kbm_fmc_ctl_blk_xfer_en)
{
if(thread_got_sync(kbm_sync_timer) )
{
trace0(0, sm_media, 0, "copy: timeout trying to read sector. aborting") ;
return k_error ;
}
}
err_byte = _mcu_register_rd(x_smc_stat);
trace1(0, sm, 0, "copy smc_stat:%02x", (_mcu_register_rd(x_smc_stat))) ;
if (err_byte&(kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b|kbm_smc_stat_ecc_err_c_a|kbm_smc_stat_ecc_err_c_b))
{
if(err_byte&(kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b))
{
if(retry)
{
trace0(0, sm, 0, "copy: double-bit error: retry failed. block has gone bad.") ;
result=k_media_copy_error_src;
data_status=0x00;
break;
}
else
{
trace0(0, sm, 0, "copy: double-bit error: retrying read...") ;
result=k_media_copy_error_src;
data_status=0x00;
retry=k_true;
// reverse data flow direction to prevent host data from sneaking through
_mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
}
}
else
{
retry=k_false;
}
if(err_byte&kbm_smc_stat_ecc_err_c_a)
{
trace2(0, sm, 0, "copy: correctable 1-bit error addr:%d.%d", ecc_a_add_h, (ecc_a_add_l&0x07)) ;
sm_correct_sram_bit(4, ecc_a_add_h, (ecc_a_add_l&0x07));
_mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_a);
}
if(err_byte&kbm_smc_stat_ecc_err_c_b)
{
trace2(0, sm, 0, "copy: correctable 1-bit error addr:%d.%d", (((uint16)ecc_b_add_h)+0x100), (ecc_b_add_l&0x07)) ;
sm_correct_sram_bit(4, (ecc_b_add_h+0x100), (ecc_b_add_l&0x07)) ;
_mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_b);
}
}
else
{
retry=k_false;
}
}while(retry);
if(map_log_blk_has_bad_data())
{
trace0(0, sm, 0, "block has bad data somewhere. read src extra data to correctly copy over 'data status' flag");
data_status= (sm_check_data_status(g_addr_page, 1)?0x00:data_status);
// reset chip to get back to read/
nand_cmd_reset_device();
}
// bind current logical block to new physical block
sm_media_bind_log2phy() ;
// set the data status (0x00=> data bad, 0xff=>no errors or 1-bit error corrected
XBYTE[0x3664]=x_sm_redt_data[k_ix_redt_data_status]=data_status;
trace1(0, sm, 0, "copy: page data status:%02x", data_status);
// reverse data flow direction
_mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
x_smc_stat = kbm_smc_stat_rdy ;
_sm_set_wr_cmd(k_sm_write_data);
_media_set_write_addr() ;
sm_mode_ctl |= kbm_sm_mode_ecc_blk_xfer_en;
_sm_hw_ecc_wr_start() ;
trace0(0, sm, 0, "ecc_en on") ;
// set fmc ctl reg - 1 sector
_mcu_register_wr(x_fmc_cnt3, 0x00) ;
_mcu_register_wr(x_fmc_cnt2, 0x00) ;
_mcu_register_wr(x_fmc_cnt1, 0x02) ;
_mcu_register_wr(x_fmc_cnt0, 0x00) ;
// enable blk xfer
_mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
// point the rd toggle & count to buffer a (rd toggles point the dest (SIE or DBUF) where to read)
_mcu_register_wr( x_ramrdbc_a1, 0x02) ;
_mcu_register_wr( x_ramrdbc_a2, 0x00) ;
// aim fmc at buffer a
// _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_rdtog_valid) ;
_mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_rdtog_valid |(_mcu_register_rd(x_ep2_ctl) & ~kbm_ep2_ctl_ramrd_tog));
// bad bad bad form.... do a while loop
while(_mcu_register_rd( x_fmc_ctl)&kbm_fmc_ctl_blk_xfer_en)
{
if(thread_got_sync(kbm_sync_timer) )
{
trace0(0, sm_media, 0, "timeout trying to write sector. aborting") ;
return k_media_copy_error_dst ;
}
}
_sm_hw_ecc_wr_stop() ;
sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
trace0(0, sm, 0, "ecc_en off") ;
// send the write command to program the data to the card
trace0(0, sm, 0, "cmd: write") ;
_sm_set_wr_cmd(k_sm_write);
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
{
nand_cmd_reset_device();
trace0(0, sm, 0, "error writing sector for copy") ;
return k_media_copy_error_dst ;
}
if (k_success != nand_cmd_check_status())
{
trace0(0, sm, 0, "sm_write_end_split - write fault") ;
return k_media_copy_error_dst ;
}
_sm_hw_set_wr_standby();
_sm_hw_set_rd_standby();
return result;
}
//------------------------------------------------------------------------------
//+-----------------------------------------------------------------------------
// Name:
// sm_media_phy2log()
//
// Declaration:
// t_result sm_get_lba(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_phy2log(void) reentrant
{
uint16 addr1;
uint16 addr2;
trace0(0, sm_media, 0, "sm_media_phy2log()") ;
addr1=_uint16( x_sm_redt_data[k_ix_redt_lba1_hi],x_sm_redt_data[k_ix_redt_lba1_lo]) ;
addr2=_uint16( x_sm_redt_data[k_ix_redt_lba2_hi],x_sm_redt_data[k_ix_redt_lba2_lo]) ;
if (addr1==addr2)
{
// addresses are equal
if ((addr1 &0xF000)==0x1000)
{
g_addr_log_blk=(addr1 &0x0FFF)/2;
trace2(0, sm_media, 0, "RD_PHY:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
return k_success;
}
}
if (bit_count16(addr1^addr2)!=0x01)
{
// more than 1 bit error
trace2(0, sm_media, 0, "inconsistant log_blk binding: addr1:%04x addr2:%04x", addr1, addr2) ;
return k_error ;
}
// only 1 bit error
if ((addr1 &0xF000)==0x1000)
{
if (0 == (bit_count16(addr1) &0x01))
{
g_addr_log_blk=(addr1 &0x0FFF)/2;
trace2(0, sm_media, 0, "RD_PHY:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
return k_success;
}
}
if ((addr2 &0xF000)==0x1000)
{
if (0 == (bit_count16(addr2) &0x01))
{
g_addr_log_blk=(addr2 &0x0FFF)/2;
trace2(0, sm_media, 0, "phyblock:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
return k_success;
}
}
trace2(0, sm_media, 0, "inconsistant log_blk binding: addr1:%04x addr2:%04x", addr1, addr2) ;
return k_error ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_bind_log2phy()
//
// Declaration:
// t_result sm_media_bind_log2phy(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_bind_log2phy(void) reentrant
{
uint16 addr;
trace1(0, sm_media, 0, "+sm_media_bind_log2phy(log_blk:%d)", g_addr_log_blk) ;
x_sm_redt_data[k_ix_redt_block_status]=0xFF;
x_sm_redt_data[k_ix_redt_data_status] =0xFF;
addr=g_addr_log_blk*2+0x1000;
if ((bit_count16(addr)%2)) addr++;
x_sm_redt_data[k_ix_redt_lba1_hi]=x_sm_redt_data[k_ix_redt_lba2_hi]= _h(addr) ;
x_sm_redt_data[k_ix_redt_lba1_lo]=x_sm_redt_data[k_ix_redt_lba2_lo]= _l(addr) ;
// bind the smc buffer too... just to keep 'em all the same
sm_synch_hw_buff_to_redt_buf() ;
// note.. this binding is not set until the data is written! it's only in the
// redundant (extra) data section
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_map_set_phyblock_failed()
//
// Declaration:
// t_result sm_map_set_phyblock_failed(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_set_phyblock_failed(void) reentrant
{
uint8 page;
uint8 i ;
page=g_addr_page ;
trace0(0, sm_media, 0, "sm_media_set_phyblock_failed()...") ;
// mark the block bad in the x_sm_redt_data data buffer
for (i=0; i<k_sm_redt_buffer_sz; i++)
x_sm_redt_data[i]=(uint8)((i==k_ix_redt_block_status)?0xF0:0xFF);
// write the x_sm_redt_data data buffer to all sectors in the block
for (g_addr_page=0;
g_addr_page<_media_data(pages_per_block) ;
g_addr_page++)
{
sm_media_write_extra_data();
}
g_addr_page=page;
trace2(0, sm_media, 0, "phy block %d:%d marked bad", g_addr_zone, g_addr_wr_phy_blk);
return k_success ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_is_phyblock_ok()
//
// Declaration:
// t_bool sm_media_is_phyblock_ok(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// TBD
//------------------------------------------------------------------------------
t_result sm_media_is_phyblock_ok(void) reentrant
{
uint8 blk_status = x_sm_redt_data[k_ix_redt_block_status] ;
trace0(0, sm_media, 0, "sm_media_is_phyblock_ok()") ;
if (blk_status==0xFF)
{
trace0(0, sm_media, 0, "sm_media_is_phyblock_ok() - Y") ;
return k_true ;
}
// sm_dbg_dump_redt_data();
if (blk_status==0x00)
{
trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - N. block status: %02x. block marked 'bad'", blk_status) ;
return k_false ;
}
if (bit_count8(blk_status)<7)
{
trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - N. block status: %02x. too many errors. bit_count8(blk) < 7) could try to reclaim?", blk_status) ;
return k_false ;
}
// if the status was not 0xff, but has a bit count of 7, then there is a
// 1-bit error, off from being 0xff, therefor it's considered to be "good"
trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - Y. block status: %02x, bit count of 7", blk_status) ;
return k_true ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_is_phyblock_blank()
//
// Declaration:
// t_bool sm_is_data_blank(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_is_phyblock_blank (void) reentrant
{
uint8 i;
for (i=0; i<k_sm_redt_buffer_sz; i++)
if (x_sm_redt_data[i]!=0xFF)
{
trace0(0, sm, 0, "sm_media_is_phyblock_blank(): N") ;
return k_false ;
}
trace0(0, sm, 0, "sm_media_is_phyblock_blank(): Y") ;
return k_true ;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_seek_cis()
//
// Declaration:
// t_result sm_media_seek_cis(void) reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_seek_cis(void) reentrant
{
g_addr_zone=0;
g_addr_page=0;
trace0(0, sm_media, 0, "sm_media_seek_cis()") ;
for ( g_addr_rd_phy_blk=0;
g_addr_rd_phy_blk<(_media_data(physical_blocks_per_zone)-_media_data(logical_blocks_per_zone)-1);
g_addr_rd_phy_blk++)
{
if (k_success != sm_media_read_extra_data())
{
trace0(0, sm_media, 0, "error - could not read extra data") ;
sm_soft_reset();
return( k_error);
}
if (sm_media_is_phyblock_ok())
break;
}
if (g_addr_rd_phy_blk==(_media_data(physical_blocks_per_zone)-_media_data(logical_blocks_per_zone)-1))
{
trace0(0, sm_media, 0, "error - valid cis block not found.") ;
sm_soft_reset();
return k_error ;
}
while (g_addr_page<k_sm_max_cis_sect)
{
if (g_addr_page)
{
if (k_success != sm_media_read_extra_data())
{
trace0(0, sm_media, 0, "error - could not read extra data (2)") ;
sm_soft_reset();
return k_error ;
}
}
if (sm_redt_is_data_valid())
{
// redundant data reports data is good.
_media_data(sector_buffer) = g_sector_buffer ;
if ( k_success != sm_media_read_sector())
{
trace1(0, sm_media, 0, "page %d read failure. cis not found.", g_addr_page) ;
sm_soft_reset();
return k_error ;
}
if ( k_success != sm_media_validate_sector(g_sector_buffer) )
{
trace1(0, sm_media, 0, "page %d data invalid", g_addr_page) ;
sm_soft_reset();
return k_error ;
}
if ( k_success != sm_validate_cis(g_sector_buffer))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -