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

📄 nand.c

📁 U盘控制器USB97C223的固件代码,对2kPAGE NAND FLASH 有很好的支持.
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Purpose:
//   Read data from sm media
//
// Arguments:
//   None.
//   Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
//   No return value.
//   However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
//     k_command_passed - command completed.
//     k_command_failed - an error occurred.
//
// Notes:
//   This is the start STATE of the dfa_ata_read DFA.
//   It overrides dfa_lun_read.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void nand_dfa_read(void) reentrant
{
  trace0(0, nand, 0, "nand_dfa_read()");
  _fmc_set_options(0);
  _fmc_set_timeout(10000);
  _fmc_set_callback(nand_read_begin_xfer, sm_read_end_xfer,
                    nand_read_begin_split, nand_read_end_first_split,
                    fmc_dflt_callback, fmc_dflt_callback, sm_read_end_burst);

#ifdef k_enable_write_caching
  // flush write cache
  if (_media_data(options)&kbm_media_data_opt_write_cache)
    map_write_cache_flush_all() ;
#endif

  dfa_lun_read();
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------


//+-----------------------------------------------------------------------------
// Name:
//   nand_write_begin_first_split
//
// Declaration:
//   t_result nand_write_begin_first_split(void);
//
// Purpose:
//   Issue the write command to the smart media device.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result nand_write_begin_first_split() reentrant
{
  trace0(0, nand, 1, "nand_write_begin_first_split()");
  // compute phy addresses in case this is the first sector
  nand_select_card() ;
  nand_wr_va2pa() ;
  nand_rd_va2pa() ;
  
  if(k_ix_media_nand==g_active_media)
  {
    g_fmc_begin_split_callback = (t_fmc_callback) sm_write_begin_split;
    // $$$ old n busted
    // sm_set_write_mode_page_data();
    // $$$ new hotness
    sm_rd_cmd_begin(k_sm_reset_chip); 
    sm_wait_rdy_with_timeout(k_sm_busy_reset_timeout);
  }
  else
  {
    g_fmc_begin_split_callback = (t_fmc_callback) n2k_write_begin_split;

    trace2(0, n2k, 0, "beginning split at page:%d segment:%d", g_addr_page, g_addr_segment) ;
    // check to see if we are starting in middle of a page
    if(g_addr_segment)
    {
      // pre-read the old page into chip cache
      n2k_page_read_for_copy() ;
      // write the full destination address
      n2k_page_write_cache_data() ;
      n2k_page_set_wr_offset( _n2k_data_offset( g_addr_segment ) ) ;
    }
  }
  return k_success;
}



//+-----------------------------------------------------------------------------
// Name:
//   n2k_write_begin_xfer
//
// Declaration:
//   void n2k_write_begin_xfer(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_xfer() reentrant
{
  t_result result ;
  uint16   max_split_size ;

  TRACE4(271, sm, 10, "n2k_write_begin_xfer() - start:0x%04X%04X count:0x%04X%04X" , _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(_fmc_get_lb_count_32()), _lw(_fmc_get_lb_count_32()));

  _lun_data(sensep) = &sense_write_error;

  // get virtual addr
  map_lba2addr_rd(_fmc_get_start_lb_32()) ;

  // enable the correct card
  nand_select_card() ;

  // copy head
  result = map_write_begin( _fmc_get_start_lb_32() ) ;

  // make sure we're in the right mode - fixes a bug where
  // the first burst of the first split of the xfer begins
  // on a zone that needed to be paged in...
  sm_set_write_mode_page_data();

  // precompute max split size
  max_split_size = (_media_data(pages_per_block)-g_addr_page)*_media_data(segments_per_page)-g_addr_segment ;
  _lun_data(max_lb_per_split) = _min( max_split_size, _fmc_get_lb_count_32());
  trace5(0, n2k, 10, "-----write begin xfer - zone:%d phy:%d log:%d page:%d count:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split) );

  // burst size needs to be 1, because the sm controller can't
  // handle more than 512 bytes out at a time.
  _lun_data(max_lb_per_burst) = 1;
  return result ;
}


//+-----------------------------------------------------------------------------
// Name:
//   n2k_write_begin_split
//
// Declaration:
//   t_result n2k_write_begin_split(void);
//
// Purpose:
//   Issue the write command to the smart media device.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_split() reentrant
{
  uint8 zone_before ;
  trace0(0, n2k, 1, "sm_write_begin_split()");
  trace1(0, n2k, 0, "g_addr_rd_phy_blk: %d", g_addr_rd_phy_blk) ;

  zone_before = g_addr_zone ;

  // if a new physical block, tell the mapper to go git us one.
  if (k_success != map_lba2addr_rd(_fmc_get_start_lb_32()))
    return(k_error);

  if(g_addr_zone != zone_before)
  {
    // we've crossed a boundry on a split, do a reset
    trace0(0, n2k, 0, "zone-change detected.") ;
    nand_select_card() ;
    sm_set_write_mode_page_data() ;
  }

  if(!g_addr_page)
  {
    if (k_success != map_alloc_wr_blk())
      return(k_error);
  }

  // convert virtual address zone/block/sector into page/offsets
  nand_rd_va2pa() ;
  nand_wr_va2pa() ;


  TRACE0(272, sm, 0, "ready to begin writing sectors") ;
  return k_success;
}

//+-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result n2k_write_end_split(void) reentrant
{
  trace0(0, n2k, 0, "n2k_write_end_split()") ;

  trace2(0, n2k, 0, "split ended on to page %d segment %d", g_addr_page, g_addr_segment) ;
  if( g_addr_segment )
  {
    trace0(0, n2k, 0, "last split.  need to flush current page cache") ;
    if( k_success != n2k_page_program() )
    {
      trace0(0, n2k, 0, "n2k_cache_program failed") ;
      return k_error ;
    }
    g_addr_page++;
    g_addr_segment=0;
    nand_incr_addr() ;
  }
  return sm_write_end_split() ;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_write_begin_burst
//
// Declaration:
//   t_result sm_write_begin_burst(void);
//
// Purpose:
//   Issue the write command to the smart media device.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_burst() reentrant
{
  trace5(0, n2k, 0, "n2k_write_begin_burst() - zone:%d log:%d-phy:%d page:%d seg:%d", g_addr_zone, g_addr_log_blk, g_addr_wr_phy_blk, g_addr_page, g_addr_segment) ;
  trace1(0, n2k, 0, "                        - n_lbs_this_xfer:%d", g_n_lb_this_xfer.u32) ;
  // check to see if we are starting in middle of a page
  if(!g_addr_segment)
  {
    // pre-read the old page into chip cache
    n2k_page_read_for_copy() ;
    // write data into the on-chip cache, starting at the beginning of the page
    n2k_page_write_cache_data() ;
  }

  _mcu_register_set_bits(sm_mode_ctl,kbm_sm_mode_ecc_blk_xfer_en) ;
  _sm_hw_ecc_wr_start() ;
  trace0(0, n2k, 0, "bursting") ;
  return k_success;
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_write_end_burst
//
// Declaration:
//   t_result sm_write_end_burst(void);
//
// Purpose:
//   TBD
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_end_burst(void) reentrant
{

  TRACE0(273, sm, 0, "n2k_write_end_burst()") ;
  _sm_hw_ecc_wr_stop() ;
  sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
  TRACE0(274, sm, 0, "ecc_en off") ;

  g_addr_segment++ ;

  if( g_addr_segment==_media_data(segments_per_page) )
  {
    trace0(0, n2k, 0, "last burst in the page.  program the page cache") ;
    if( k_success != n2k_page_program() )
    {
      TRACE0(275, sm, 0, "n2k_cache_program failed") ;
      return k_error ;
    }
    g_addr_page++;
    g_addr_segment=0;
    nand_incr_addr() ;
  }
  return k_success ;
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_sm_write
//
// Declaration:
//   void dfa_sm_write(void) reentrant
//
// Purpose:
//   Read data from sm media
//
// Arguments:
//   None.
//   Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
//   No return value.
//   However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
//     k_command_passed - command completed.
//     k_command_failed - an error occurred.
//
// Notes:
//   This is the start STATE of the dfa_ata_write DFA.
//   It overrides dfa_lun_write.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void nand_dfa_write(void) reentrant
{
  trace0(0, nand, 0, "nand_dfa_write()");

  // check for write protection change
  if( nand_check_wp() )
  {
    trace0(0, nand, 0, "error:  write protection state changed") ;
    __thread_return_dfa(k_error) ;
  }

  // check for write protection state
  if( _mcu_register_rd(x_media_sts)&kbm_media_sts_sm_wp)
  {
    trace0(0, nand, 0, "error:  write protection enabled") ;
    _lun_data(sensep) = &sense_media_change ;
    __thread_return_dfa(k_error) ;
  }

  _fmc_set_options(0);
  _fmc_set_timeout(10000);

  if(k_ix_media_nand == g_ix_media_nand)
  {
    trace0(0, nand, 0, "preparing for 512-byte per page writes") ;
    _fmc_set_callback(sm_write_begin_xfer, sm_write_end_xfer,
                      nand_write_begin_first_split, sm_write_end_split,
                      sm_write_begin_burst, fmc_dflt_callback, sm_write_end_burst);
  }
  else
  {
    trace0(0, n2k, 0, "preparing for 2048-byte-per-page writes") ;
    _fmc_set_callback(n2k_write_begin_xfer, sm_write_end_xfer,
                      nand_write_begin_first_split, n2k_write_end_split,
                      n2k_write_begin_burst, fmc_dflt_callback, n2k_write_end_burst);
  }
  dfa_lun_write();
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_power_dn()
//
// Declaration:
//   t_result sm_power_dn() reentrant
//
// Purpose:
//   erase all physical blocks on media card, then
//   rebuild sector mapping table
//
// Arguments:
//   none
//
// Return:
//   k_success  - on successful completion
//
// Notes:
//   currently, not a dfa
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result nand_power_dn() reentrant
{
  trace0(0, nand, 0, "nand_power_dn()") ;
  _sm_hw_set_rd_standby();
  return k_success ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -