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

📄 flashwriternand.c

📁 手机中写FLASH的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
// Copyright 1999, 2000, 2001, 2002, 2003, 2004 by Texas Instruments Incorporated. All rights 
// reserved.  Property of Texas Instruments Incorporated. Restricted rights to use,
// duplicate or disclose this code are granted through contract.
//
///////////////////////////////////////////////////////////////////////////////
//
// This file contains the stand-alone code for copying an Image from Memory to
// Flash.  
//
// Last Revision date:  2-3-04
// Release 1.8
//
//Headers
//
#include "types.h"
#include "Flash_params.h"
#include "OMAP.h"
//
//Globals 
//
//Parameters downloaded in .vars section
//(this sits at fixed memory locations!)
#pragma DATA_SECTION ( image, ".image" )
ULONG image;
#pragma DATA_SECTION ( global_vars, ".vars" )
Download_Parms global_vars; 
Download_Parms *gp_vars = &global_vars;

//
//Build Parameters
#define USES_CCS


//  HW Register pointers 
volatile USHORT *pNFReg;
volatile USHORT *pNFCMD;
volatile USHORT *pNFADDR;
volatile USHORT *pNFDATA;
volatile USHORT *pNFSTAT;

USHORT gStatus_Mask;

PageInfo block_reserved = {
    						(~(BLOCK_RESERVED | BLOCK_READONLY)),
    						(~(BADBLOCKMARK))
							};

void printinfo(ULONG size, ULONG srcAddr, ULONG destAddr)
{
	printf("FlashWriter Version 1.8\n");	
	printf("Starting Download to NAND Flash\n");
	printf("Image is %d bytes long\n", size);
	printf("Reading Image from: %08X\n", srcAddr);
	printf("Writing Image to:  %08X\n", destAddr);
}

void printNANDflashtype(enum NANDFlashType flash_id)
{
	switch (flash_id)
	{
		case NANDFLASH_SAMSUNG_32x8_Q:
			printf("Samsung Nand Flash K9F5608Q0B 32MB \n");
			break;
		case NANDFLASH_SAMSUNG_32x8_U:
			printf("Samsung Nand Flash K9F5608Q0U 32MB \n");
			break;
		case NANDFLASH_SAMSUNG_16x16_Q:
			printf("Samsung Nand Flash K9F5616Q0B 32MB \n");
			break;
		case NANDFLASH_SAMSUNG_16x16_U:
			printf("Samsung Nand Flash K9F5616Q0U 32MB \n");
			break;
		case NANDFLASH_NOT_FOUND:	
		default:
			printf("Flash not Found or unsupported!\n");
			break;
	}	
}

//
// This function compares two ECC's and indicates if there is an error.
// If the error can be corrected it will be corrected to the buffer
//
BYTE flash_CompareEcc( BYTE* ecc_data1, BYTE* ecc_data2, BYTE* page_data)
{
	WORD i;
	BYTE tmp0_bit[8],tmp1_bit[8],tmp2_bit[8];
	BYTE comp0_bit[8],comp1_bit[8],comp2_bit[8];
	BYTE tmp[3];
	BYTE ecc_bit[24];
	BYTE ecc_sum=0;
	BYTE ecc_value,find_bit=0;
	WORD find_byte=0;

	for( i=0; i<=2; i++ )
	{
		*(ecc_data1+i)=~(*(ecc_data1+i));
		*(ecc_data2+i)=~(*(ecc_data2+i));
	}	
	for(i=0;i<8;i++)
	{
		tmp0_bit[i]= *ecc_data1%2;
		*ecc_data1=*ecc_data1/2;
		tmp1_bit[i]= *(ecc_data1+1)%2;
		*(ecc_data1+1)=*(ecc_data1+1)/2;
		tmp2_bit[i]= *(ecc_data1+2)%2;
		*(ecc_data1+2)=*(ecc_data1+2)/2;
	}
	for(i=0;i<8;i++)
	{
		comp0_bit[i]= *ecc_data2%2;
		*ecc_data2=*ecc_data2/2;
		comp1_bit[i]= *(ecc_data2+1)%2;
		*(ecc_data2+1)=*(ecc_data2+1)/2;
		comp2_bit[i]= *(ecc_data2+2)%2;
		*(ecc_data2+2)=*(ecc_data2+2)/2;
	}
	for( i=0; i<6; i++ )
	{
		ecc_bit[i] = tmp2_bit[i+2]^comp2_bit[i+2];
	}
	for( i=0; i<8; i++)
	{
		ecc_bit[i+6] = tmp0_bit[i]^comp0_bit[i];
		ecc_bit[i+14] = tmp1_bit[i]^comp1_bit[i];
	}
	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
	
	for( i=0; i<24; i++ )
	{
		ecc_sum += ecc_bit[i];
	}
	switch(ecc_sum)
	{
		case 0:	// Not reached because this function is not called if ECC values are equal 			
			return NO_ERROR;
		case 1:	
			return ECC_ERROR;
		case 12:
			find_byte = (ecc_bit[23]<<8)+(ecc_bit[21]<<7)+(ecc_bit[19]<<6)
	 					+(ecc_bit[17]<<5)+(ecc_bit[15]<<4)+(ecc_bit[13]<<3)
	 					+(ecc_bit[11]<<2)+(ecc_bit[9]<<1)+ecc_bit[7];
			find_bit = (ecc_bit[5]<<2) +(ecc_bit[3]<<1)+ecc_bit[1];
			ecc_value = (page_data[find_byte]>>find_bit)%2;
	
			if(ecc_value==0)
			{
				ecc_value=1;
			} else
			{
				ecc_value=0;
			}
	
			*tmp=page_data[find_byte];
			for(i=0;i<8;i++)
			{
				tmp0_bit[i]= *tmp%2;
				*tmp=*tmp/2;
			}
			tmp0_bit[find_bit]=ecc_value;
	
			*tmp=(tmp0_bit[7]<<7)+(tmp0_bit[6]<<6)+(tmp0_bit[5]<<5)
				+(tmp0_bit[4]<<4)+(tmp0_bit[3]<<3)+(tmp0_bit[2]<<2)
				+(tmp0_bit[1]<<1)+tmp0_bit[0];
			page_data[find_byte] = *tmp;
			return CORRECTED_ERROR;
		default:	
			return UNCORRECTED_ERROR;
	}
}

void InitEcc()
{
	//Setup NFC to generate ECC codes for page size
	pNFC_ECC_SELECT	= 0x00;		//Generate 3 ECC bytes in NND_ECC1,2,3
	pNFC_CTRL = 0x00000001;		//Setting for Little Endian, ECC boundary = 512, ECC = enabled	
	pNFC_PSC_CLK = 0x0;			//Set Clock divider = 1 (fastest clock, won't work for real HW connect on NFC)
	pNFC_RESET == 0x1;			//Resets the ECC generation
}

void EccGenNFC(BYTE write_data[512], LPBYTE ecc_gen)
{
	ULONG ecc;
	int i;
	ULONG *data;
	
	//Send the data 4 bytes at a time to the NAND Flash Controller
	data = (ULONG *) write_data;
	for(i=0;i<PAGE_SIZE/4;i++)
	{
		pNFC_ACCESS = *data;
		data++;
	}
	//read the ECC values
	ecc = pNFC_ECC_1;
	
    //OK now we need to bit twiddle the results to match the expected ECC correction
	ecc_gen[0] = ecc & 0xFF;
	ecc_gen[1] = (ecc & 0xFF0000) >> 16;
	ecc_gen[2] = ((ecc & 0x0F000000) >> 20) | ((ecc & 0xF00)>>4);
	//To use for correction...		
	pNFC_RESET = 0x1;		//Reset the ECC calculator for the next page
}

void reorderECC(LPBYTE ecc_in, LPBYTE ecc_out)
{
	ULONG ecc;
	
	ecc = ( ecc_in[0] )
        | ( ecc_in[1]<<16 )
        | ( (ecc_in[2]&0xF0)<<20 )
        | ( (ecc_in[2]&0x0F)<<8 );
	//OK now we need to bit twiddle the results to match the expected ECC correction
	ecc_out[0] = ~((ecc & BIT22 >> (21-7))	//P64o
					| (ecc & BIT6 <<1)		//  (5-6))	//P64e
					| (ecc & BIT21 >> (20-5))	//P32o
					| (ecc & BIT5 >>  (4-4))	//P32e
					| (ecc & BIT20 >> (19-3))	//P16o
					| (ecc & BIT4 >>  (3-2))	//P16e
					| (ecc & BIT19 >> (18-1))	//P8o
					| (ecc & BIT3 >>  (2-0)));	//P8e
    
	ecc_out[1] = ~((ecc & BIT26 >> (25-7))	//P1024o
					| (ecc & BIT10 >> (9-6))	//P1024e
					| (ecc & BIT25 >> (24-5))	//P512o
					| (ecc & BIT9 >>  (8-4))	//P512e
					| (ecc & BIT24 >> (23-3))	//P256o
					| (ecc & BIT8 >>  (7-2))	//P256e
					| (ecc & BIT23 >> (22-1))	//P128o
					| (ecc & BIT7 >>  (6-0)));	//P128e	

	ecc_out[2] = ~((ecc & BIT18 >> (17-7))	//P4o
					| (ecc & BIT2 << 5)			//>> (2-6)) //P4e
					| (ecc & BIT17 >> (16-5))	//P2o
					| (ecc & BIT1 << 4)			//>> (1-4)) //P2e
					| (ecc & BIT16 >> (15-3))	//P1o
					| (ecc & BIT0 << 3)  		//>> (0-2))	//P1e
					| (ecc & BIT27 >> (26-1))	//P2048o
					| (ecc & BIT11 >>  (10-0)));	//P2048e			                                      	                                                         
		
}

////////////////////////////////////////////////////////////////////////////////
//NAND CODE
////////////////////////////////////////////////////////////////////////////////
#define NF_CMD(cmd)     WRITE_REGISTER_USHORT(pNFCMD, (USHORT) (cmd))
#define NF_ADDR(addr)   WRITE_REGISTER_USHORT(pNFADDR, (USHORT) (addr & 0xff))
#define NF_DATA_R()     READ_REGISTER_USHORT(pNFDATA)
#define NF_DATA_W(val)  WRITE_REGISTER_USHORT(pNFDATA, (USHORT) (val))
#define NF_STAT()       READ_REGISTER_ULONG(pNFSTAT)

void NF_WAITRB()
{
	while(!((NF_STAT() & gStatus_Mask) == gStatus_Mask));
}

void reset_NAND()
{
	NF_CMD(CMD_RESET);
	NF_WAITRB();
}

////////////////////////////////////////////////////////////////////////////////
// NAND_WriteProtection()
// Enables/disables any flash write protection.
////////////////////////////////////////////////////////////////////////////////
void NAND_WriteProtection( BOOL wp )
{
	ULONG temp;
    if (wp)  // Enable.
    {
		// Enable write protection in TC.
        
        temp = READ_REGISTER_ULONG(MIF_CONFIG_REG);
        temp &= ~BIT0;
        WRITE_REGISTER_ULONG( MIF_CONFIG_REG, temp);
    }
    else    // Disable.
    {
        // Disable write protection in TC.
        temp = READ_REGISTER_ULONG(MIF_CONFIG_REG);
        temp |= BIT0;
        WRITE_REGISTER_ULONG(MIF_CONFIG_REG, temp);
    }
}

///////////////////////////////////////////////////////////////////////////////
// Identify_Nand_Flash
// Description:
//   Reads the Flash Manufacturer ID and device codes to differentiate
//   the nand flash device.
// Return:
//   NANDFLASH_NOT_FOUND
//	 NANDFLASH_SAMSUNG_32x8_Q
//	 NANDFLASH_SAMSUNG_32x8_U
//	 NANDFLASH_SAMSUNG_16x16_Q
//	 NANDFLASH_SAMSUNG_16x16_U
///////////////////////////////////////////////////////////////////////////////
enum NANDFlashType IdentifyNandFlash(void)
{
	USHORT wManufacturer;
	USHORT wDevice;

	// Get the Manufacturer & Device ID	
	// Send Read ID Command
	NF_CMD(CMD_READID);
	NF_WAITRB();
	// Send Address 00h
	NF_ADDR(0x00);
	NF_WAITRB();
	// Read the manufacturer ID
	wManufacturer = NF_DATA_R();
	// Read the device code
	wDevice = NF_DATA_R();

	//return 
	if ( wManufacturer != SAMSUNG_MANUFACT_ID )
	{		
		return NANDFLASH_NOT_FOUND;
	}
	switch ( wDevice )
	{
		case SAMSUNG_K9F5608Q0B:
			return NANDFLASH_SAMSUNG_32x8_Q;
		case SAMSUNG_K9F5608U0B:
			return NANDFLASH_SAMSUNG_32x8_U;
		case SAMSUNG_K9F5616Q0B:
			return NANDFLASH_SAMSUNG_16x16_Q;
		case SAMSUNG_K9F5616U0B:
			return NANDFLASH_SAMSUNG_16x16_U;
		default:
			return NANDFLASH_NOT_FOUND;
	}	
}
///////////////////////////////////////////////////////////////////////////
//
//  NAND_FinishCommand
//
//  Write data into the Page. The current implementation only handles
//  one Page at a time.
//
///////////////////////////////////////////////////////////////////////////
BOOL NAND_FinishCommand(BYTE bCmd)
{
	BOOL bRet;	
    //  Complete operation
    NF_CMD(bCmd);
    //  Wait for ready bit
    NF_WAITRB();
    //  Check the status
    NF_CMD(CMD_STATUS);
	bRet = !(NF_DATA_R() & STATUS_ERROR);
    //  Disable the chip    
	return bRet;
}
///////////////////////////////////////////////////////////////////////////
//
//  NAND_SendFullCommand
//
//	Send Command with Full Address
//
///////////////////////////////////////////////////////////////////////////
void NAND_SendFullCommand(BYTE bCmd, ULONG PageAddr, ULONG dwOffset)
{
    //  Write the command
    NF_CMD(bCmd);

    //  Write the address
    NF_ADDR(dwOffset);
	NF_ADDR(PageAddr);
	NF_ADDR((PageAddr >> 8));
	
	if (NEED_EXT_ADDR)
	{
		NF_ADDR((PageAddr >> 16));
	}
    //  Wait for the Ready bit
    NF_WAITRB();
}


////////////////////////////////////////////////////////////////////////////
//
//  NAND_EraseBlock
//
//  Erase the given block
//
////////////////////////////////////////////////////////////////////////////
BOOL NAND_EraseBlock(ULONG blockID)
{
    ULONG   dwPageID = blockID << 5;

	//  Issue command
    NF_CMD(CMD_ERASE);
    //  Set up address
    NF_ADDR((dwPageID) & 0xff);
    NF_ADDR((dwPageID >> 8) & 0xff);

    if (NEED_EXT_ADDR) 
    {
        NF_ADDR((dwPageID >> 16) & 0xff);
    }
    //  Complete erase operation
    if( !NAND_FinishCommand(CMD_ERASE2)) 
    {   //Failed Erase Operation
        return FALSE;
    } 	
    return TRUE;
}

//////////////////////////////////////////////////////////////////////////
//
//  NAND_SimpleRead
//
//  Read data out of the Page. The current implementation only handles
//  one Page at a time.
//
//////////////////////////////////////////////////////////////////////////
void NAND_SimpleRead(LPBYTE pPageBuff, ULONG dwNumBytes)
{
	ULONG i;
	ULONG dwNumWords;
	USHORT usData;

	dwNumWords = (dwNumBytes + 1)/sizeof(USHORT);
	if (pPageBuff)
	{	// Handle unaligned buffer
		if (((ULONG)pPageBuff) & 0x1)
		{
	        for(i=0; i<dwNumWords; i++) 
	        {
				usData = NF_DATA_R();
				pPageBuff[i*2] = (usData & 0xff);
				pPageBuff[i*2+1] = (usData >> 8) & 0xff;
	        }
		}  else
		{
	        for(i=0; i<dwNumWords; i++) 
	        {
	            ((USHORT *)pPageBuff)[i] = NF_DATA_R();
	        }
		}
	}  else
	{
        //  Advance the read pointer
        for(i=0; i<dwNumWords; i++) 
        {
            usData = NF_DATA_R();
        }
	}
}

///////////////////////////////////////////////////////////////////////////
//
//  NAND_SimpleWrite
//
//  Write data into the Page. The current implementation only handles
//  one Page at a time.
//
///////////////////////////////////////////////////////////////////////////
void NAND_SimpleWrite(LPBYTE pPageBuff, ULONG dwNumBytes)
{
	ULONG i;
	ULONG dwNumWrites;

	//NOTE: This hardware is odd: only a byte can be written at a time and it must reside in the
	//upper byte of a USHORT.
	dwNumWrites = (dwNumBytes + 1)/sizeof(USHORT);	
	
	if (pPageBuff) 
	{
		//  Special case to handle un-aligned buffer pointer.
	    for(i=0; i<dwNumWrites; i++) 
	    {
			NF_DATA_W( ((USHORT *)pPageBuff)[i] );
		}
	}  else 
	{
		// Make sure we advance the Flash's write pointer (even though we aren't writing real data)
		for(i=0; i<dwNumWrites; i++)
		{
            NF_DATA_W(0xffff);
		}
	}

⌨️ 快捷键说明

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