⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_media.c

📁 U盘控制器USB97C223的固件代码,对2kPAGE NAND FLASH 有很好的支持.
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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 + -