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

📄 flashhw.c

📁 norflash烧写 电子开发人员
💻 C
字号:
/***********************************************************************/
/*  This file is part of the ARM Toolchain package                     */
/*  Copyright KEIL ELEKTRONIK GmbH 2003 - 2007                         */
/***********************************************************************/
/*                                                                     */
/*  FlashHW.C:   Hardware Layer of NAND Flash Programming Functions    */
/*               adapted for the Samsung S3C2440 Controller            */
/***********************************************************************/

#include "NAND_Error.h"                     // Error definitions

#define BLOCK_SIZE  	   64

// Register and bit definitions
#define NFCONF                 (*(volatile unsigned long *) (0x4E000000))
#define NFCONT                 (*(volatile unsigned long *) (0x4E000004))
#define NFCMMD                 (*(volatile unsigned long *) (0x4E000008))
#define NFADDR                 (*(volatile unsigned long *) (0x4E00000C))
#define NFDATA                 (*(volatile unsigned long *) (0x4E000010))
#define NFDATA_C               (*(volatile unsigned char *) (0x4E000010))
#define NFMECCD0               (*(volatile unsigned long *) (0x4E000014))
#define NFMECCD1               (*(volatile unsigned long *) (0x4E000018))
#define NFSECCD                (*(volatile unsigned long *) (0x4E00001C))
#define NFSTAT                 (*(volatile unsigned long *) (0x4E000020))
#define NFESTAT0               (*(volatile unsigned long *) (0x4E000024))
#define NFESTAT1               (*(volatile unsigned long *) (0x4E000028))
#define NFMECC0                (*(volatile unsigned long *) (0x4E00002C))
#define NFMECC1                (*(volatile unsigned long *) (0x4E000030))
#define NFSECC                 (*(volatile unsigned long *) (0x4E000034))
#define NFSBLK                 (*(volatile unsigned long *) (0x4E000038))
#define NFEBLK                 (*(volatile unsigned long *) (0x4E00003C))

#define CLKCON                 (*(volatile unsigned long *) (0x4C00000C))
#define CLKSLOW                (*(volatile unsigned long *) (0x4C000010))
#define CLKDIVN                (*(volatile unsigned long *) (0x4C000014))

#define INTMSK                 (*(volatile unsigned long *) (0x4A000008))

#define GPACON                 (*(volatile unsigned long *) (0x56000000))
#define GPADAT                 (*(volatile unsigned long *) (0x56000004))

#define GPBCON                 (*(volatile unsigned long *) (0x56000010))
#define GPBDAT                 (*(volatile unsigned long *) (0x56000014))
#define GPBUP                  (*(volatile unsigned long *) (0x56000018))

// NAND Flash Commands
#define NAND_CMD_READ0         0x00         // Read mode (1) command
#define NAND_CMD_READ1         0x01         // Read mode (2) command
#define NAND_CMD_PAGEPROG      0x10         // Auto program command
#define NAND_CMD_READSTART     0x30         // Read start command
#define NAND_CMD_READ2         0x50         // Read mode (3) command
#define NAND_CMD_ERASE1ST      0x60         // Auto block erase 1-st command
#define NAND_CMD_STATUS        0x70         // Status read (1) command
#define NAND_CMD_STATUS_MULTI  0x71         // Status read (2) command
#define NAND_CMD_SDIN          0x80         // Serial data input command
#define NAND_CMD_READID        0x90         // ID read (1) command
#define NAND_CMD_ERASE2ND      0xD0         // Auto block erase 2-nd command
#define NAND_CMD_RESET         0xFF         // Reset command


// Module's local functions prototypes
static int SetAddress_HW      (unsigned long adr);
static int SetBlockAddress_HW (unsigned long adr);


// Buffer for spare area reading or writing
unsigned char spare_buf[16];

/************************* Module Exported Functions ***************************/

/*- InitFlashController_HW (...) -----------------------------------------------
 *
 *  Initialize Flash Controller
 *    Parameter:  bus_width:  Bus Width (8, 16 bit)
 *               adr_cycles:  Addressing Cycles (3, 4, 5)
 *                page_type:  Page Type (0 - Small Page, 1 - Large Page)
 *                      clk:  Clock Frequency (Hz)
 *    Return Value:           NAND_ERROR
 */

int InitFlashController_HW (void) {

  
  // Set important registers to reset values as hardware reset is not functional 
  // through JTAG reset pin
  INTMSK  = 0xFFFFFFFF;
  CLKCON  = 0x001FFFF0;
  GPACON  = 0xFFFFFFFF;

  // Disable Write Protect, drive nFWP pin high
  GPBUP  |= 0x0080;
  GPBCON |= 0x4000;
  GPBDAT |= 0x0080;

  // Set: TACLS = 3, TWRPH0 = 7, TWRPH1 = 7
  NFCONF  = (3 << 12) | (7 << 8) | (7 << 4);

  // Set: Lock spare ECC generation, Lock main data area ECC generation, 
  //      Initialize ECC encoder/decoder, NAND flash controller enable
  NFCONT  = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 0);

  while (!(NFSTAT & 0x01));             // Wait while controller busy
  NFCMMD  = NAND_CMD_RESET;             // Reset NAND flash
  while (!(NFSTAT & 0x01));             // Wait while controller busy

  NFSBLK  = (0x00000000 >> 9);          // NAND Flash prog start block address
  NFEBLK  = (0x08000000 >> 9);          // NAND Flash prog end   block address

  return (NAND_OK);
}


/*- EraseBlock_HW (...) --------------------------------------------------------
 *
 *  Erase whole Block
 *    Parameter:      adr:  Block Start Address
 *    Return Value:   NAND_ERROR
 */

int EraseBlock_HW (unsigned long adr) {

  while (!(NFSTAT & 0x01));             // Wait while controller busy
  NFCMMD  = NAND_CMD_ERASE1ST;
  SetBlockAddress_HW(adr);
  NFCMMD  = NAND_CMD_ERASE2ND;
  while (!(NFSTAT & 0x01));             // Wait while controller busy

  return (NAND_OK);
}


/*- ProgramPage_HW (...) -------------------------------------------------------
 *
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Page Start Address
 *                     sz:  Page Size
 *                    buf:  Page Data
 *    Return Value:         NAND_ERROR
 */

int ProgramPage_HW (unsigned long adr, unsigned long sz, unsigned char *buf) {
  int i;
  unsigned long *ptr_ul = (unsigned long *)buf;

    // Small Page Device
    while (!(NFSTAT & 0x01));           // Wait while controller busy
    NFCMMD = NAND_CMD_SDIN;
    SetAddress_HW(adr);
    for (i = 0; i < ((sz+3)>>2); i++) { // Write requested number of bytes
      NFDATA = *ptr_ul++;
    }
    NFCMMD = NAND_CMD_PAGEPROG;
    while (!(NFSTAT & 0x01));           // Wait while controller busy

  return (NAND_OK);
}



/*- ReadPage_HW (...) ----------------------------------------------------------
 *
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Page Start Address
 *                     sz:  Page Size
 *                    buf:  Page Data
 *    Return Value:         NAND_ERROR
 */

int ReadPage_HW (unsigned long adr, unsigned long sz, unsigned char *buf) {
  int i;
  unsigned long *ptr_ul = (unsigned long *)buf;
 
    while (!(NFSTAT & 0x01));           // Wait while controller busy
    NFCMMD = NAND_CMD_READ0;
    SetAddress_HW(adr);
    while (!(NFSTAT & 0x01));           // Wait while controller busy
    for (i = 0; i < ((sz+3)>>2); i++) { // Read requested number of bytes
      *ptr_ul++ = NFDATA;
    }
    while (i < (528>>2)) {              // Read remaining bytes to the end of page
      NFDATA;
      i++;
    }
    while (!(NFSTAT & 0x01));           // Wait while controller busy

  return (NAND_OK);
}


/*- CheckBlock_HW (...) --------------------------------------------------------
 *
 *  Check if block at requested address is valid
 *    Parameter:      adr:  Block Start Address
 *    Return Value:         NAND_ERROR
 */

int CheckBlock_HW (unsigned long adr) {
  int i;
  unsigned long *ptr_ul = (unsigned long *)spare_buf;

    while (!(NFSTAT & 0x01));           // Wait while controller busy
    NFCMMD = NAND_CMD_READ2;
    SetAddress_HW(adr);
    while (!(NFSTAT & 0x01));           // Wait while controller busy
    for (i = 0; i < (16 >> 2); i++) {   // Read 16 spare area bytes
      *ptr_ul++ = NFDATA;
    }
    while (!(NFSTAT & 0x01));           // Wait while controller busy
    NFCMMD = NAND_CMD_READ0;				  //?????
    while (!(NFSTAT & 0x01));           // Wait while controller busy

    // If 6-th byte in spare area is != 0xFF then the block is bad
    if (spare_buf[5] != 0xFF)   return 1;
    
  return (NAND_OK);
}





/*- SetAddress_HW (...) --------------------------------------------------------
 *
 *  Set the address according to address word count
 *    Parameter:     	 adr:  Address Requested for Setting
 *               	adr_type:  Address Word Count
 *             	   page_type:  Size of Page
 *    Return Value:         NAND_ERROR
 */

static int SetAddress_HW (unsigned long adr) {

  NFADDR    = adr & 0xFF;               // Address word 1st
  SetBlockAddress_HW(adr);

  return (NAND_OK);
}


/*- SetBlockAddress_HW (...) --------------------------------------------------------
 *
 *  Set the block address according to address word count
 *    Parameter:      adr:  Address Requested for Setting
 *               adr_type:  Address Word Count
 *              page_type:  Size of Page
 *    Return Value:         NAND_ERROR
 */

static int SetBlockAddress_HW (unsigned long adr) {
 
    NFADDR    = (adr >>  9) & 0xFF;     // Address word 1st
    NFADDR    = (adr >> 17) & 0xFF;     // Address word 2rd
    NFADDR  = (adr >> 25) & 0xFF;     // Address word 3th

  return (NAND_OK);
}


int ClearBadBlock(unsigned long block){
	int i;
    unsigned long *ptr_ul = (unsigned long *)spare_buf;
    unsigned long adr;
	adr=block<<14;
	
	while (!(NFSTAT & 0x01));           
   
    for (i=0; i<16; i++) spare_buf[i]=0xFF;

    // Write Spare Data
    NFCMMD = NAND_CMD_READ2;
    NFCMMD = NAND_CMD_SDIN;
    SetAddress_HW(adr);
    for (i = 0; i < (16>>2); i++) {     // Write 16 spare area bytes
      NFDATA = *ptr_ul++;
    }
    NFCMMD = NAND_CMD_PAGEPROG;

    while (!(NFSTAT & 0x01));           // Wait while controller busy
    NFCMMD = NAND_CMD_READ0;
    while (!(NFSTAT & 0x01));  

   return 0;
}


int nand_write(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  unsigned char *downPt;	
  unsigned long  block,page,blockPage,block_check,size; 	
  int i;

  size=0;
  downPt=(unsigned char *)buf;			              //point to download address

  //block=(adr>>14)-1;												   
	block=0;
  //copy from SDRAM to nand flash 
  for(i=0;i<BLOCK_SIZE;i++)
  {
    block++;											  //copy 
  	block_check=block<<14;							      //block address
	if(CheckBlock_HW(block_check))  continue;			  //check bad block 
	EraseBlock_HW(block_check);
	for(page=0;page<32;page++) 							  //copy a block=  32 page
	{
	 page=page&0x1f;
     blockPage=(block<<5)+page;							  //block and page address
	 blockPage=blockPage<<9;
	 ProgramPage_HW(blockPage,512,downPt);				  //write a page
	 downPt += 512;	

	 size+=512; 
	}

    if(size>sz) break;				
  }		

  return  0;
}


int nand_read(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  unsigned char *downPt;	
  unsigned long  block,page,blockPage,block_check,size; 	
  int i;

  size=0;
  downPt=(unsigned char *)buf;			   //point to download address

  block=0;												   

  //copy from nand flash to SDRAM
  for(i=0;i<BLOCK_SIZE;i++)
  {
    block++;											  //copy from 1 block
  	block_check=block<<14;							      //block address
	if(CheckBlock_HW(block_check))  continue;			  //check bad block 
	for(page=0;page<32;page++) 							  //copy a block=32 page
	{
	 page=page&0x1f;
     blockPage=(block<<5)+page;							  //block and page address
	 blockPage=blockPage<<9;
	 ReadPage_HW(blockPage,512,downPt);					  //read a block
	 downPt += 512;	

	 size+=512;
	}

	if(size>sz) break;		
  }		

 return 0;
}
/*******************************************************************************/

⌨️ 快捷键说明

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