📄 sm_media.c
字号:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_write_sector() reentrant
{
uint8 i ;
uint8* buf ;
trace4(0, sm_media, 0, "+sm_media_write_sector() zone:%d WR_PHY:%d log:%d page:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page) ;
if( (g_addr_wr_phy_blk == k_block_free) )
return k_media_err_illegal_lba ;
buf = _media_data(sector_buffer) ;
nand_wr_va2pa() ;
// issue start-of-write command
sm_wr_cmd_begin(k_sm_write_data);
// set the address
_media_set_write_addr() ;
// send the even page
sm_pio_wr_buf(buf);
// send even page extra data
for (i=0x00;i<((_mcu_register_rd(x_media_sts)&kbm_media_sts_sm_256_page)?0x08:0x10);i++)
_sm_data_wr(x_sm_redt_data[i]);
// issue the end-of-write command
#if 1
trace0(0, sm, 0, "cmd: write") ;
sm_set_wr_cmd(k_sm_write);
#else
if(g_addr_page==(_media_data(pages_per_block)-1))
{
trace0(0, sm, 0, "cmd: write") ;
sm_set_wr_cmd(k_sm_write);
}
else
{
trace0(0, sm, 0, "cmd: write cache");
sm_set_wr_cmd(k_nand_cmd_write_cache);
}
#endif
if (sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
{
trace0(0, sm_media, 0, "error waiting for sm to program") ;
sm_reset_device();
return k_error ;
}
// for odd pages (on devices that use 'em) do it again.
if (( _mcu_register_rd(x_media_sts)&kbm_media_sts_sm_256_page))
{
sm_wr_cmd_begin(k_sm_write_data);
_media_set_write_addr() ;
sm_pio_wr_buf(buf+0x0100);
for (i=0x08;i<k_sm_redt_buffer_sz;i++)
_sm_data_wr(x_sm_redt_data[i]);
sm_set_wr_cmd(k_sm_write);
if (sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
{
sm_reset_device();
return k_error ;
}
}
_sm_hw_set_wr_standby();
_sm_hw_set_rd_standby();
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// sm_media_copy_sector()
//
// Declaration:
// t_result sm_media_copy_sector() reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_copy_sector() reentrant
{
uint8 err_byte;
t_bool retry;
uint8 data_status;
t_result result;
trace4(0, sm_media, 0, "+sm_media_copy_sector() zone:%d SRC_BLK:%d DEST_BLK:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page) ;
if( (g_addr_wr_phy_blk == k_block_free) )
{
trace0(0, sm_media, 0, " error. invalid wr_phy_block: 0xffff") ;
return k_media_err_illegal_lba ;
}
nand_rd_va2pa() ;
// read retries and data status
retry=k_false;
// data status is good
data_status=0xff;
result=k_success;
do
{
// TRACE0(164, sm_media, 0, "reading sector mode: 512+16") ;
sm_rd_cmd_begin(k_sm_read) ;
_media_set_read_addr() ;
_mcu_register_wr(x_smc_stat, (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));
_mcu_register_clr_bits(x_smc_stat_msk, (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));
_mcu_register_set_bits(sm_mode_ctl, kbm_sm_mode_ecc_blk_xfer_en) ;
x_isr0 = kbm_isr0_fmc_irq ;
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_ramwr_tog));
_mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_wrtog_valid|kbm_ep2_ctl_dir|kbm_ep2_ctl_enable);
// 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))
{
sm_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/
sm_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));
_mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_rdtog_valid|kbm_ep2_ctl_enable);
// _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
// 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
#if 1
trace0(0, sm, 0, "cmd: write") ;
sm_set_wr_cmd(k_sm_write);
#else
if(g_addr_page==(_media_data(pages_per_block)-1))
{
trace0(0, sm, 0, "cmd: write") ;
sm_set_wr_cmd(k_sm_write);
}
else
{
trace0(0, sm, 0, "cmd: write cache");
sm_set_wr_cmd(k_nand_cmd_write_cache);
}
#endif
if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
{
sm_reset_device();
trace0(0, sm, 0, "error writing sector for copy") ;
return k_media_copy_error_dst ;
}
if (k_success != sm_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)
{
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 (bit_count16(addr1^addr2)!=0x01)
{
// 0, or 2+ bit difference.
trace2(0, sm_media, 0, "inconsistant log_blk binding: addr1:%04x addr2:%04x", addr1, addr2) ;
return k_error ;
}
// 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, "1-bit error in block addr2. using block addr 1 binding. phy_blk:%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, "1-bit error in block addr1. using block addr 2 binding. phy_blk:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -