示例#1
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Launch a copy-back session
//!
//! \param page_addr          absolute recipient page address of the block
//!
//! \pre <code>nf_init()</code> should have been called before.
//!
void nfc_copy_back_conf( U32 page_addr )
{
   nf_wait_busy();
   nf_wr_cmd(NF_RANDOM_DATA_INPUT_CMD);
   nf_wr_addr( 0 );
   nf_wr_addr( 0 );
   nf_wr_addr( LSB0(page_addr) );
   nf_wr_addr( LSB1(page_addr) );
   if ( 3==G_N_ROW_CYCLES )
   {
      nf_wr_addr( MSB1(page_addr) );
   }
   nf_wr_cmd(NF_PAGE_PROGRAM_CMD);
}
示例#2
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Prepare a copy-back session
//!
//! \param page_addr          absolute source page address of the block
//!
//! \pre <code>nf_init()</code> should have been called before.
//!
void nf_copy_back_init( U32 page_addr )
{
   nf_wait_busy();
   nf_wr_cmd(NF_READ_CMD);
   nf_wr_addr( 0 );
   nf_wr_addr( 0 );
   nf_wr_addr( LSB0(page_addr) );
   nf_wr_addr( LSB1(page_addr) );
   if ( 3==G_N_ROW_CYCLES )
   {
      nf_wr_addr( MSB1(page_addr) );
   }
   nf_wr_cmd(NF_COPY_BACK_CMD);
   nf_wait_busy();
}
示例#3
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Tests the Nand Flash configuration
//!
//! The function verifies that the connected NF is
//! properly declared in conf_nf.h.
//!
//! \param nb_dev number of device
//!
//! \return The number of device connected and corresponding
//! to NF identifiers.
//!
U8 nf_check_type( U8 nb_dev )
{
   U8 i_dev;

   //nf_init(        nb_dev, 0 );
#warning Update for full support.
   nf_reset_nands( nb_dev ); // Reset all the NF devices

   // Test NF configuration
   //
   for( i_dev=0 ; i_dev<nb_dev ; i_dev++ )
   {
      nf_select( i_dev );
      nf_wait_busy();
      nf_force_CE();
      nf_wr_cmd(NF_READ_ID_CMD);
      nf_wr_addr( 0 );
      if(( nf_rd_data()!=G_DEV_MAKER  )
      || ( nf_rd_data()!=G_DEV_ID     ))
      {
         Assert( false );
         return i_dev;
      }
      if( G_CE_LOW )
      {
         // Activate CE Low if needed. This config is static
         // and we supposed that it is no more deactivated in firmware.
         nf_force_CE();
      }
   }
   return nb_dev;
}
示例#4
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Mark a block as 'invalid' by clearing it entirely.
//!
//! \param page_addr          absolute page address of the block
//!
//! \pre <code>nf_init()</code> should have been called before.
//! The device which holds this bad block should have been selected
//! before with <code>nf_select( id )</code>.
//!
void nf_mark_bad_block(U32 page_addr)
{
   U8  n_bytes;
   U8  i_byte;
   U8  i_page;


   n_bytes= ( Is_nf_512() )
   ?  16  // 512B page access
   :  64  // 2KB  page access
   ;
   // Erasing the block is mandatory to prevent partial programming
   // (some 512B NF does support partial prog, but not after a copy back command).
   nf_erase_block( page_addr, true );
   for ( i_page=(U8)1<<G_SHIFT_BLOCK_PAGE ; i_page!=0 ; i_page--, page_addr++ )
   {
      nf_open_page_write( page_addr, NF_SPARE_POS-8 );
      nf_wr_data('A'); nf_wr_data('t');
      nf_wr_data('m'); nf_wr_data('e');
      nf_wr_data('l'); nf_wr_data(' ');
      nf_wr_data(' '); nf_wr_data(' ');
      for ( i_byte=n_bytes ; i_byte!=0 ; i_byte-=4 )
      {
         nf_wr_data(0);
         nf_wr_data(0);
         nf_wr_data(0);
         nf_wr_data(0);
      }
      nf_wr_cmd(NF_PAGE_PROGRAM_CMD); // Confirm programming
   }
}
示例#5
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Erases a block.
//!
//! The erase will be done only if the block is not bad
//!
//! \param page_addr          absolute page address of the block
//! \param force_erase        true forces erasing, false erases the block (if not bad)
//!
//! \pre <code>nf_init()</code> should have been called before.
//! The device which holds the block to delete should have been selected
//! before with <code>nf_select( id )</code>.
//!
void nf_erase_block( U32 page_addr, U8 force_erase )
{
   if( false==force_erase )
   {
      nf_open_page_read( page_addr, NF_SPARE_POS + G_OFST_BLK_STATUS );
      if( (nf_rd_data()!=0xFF) ) return; // The block is bad. We can not erase it
   }
   nf_wait_busy();
   nf_wr_cmd(NF_BLOCK_ERASE_CMD);          // Auto Block Erase Setup
   nf_wr_addr( LSB0(page_addr) );
   nf_wr_addr( LSB1(page_addr) );
   if ( 3==G_N_ROW_CYCLES )
   {
      nf_wr_addr( MSB1(page_addr) );
   }
   nf_wr_cmd(NF_BLOCK_ERASE_CONFIRM_CMD);      // Erase command
}
示例#6
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Reset all the NF devices.
//!
//! \param nb_dev Number of device
//!
void nf_reset_nands( U8 nb_dev )
{
   U8 i_dev;
   for( i_dev=0 ; i_dev<nb_dev ; i_dev++ )
   {
      nf_select( i_dev );
      // The wait is mandatory here since the function is used to wait any
      // pending internal programming (Cache Program cmd).
      nf_wait_busy();
      nf_wr_cmd(NF_RESET_CMD);
      nf_wait_busy();
   }
}
示例#7
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Check the status Ready/Busy of the Nand Flash
//! \return bool
//!    true   -> The Nand Flash is ready and connected
//!    false  -> The Nand Flash must be no connected (timeout)
//!
static bool nfc_nf_is_ready( void )
{
   U8 u8_timeout;
   U8 dummy;
   nf_wr_cmd( NF_READ_STATUS_CMD );  // send status for each read, because the NF must be in reset sequence
   dummy = Nfc_rd_status();     // active first read

   for (u8_timeout=NF_MAX_RB_TIMEOUT ; u8_timeout!=0 ; u8_timeout--)
   {
      if(( (Nfc_rd_status() & NF_MASK_STATUS_READY) !=0 )    // the busy pin is not tested, and the bit ready may be wrong penddind the rise of busy pin
      && ( (Nfc_rd_status() & NF_MASK_STATUS_READY) !=0 ) )  // To not read a wrong status, we check the status after 6 cycles (300ns)
      {
            return true;  // NF READY
      }
   }
   return false;          // TIMEOUT
}
示例#8
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Read the ID of the Nand-Flash
//!
//! \param read_id_cmd  Read_id command (NF_READ_ID_CMD, NF_READ_ID2_CMD)
//! \param nf_num       Nand Flash number
//!
//! \return :
//!   MSB0(ret) (MSB) is the Maker Code,
//!   MSB1(ret) is the Device Id,
//!   MSB2(ret) is 3rd byte returned,
//!   MSB3(ret) (LSB) is 4th byte returned.
//!
//! \pre <code>nf_init()</code> should have been called before.
//!
U32 nf_read_id( U8 read_id_cmd, U8 nf_num )
{
   U32 ret;

   nf_select( nf_num );
   nf_wait_busy();
   //nf_force_CE();
   nf_wr_cmd (read_id_cmd);
   nf_wr_addr( 0 );

   MSB0(ret)= nf_rd_data(); // Maker Code
   MSB1(ret)= nf_rd_data(); // Device Id
   MSB2(ret)= nf_rd_data(); // extra
   MSB3(ret)= nf_rd_data(); // extra (Multi Plane Support)

   //Nfc_action( NFC_ACT_ASSERT_CE, NFC_EXT_NOP);
   return ret;
}
示例#9
0
文件: nf.c 项目: InSoonPark/asf
//! \brief Tests the true busy. Note that we test twice the ready, since there is
//! an hardware minimum requirement between the end of the busy and the first
//! read cycle. Since the busy is not wired, the ready is tested twice.
//!
void nf_wait_busy( void )
{
   ecchrs_freeze(&AVR32_ECCHRS);
   nf_wr_cmd(NF_READ_STATUS_CMD);
   if( Is_nf_2k() )
   {
      if( G_CACHE_PROG )
      {
         while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_2KB )==0 );
         while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_2KB )==0 );
      }
      else
      {
         while( (nf_rd_data() & NF_MASK_STATUS_READY     )==0 );
         while( (nf_rd_data() & NF_MASK_STATUS_READY     )==0 );
      }
   }
   if( Is_nf_512() )
   {
      while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_512B )==0 );
      while( (nf_rd_data() & NF_MASK_STATUS_T_RDY_512B )==0 );
   }
   ecchrs_unfreeze(&AVR32_ECCHRS);
}
示例#10
0
// main function
int main(void)
{
  bool   valid_block_found[NF_N_DEVICES];
  U32    u32_nf_ids, i_dev, i_block;
  U8     maker_id, device_id;
  U32    i, j;
  // ECCHRS options.
  static const ecchrs_options_t ECCHRS_OPTIONS =
  {
    .typecorrect = ECCHRS_TYPECORRECT_4_BIT,
    .pagesize    = ECCHRS_PAGESIZE_4_BIT_2112_W
  };

  // switch to oscillator 0
  pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);

   // init debug serial interface
  init_dbg_rs232(FOSC0);

  nf_init(FOSC0); // init the nand flash driver with the correct HSB frequency
  nf_unprotect();

  print_dbg("\r\nECCHRS example using Nand Flash.\r\n================================\r\n\r\n");

  // - Simple test of the NF communication through the SMC.
  // - Find all bad blocks.
  // - Find a valid block for the remaining tests.
  nf_reset_nands(NF_N_DEVICES);

  print_dbg("\tCPU, HSB is at 12000000Mhz.\r\n");
  print_dbg("\tPBA, PBB is at 12000000Mhz.\r\n");

  print_dbg("\tDetecting Nand Flash device(s).\r\n");
  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
  {
    // Performs some init here...
    valid_block_found[i_dev] = false;

    // Test Maker and Device ids
    u32_nf_ids = nf_read_id( NF_READ_ID_CMD, i_dev );
    maker_id  = MSB0(u32_nf_ids);
    device_id = MSB1(u32_nf_ids);
    print_dbg("\t\tNF");
    print_dbg_hex(i_dev);
    print_dbg(" [Maker=");
    print_dbg_hex(maker_id);
    print_dbg("] [Device=");
    print_dbg_hex(device_id);
    print_dbg("]\r\n");
    if( maker_id==M_ID_MICRON )
    {
      print_dbg("\t\t       Micron chip");
      if( device_id==0xDA ){
        print_dbg("- MT29F2G08AACWP device\r\n");
      }
      else
      {
       print_dbg("- *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n");
        return -1;
      }
    }
    else
    {
      print_dbg("\t\t       *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n");
      return -1;
    }
  }

  // Looking for valid blocks for the test.
  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
  {
    nf_select(i_dev);
    for( i_block=0 ; i_block<G_N_BLOCKS ; i_block++ )
    {
      nf_open_page_read( nf_block_2_page(i_block), NF_SPARE_POS + G_OFST_BLK_STATUS );
      if( (nf_rd_data()==0xFF) )
      { // The block is valid.
        print_dbg("\tValid block found (");
        print_dbg_ulong(i_block);
        print_dbg(") on NF ");
        print_dbg_hex(i_dev);
        print_dbg("\r\n");
        valid_block_found[i_dev]= true;
        valid_block_addr[i_dev] = i_block;
        break;
      }
    }
  }

  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
    if( !valid_block_found[i_dev] )
    {
      print_dbg("Error: no valid blocks found.\r\n");
      return 0;
    }

  print_dbg("\tECCHRS IP ver ");
  print_dbg_ulong(ecchrs->version);
  print_dbg("(");
  print_dbg_hex(ecchrs->version);
  print_dbg(")");
  print_dbg("\r\n");


  // Work with NF 0 from now...
  nf_select(0);

  // Setup the ECCHRS.
  ecchrs_init(&AVR32_ECCHRS, &ECCHRS_OPTIONS);

  // Ensures that the block is erased for the test.
  print_dbg("\tErasing a free block for the test.\r\n");
  nf_erase_block(nf_block_2_page(valid_block_addr[0]), false);

  // Reset the ECCHRS state machine.
  ecchrs_reset(&AVR32_ECCHRS);

  // Program a simple patterns in the first page.
  print_dbg("\tProgramming the first page with a simple pattern.\r\n");
  nf_open_page_write( nf_block_2_page(valid_block_addr[0]), 0);
  for ( i = 0; i < 2048/2; i++ )
  {
    U16 val = i;
    nf_wr_data(MSB(val));
    nf_wr_data(LSB(val));
  }

  // Extract the ECCs and store them at the end of the page.
  // [2054; 2063]: codeword  0:9
  // [2070; 2079]: codeword 10:19
  // [2086; 2095]: codeword 20:29
  // [2102; 2111]: codeword 30:39
  // Since we use the Random Data Output command, we need to freeze
  // the ECCHRS in order to keep our ECC codewords unchanged.
  print_dbg("\tExtracting the ECCHRS codewords and store them in the page.\r\n");
  ecchrs_freeze(&AVR32_ECCHRS);  // not needed if ECCHRS reaches the end of page.
  for ( i=0 ; i<4 ; i++ )
  {
    U16 offset = 2048+6+16*i;
    nf_wr_cmd(NF_RANDOM_DATA_INPUT_CMD);
    nf_wr_addr( LSB(offset) );
    nf_wr_addr( MSB(offset) );
    for ( j=0 ; j<10 ; j++ )
      nf_wr_data( ecchrs_get_cw(&AVR32_ECCHRS, i*10+j) );
  }
  ecchrs_unfreeze(&AVR32_ECCHRS);

  nf_wr_cmd(NF_PAGE_PROGRAM_CMD);


  // Now let's test the ECC verification.
  print_dbg("\tReading the first page.\r\n");
  nf_open_page_read( nf_block_2_page(valid_block_addr[0]), 0);
  for( i=0 ; i<2048 ; i++ )
    nf_rd_data();

  print_dbg("\tChecking if the data are valid thanks to the ECCHRS codewords.\r\n");
  for ( i=0 ; i<4 ; i++ )
  {
    U16 offset = 2048+6+16*i;
    ecchrs_freeze(&AVR32_ECCHRS);
    nf_wr_cmd(NF_RANDOM_READ_CMD_C1);
    nf_wr_addr( LSB(offset) );
    nf_wr_addr( MSB(offset) );
    nf_wr_cmd(NF_RANDOM_READ_CMD_C2);
    ecchrs_unfreeze(&AVR32_ECCHRS);
    for ( j=0 ; j<10 ; j++ )
      nf_rd_data();
  }

  // Check if there is any errors after the read of the page.
  i = ecchrs_4bit_check_error(&AVR32_ECCHRS);
  print_dbg("\tSR1 is  ");
  print_dbg_ulong(i);
  print_dbg("(");
  print_dbg_hex(i);
  print_dbg(")");
  print_dbg("\r\n");

  if(i&(15))
  {
   print_dbg("\tERROR: ECCHRS detects some errors in the sectors 1, 2, 3 or 4\r\n");
  }
  else
   print_dbg("\tNo error detected.\r\n");

  // Let the block free.
  nf_erase_block(nf_block_2_page(valid_block_addr[0]), false);
  return 0;
}
示例#11
0
文件: nf_example.c 项目: Mazetti/asf
/*! \brief Main function.
 */
int main(void)
{
  bool   valid_block_found[NF_N_DEVICES];
  U32    u32_nf_ids, i_dev, i_block;
  U8     maker_id, device_id, byte3;
  U32    i, time_s, time_e;
  U8     data;

  // start init
  sysclk_init();

  // Enable clock for require module
  sysclk_enable_hsb_module(SYSCLK_EBI);
  sysclk_enable_pbb_module(SYSCLK_SMC_REGS);
  sysclk_enable_pbb_module(SYSCLK_HMATRIX);

  // Initialize the board.
  // The board-specific conf_board.h file contains the configuration of the board
  // initialization.
  board_init();

  init_stdio();

#ifdef NF_ADDON // addon nandflash board for EVK1104 (not mounted by default)
  // Unselect NF on board
  gpio_set_gpio_pin(AVR32_PIN_PX53);
  gpio_set_gpio_pin(AVR32_PIN_PX52);
#endif

  nf_init(sysclk_get_cpu_hz());
  nf_unprotect();

  printf("\x0C");
  printf("Nand Flash example.\r\n===================\r\n\r\n");

  // - Simple test of the NF communication through the SMC.
  // - Find all bad blocks.
  // - Find a valid block for the remaining tests.
  nf_reset_nands(NF_N_DEVICES);

  printf("\tDetecting Nand Flash device(s).\r\n");
  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
  {
    // Performs some init here...
    valid_block_found[i_dev] = false;

    // Test Maker and Device ids
    u32_nf_ids = nf_read_id( NF_READ_ID_CMD, i_dev );
    maker_id  = MSB0(u32_nf_ids);
    device_id = MSB1(u32_nf_ids);
    byte3     = MSB3(u32_nf_ids);
    printf("\t\tNF %ld: [Maker=0x%02x] [Device=0x%02x] [byte3=0x%02x]\r\n", i_dev, maker_id, device_id, byte3);
    if( maker_id==M_ID_MICRON )
    {
      printf("\t\t       Micron chip");
      if( (device_id==0xDA) && (byte3==0x15) )
        printf("- MT29F2G08AACWP device\r\n");
      else if( (device_id==0xDA) && (byte3==0x95) )
        printf("- MT29F2G08AADWP device\r\n");
      else
      {
        printf("- *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n");
        return -1;
      }
    }
    else
    {
      printf("\t\t       *** Error: unexpected chip detected. Please check the board settings and hardware.\r\n");
      return -1;
    }
  }

  printf("\r\n\tTesting bad blocks.\r\n");
  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
  {
    printf("\t\tNF %ld:\r\n", i_dev);
    nf_select(i_dev);
    for( i_block=0 ; i_block<G_N_BLOCKS ; i_block++ )
    {
      nf_open_page_read( nf_block_2_page(i_block), NF_SPARE_POS + G_OFST_BLK_STATUS );
      if( (nf_rd_data()!=0xFF) )
      { // The block is bad.
        printf("\t\t\tBlock %ld (0x%lx) is bad.\r\n", i_block, i_block);
      }
      else
      {
        if( !valid_block_found[i_dev] )
        {
          valid_block_found[i_dev]= true;
          valid_block_addr[i_dev] = i_block;
          printf("\t\t\tFirst valid block is at address %ld (0x%lx).\r\n", i_block, i_block);
        }
      }
    }
  }

  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
    if( !valid_block_found[i_dev] )
    {
      printf("Error %d\r\n", __LINE__);
      return 0;
    }



  // - Ensure good NF behaviour through simple commands.
  //   Erase, Program, Read
  // - Measures NF timings.
  printf("\r\n\tMeasuring NF timings.\r\n");
  for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
  {
    printf("\t\tNF %ld:\r\n", i_dev);
    nf_select(i_dev);
    nf_erase_block( nf_block_2_page(valid_block_addr[0]), false);
    time_s = Get_sys_count();
    nf_wait_busy();
    time_e = Get_sys_count();

    // Verify that the block is erased.
    nf_open_page_read( nf_block_2_page(valid_block_addr[0]), 0);
    for( i= 0; i<2048 ; i++ )
    {
      data = nf_rd_data();
      if( data!=0xFF )
      {
        printf("\tError: offset %d is not erased (read %d).\r\n", (U8)i, data);
        return 0;
      }
    }
    printf("\t\t\tTime to erase a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz()));

    nf_open_page_write( nf_block_2_page(valid_block_addr[0]), 0);
    for( i=0 ; i<2048 ; i++ )
      nf_wr_data(i%256);
    nf_wr_cmd(NF_PAGE_PROGRAM_CMD);

    time_s = Get_sys_count();
    nf_wait_busy();
    time_e = Get_sys_count();
    printf("\t\t\tTime to program a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz()));

    time_s = Get_sys_count();
    nf_open_page_read( nf_block_2_page(valid_block_addr[0]), 0);
    time_e = Get_sys_count();
    printf("\t\t\tTime to access to a page:%ld cy (%ld us)\r\n", time_e-time_s, cpu_cy_2_us(time_e-time_s, sysclk_get_cpu_hz()));
    for( i= 0; i<2048 ; i++ )
    {
      data = nf_rd_data();
      if( data!= i%256)
      {
        printf("\tError: expect %d, read %d\r\n", (U8)i, data);
        return 0;
      }
    }
  }

  printf("Example DONE\r\n");

  return 0;
}