📄 flashhw.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 + -