flash.c

来自「FreeScale imx21开发板Nand flash烧写程序」· C语言 代码 · 共 1,195 行 · 第 1/3 页

C
1,195
字号
// ***************************************************************************
//
//  Filename:       flash.c
//
//  Created:        Louis Lai (6/20/2003)
//
//  Modified:       $Author: $ $Date: $
//
// ***************************************************************************


// ***************************************************************************
//  pragmas
// ***************************************************************************


// ***************************************************************************
//  includes
// ***************************************************************************
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tht_memory_map_defines.h"
#include "common.h"

//add by fcding
#include "mx_nand2k.h"
#include "flash_report.h"

//add by fcding
/*****************************************************************************
* <Macros>
*****************************************************************************/
#define CCM_RCSR 						(0x10027000+0x814)
#define CCM_PDR0 						(0x10027000+0x18)

//#define NFC_BASE_ADDR				(0xD8000000)
#define NFC_MAB0_BASE       (NFC_BASE_ADDR+0x000)	/*  main area buffer0 */
#define NFC_MAB1_BASE       (NFC_BASE_ADDR+0x200)	/*  main area buffer1 */
#define NFC_MAB2_BASE       (NFC_BASE_ADDR+0x400)	/*  main area buffer2 */
#define NFC_MAB3_BASE       (NFC_BASE_ADDR+0x600)	/* main area buffer3 */
#define NFC_SAB0_BASE       (NFC_BASE_ADDR+0x800)	/* spare area buffer0 */
#define NFC_SAB1_BASE       (NFC_BASE_ADDR+0x810)	/* spare area buffer1 */
#define NFC_SAB2_BASE       (NFC_BASE_ADDR+0x820)	/*  spare area buffer2 */
#define NFC_SAB3_BASE       (NFC_BASE_ADDR+0x830)	/*  spare area buffer3 */
	
#define NFC_REG_BASE        (NFC_BASE_ADDR+0xE00)   /*  nfc register area */
#define NFC_BUFSIZE         (NFC_REG_BASE+0x00)	  
#define NFC_BLK_ADD_LOCK    (NFC_REG_BASE+0x02)	    
#define NFC_RAM_BUF_ADDR    (NFC_REG_BASE+0x04)	  
#define NFC_NAND_FLASH_ADDR (NFC_REG_BASE+0x06)	  
#define NFC_NAND_FLASH_CMD  (NFC_REG_BASE+0x08)	  
#define NFC_CONFIGURATION   (NFC_REG_BASE+0x0A)	  
#define NFC_ECC_STAT_RES    (NFC_REG_BASE+0x0C)	  
#define NFC_ECC_RSLT_MA     (NFC_REG_BASE+0x0E)	  
#define NFC_ECC_RSLT_SA     (NFC_REG_BASE+0x10)	  
#define NFC_NF_WR_PROT      (NFC_REG_BASE+0x12)	  
#define NFC_ULOCK_START_BLK (NFC_REG_BASE+0x14)	  
#define NFC_ULOCK_END_BLK   (NFC_REG_BASE+0x16)	  
#define NFC_NF_WR_PROT_STAT (NFC_REG_BASE+0x18)	  
#define NFC_NF_CONFIG1      (NFC_REG_BASE+0x1A)	  
#define NFC_NF_CONFIG2      (NFC_REG_BASE+0x1C)	  
/*******************************************************************************/

#define NAND_CMD_READ              (0x00)
#define NAND_CMD_READ1             (0x01)
#define NAND_CMD_READ2             (0x50)       
#define NAND_CMD_READ_CONFIRM      (0x30)
#define NAND_CMD_PAGE_PROG         (0x80)
#define NAND_CMD_PAGE_PROG_CONFIRM (0x10)
#define NAND_CMD_ERASE             (0x60)
#define NAND_CMD_ERASE_CONFIRM     (0xD0)
#define NAND_CMD_READID            (0x90)
#define NAND_CMD_RESET             (0xFFFF)
#define NAND_CMD_READ_STATUS       (0x70)

#define NAND_STATUS_READY          (0x40)
#define NAND_STATUS_NOT_PROTECT    (0x80)
#define NAND_STATUS_PROG_ERROR     (0x01)

#define NF_FMS_2KB                 (0x20)
#define NF_16BIT                   (0x10)
#define PCDR0_NFCDIV_MASK          (0x0000F000)
#define PCDR0_NFCDIV_10            (0x9)

#define NFC_BUSY  (!( *(volatile u16 *)NFC_NF_CONFIG2 & 0x8000 ))

/*****************************************************************************
* <global Variables>
*****************************************************************************/
nand_t nand_type[] = {
//  manuf  device io    badblock row   num   num     
//  id     id     width marker   addr  of    of     
//                      offset   cycle block page    
  { 0xEC,  0xDC,  8,    0,       3,    4096, 64, "NAND K9F4G08U0M" }, // K9F4G08U0M  
  { 0xEC,  0xAA,  8,    0,       3,    2048, 64, "NAND K9K2G08R0A" }  // K9K2G08R0A
};

nand_t *gNAND;	


//#define DEBUG


#ifndef TRUE
    #define TRUE               (1 == 1)
#endif
#ifndef FALSE
    #define FALSE              (1 == 2)
#endif

// ***************************************************************************
//  macros
// ***************************************************************************
#define MIN(a,b)                ((a) < (b) ? (a) : (b))
#define MAX(a,b)                ((a) > (b) ? (a) : (b))

// ***************************************************************************
//  definitions
// ***************************************************************************
#define FLASH_DQ7_2X16      ((1 << (7 + 16)) | (1 << 7))
#define FLASH_DQ5_2X16      ((1 << (5 + 16)) | (1 << 5))
#define	TACC				55								// Asyn. Access Time 
#define TIACC				87	 							// Syn. Access Time#define	HCLK				66								// EIM CLK
#define FCLK				54								// Flash Burst CLK
#define	HCLK				66

#define MX21_MEM_ADDR_CS0	0xC8000000
#define MX21_MEM_ADDR_CS1	0xCC000000
#define MX21_MEM_ADDR_CS2	0xD0000000
#define MX21_MEM_ADDR_CS3	0xD1000000
#define MX21_MEM_ADDR_CS4	0xD2000000
#define MX21_MEM_ADDR_CS5	0xD3000000



//change by fcding
U8 nand_init(void)
{

	U8  man_id;
	U8  dev_id;
	U16 i;
	U8 is_found =0;

  *(volatile U32 *)CCM_RCSR  &= ~NF_16BIT;   /* Set to 8-bit NAND */
  *(volatile U32 *)CCM_RCSR  |= NF_FMS_2KB;  /* Set to 2K Page Size */

  *(volatile U32 *)CCM_PDR0  &= ~PCDR0_NFCDIV_MASK;
  *(volatile U32 *)CCM_PDR0  |= (PCDR0_NFCDIV_10 << 12);   /* set NFC_PODF = 10 */

  *(volatile U16 *)NFC_RAM_BUF_ADDR    = 0;      /* select Buffer 0 */
  *(volatile U16 *)NFC_ULOCK_START_BLK = 0x0000;
  *(volatile U16 *)NFC_ULOCK_END_BLK   = 0x0FFF;
  *(volatile U16 *)NFC_NF_WR_PROT      = 0x0004;
  *(volatile U16 *)NFC_CONFIGURATION   = 0x0002; /* unlock the internal RAM buffer */
  *(volatile U16 *)NFC_NF_CONFIG2      = 0x8000; /* clear all operation */
  //*(volatile U16 *)NFC_NF_CONFIG1      = 0x0018; /* enable ECC and disable spare only, disable interrupt*/
	*(volatile U16 *)NFC_NF_CONFIG1      = 0x0008;	

	*(volatile U16 *)NFC_ECC_STAT_RES	=0x0000;
/*
   nand_read_id(&man_id, &dev_id);
    
   gNAND = nand_type;
   i = sizeof(nand_type) / sizeof(nand_t);
   while(i--) {
   if( nand_type[i].man_id == man_id && nand_type[i].dev_id == dev_id ){
     gNAND = nand_type + i;
    if( gNAND->io_width == 16 )
       *(volatile u32 *)CCM_RCSR  |=  NF_16BIT;   
     is_found = 1;
     dbg("Find specific NAND type!\n");
    break;
   }
   }
   if(is_found)
    return NAND_ERROR_NO;
   else
    return NAND_ERROR_INIT;
*/
}

U8 nfc_wait(void)
{
  while(NFC_BUSY); /* Wait for Basic Operation Complete */

  return 0;
}

void nfc_command_input(U16 command)
{
	*(volatile U16 *)NFC_NAND_FLASH_CMD  = command;
	*(volatile U16 *)NFC_NF_CONFIG2      = 0x0001; 
   
	nfc_wait();
}

U8 nand_read_status(void)
{
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;

	nfc_command_input(NAND_CMD_READ_STATUS);
	*(volatile U16 *)NFC_NF_CONFIG2 = 0x0020; // FDO -> Read Status

	nfc_wait();

	return (U8)((*(volatile U32 *)(NFC_MAB0_BASE)) & 0xFF) ;
}

void nfc_address_input(U16 address)
{
   *(volatile U16 *)NFC_NAND_FLASH_ADDR = address;
   *(volatile U16 *)NFC_NF_CONFIG2 = 0x0002;
   nfc_wait();
}

void nfc_address_cycle(U32 Address, U8 NumOfCycle)
{
	U8 i;

	for(i=0; i<NumOfCycle; i++)
	nfc_address_input( (U16)( (Address>>(i*8))&0xFF ) );
}

void nfc_flash_data_output(void)
{
	*(volatile U16 *)NFC_NF_CONFIG2 = 0x0008;
	nfc_wait();
}

U8 nfc_ecc_uncorrectable_error(void)
{
   return ( *(volatile U16 *)NFC_ECC_STAT_RES & 0xA ) ? 1 : 0;
}

U8 nand_erase_block(u32 BlockNum)
{
	U32 row;
   
	row = (BlockNum*NAND_NUM_OF_PAGES);

	nfc_command_input(NAND_CMD_ERASE);
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);

	nfc_command_input(NAND_CMD_ERASE_CONFIRM);

	if( nand_read_status() & NAND_STATUS_PROG_ERROR ) {	
		return NAND_ERROR_ERASE;
	}
	else
		return NAND_ERROR_NO;
}

void nfc_flash_data_input(void)
{
   *(volatile U16 *)NFC_NF_CONFIG2 = 0x0004;
   nfc_wait();
}

U8 nand_mark_bad_block(U32 BlockNum)
{
	U8 i;
	U32 col = 0, row;
   
	row = (BlockNum*NAND_NUM_OF_PAGES);
  
	for(i=0; i<64; i+=2)
		*(volatile U16 *)(NFC_SAB0_BASE+i) = 0;
 
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;

	nfc_command_input(NAND_CMD_PAGE_PROG);
	nfc_address_cycle(col, 2);
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
	nfc_flash_data_input();

	*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
	nfc_flash_data_input();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
	nfc_flash_data_input();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
	nfc_flash_data_input();

	nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);

	while (!(nand_read_status() & NAND_STATUS_READY));

	if (nand_read_status() & NAND_STATUS_PROG_ERROR)
	{ 
		return 1;
	}

	return 0;
}
U8 nand_block_is_good(U32 BlockNum)
{
	U16 flag;
	U32 col = 0, row;
   
	/* check first page */
	row = (BlockNum*NAND_NUM_OF_PAGES);

	*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;

	nfc_command_input(NAND_CMD_READ);
	nfc_address_cycle(col, 2);
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
	/* command READ CONFIRM */
	nfc_command_input(NAND_CMD_READ_CONFIRM);
	nfc_flash_data_output();

	*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
	nfc_flash_data_output();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
	nfc_flash_data_output();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
	nfc_flash_data_output();
   
	if(nfc_ecc_uncorrectable_error()) {
		return 0;
	}

	flag = *(volatile u16 *)(NFC_SAB0_BASE + 4);

	if ((flag & 0xFF00) != 0xFF00) {
		return 0;
	}
   
	/* check second page */
	row = (BlockNum*NAND_NUM_OF_PAGES) + 1;

	*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;

	nfc_command_input(NAND_CMD_READ);
	nfc_address_cycle(col, 2);
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
	/* command READ CONFIRM */
	nfc_command_input(NAND_CMD_READ_CONFIRM);
	nfc_flash_data_output();

	*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
	nfc_flash_data_output();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
	nfc_flash_data_output();
	*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
	nfc_flash_data_output();

	if(nfc_ecc_uncorrectable_error()) {

		return 0;
	}
    	
	flag = *(volatile U16 *)(NFC_SAB0_BASE + 4);

	return ((flag & 0xFF00) == 0xFF00);

}

void nand_wait(void)
{
	while(!(NAND_STATUS_READY  & nand_read_status()));
}

void nfc_memcpy(U32 SourceAddress, U32 TargetAddress, U32 ByteSize)
{
	U32 i;
	for(i=0; i<ByteSize; i+=4) {
		*(volatile u32 *)(TargetAddress+i) = *(volatile u32 *)(SourceAddress+i);
		
	}
}

U8 nand_read_page(U32 BlockNum, U32 PageNum, U32 TargetAddress, U32 ByteSize)
{

  *(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
  nfc_command_input(NAND_CMD_READ);
  nfc_address_cycle(0, 2);
  nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
  nfc_command_input(NAND_CMD_READ_CONFIRM);
  nfc_flash_data_output();

  *(volatile u16 *)NFC_RAM_BUF_ADDR = 1;
  nfc_flash_data_output();
  *(volatile u16 *)NFC_RAM_BUF_ADDR = 2;
  nfc_flash_data_output();
  *(volatile u16 *)NFC_RAM_BUF_ADDR = 3;
  nfc_flash_data_output();

  if(nfc_ecc_uncorrectable_error())
    return NAND_ERROR_ECC;
    
  nfc_memcpy(NFC_MAB0_BASE, TargetAddress, ByteSize);
  
  return NAND_ERROR_NO;  
}

U8 nand_read(U32 FlashAddress, U32 TargetAddress, U32 ByteSize)

⌨️ 快捷键说明

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