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

📄 flash_nand.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
📖 第 1 页 / 共 3 页
字号:
static const unsigned char _nand_ecc_precalc_table[] = {    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00};static void _nand_trans_result(unsigned char reg2, unsigned char reg3,                   unsigned char *ecc0, unsigned char *ecc1){    unsigned char a, b, i, tmp1, tmp2;	    /* Initialize variables */    a = b = 0x80;    tmp1 = tmp2 = 0;	    /* Calculate first ECC byte */    for (i = 0; i < 4; i++) {        if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */            tmp1 |= b;        b >>= 1;        if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */            tmp1 |= b;        b >>= 1;        a >>= 1;    }	    /* Calculate second ECC byte */    b = 0x80;    for (i = 0; i < 4; i++) {        if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */            tmp2 |= b;        b >>= 1;        if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */            tmp2 |= b;        b >>= 1;        a >>= 1;    }	    /* Store two of the ECC bytes */    *ecc0 = tmp1;        *ecc1 = tmp2;}//// Calculate 3 byte ECC on 256 bytes of data//static void_nand_page_ECC(unsigned char *data, unsigned char *ecc0,               unsigned char *ecc1, unsigned char *ecc2){    unsigned char idx, reg1, reg2, reg3;    int j;	    /* Initialize variables */    reg1 = reg2 = reg3 = 0;    *ecc0 = *ecc1 = *ecc2 = 0;	    /* Build up column parity */     for(j = 0; j < 256; j++) {        /* Get CP0 - CP5 from table */        idx = _nand_ecc_precalc_table[*data++];        reg1 ^= (idx & 0x3f);        /* All bit XOR = 1 ? */        if (idx & 0x40) {            reg3 ^= (unsigned char) j;            reg2 ^= ~((unsigned char) j);        }    }	    /* Create non-inverted ECC code from line parity */    _nand_trans_result(reg2, reg3, ecc0, ecc1);	    /* Calculate final ECC code */    *ecc0 = ~*ecc0;    *ecc1 = ~*ecc1;    *ecc2 = ((~reg1) << 2) | 0x03;}//// Correct a buffer via ECC (1 bit, 256 byte block)//  Return: 0 => No error//          1 => Corrected//          2 => Not corrected, ECC updated//         -1 => Not correctable//int _nand_correct_data(unsigned char *dat, unsigned char *read_ecc, unsigned char *calc_ecc){    unsigned char a, b, c, d1, d2, d3, add, bit, i;	    /* Do error detection */     d1 = calc_ecc[0] ^ read_ecc[0];    d2 = calc_ecc[1] ^ read_ecc[1];    d3 = calc_ecc[2] ^ read_ecc[2];	    if ((d1 | d2 | d3) == 0) {        /* No errors */        return 0;    } else {        a = (d1 ^ (d1 >> 1)) & 0x55;        b = (d2 ^ (d2 >> 1)) & 0x55;        c = (d3 ^ (d3 >> 1)) & 0x54;		        /* Found and will correct single bit error in the data */        if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {            c = 0x80;            add = 0;            a = 0x80;            for (i=0; i<4; i++) {                if (d1 & c)                    add |= a;                c >>= 2;                a >>= 1;            }            c = 0x80;            for (i=0; i<4; i++) {                if (d2 & c)                    add |= a;                c >>= 2;                a >>= 1;            }            bit = 0;            b = 0x04;            c = 0x80;            for (i=0; i<3; i++) {                if (d3 & c)                    bit |= b;                c >>= 2;                b >>= 1;            }            b = 0x01;            a = dat[add];            a ^= (b << bit);            dat[add] = a;            return 1;        } else {            i = 0;            while (d1) {                if (d1 & 0x01)                    ++i;                d1 >>= 1;            }            while (d2) {                if (d2 & 0x01)                    ++i;                d2 >>= 1;            }            while (d3) {                if (d3 & 0x01)                    ++i;                d3 >>= 1;            }            if (i == 1) {                /* ECC Code Error Correction */                read_ecc[0] = calc_ecc[0];                read_ecc[1] = calc_ecc[1];                read_ecc[2] = calc_ecc[2];                return 2;            } else {                /* Uncorrectable Error */                return -1;            }        }    }	    /* Should never happen */    return -1;}//----------------------------------------------------------------------------// Program Bufferstatic intflash_program_buf(void* addr, void* data, int len){	int res=FLASH_ERR_OK;	unsigned char *paddr=addr;	unsigned char *pdata=data;		while(len>0) {		if(StatusCheck(chip0_en, def_width)!=FAIL)		{			if( pagewrite(paddr,pdata,flash_dev_info->page_size) != PASS)				return FLASH_ERR_PROGRAM;			flash_delay();			len -= flash_dev_info->page_size;			paddr += flash_dev_info->page_size ;			pdata += flash_dev_info->page_size ;		}	}	return res;}//----------------------------------------------------------------------------// Read data into bufferintflash_read_buf(void* addr, void* buff, int len){	int i,res=FLASH_ERR_OK;	UINT8 read_buff[2048+64],*pbuff=(UINT8*)buff;		while(len>0){		if(StatusCheck(chip0_en, def_width)!=FAIL)		{			if(pageread((UINT64)addr,((len>=info_flash[4])?pbuff:read_buff))!=PASS){				res = FLASH_ERR_HWR;				break;			}        				//memcpy(pbuff,read_buff,(len>flash_dev_info->page_size)?flash_dev_info->page_size:len);			if(len < info_flash[4])				memcpy(pbuff,read_buff,(len>flash_dev_info->page_size)?flash_dev_info->page_size:len);						flash_delay();			len -= flash_dev_info->page_size;			addr += flash_dev_info->page_size;			pbuff += flash_dev_info->page_size;		}		}	return res;}int pageread(UINT64 page_add, UINT8* page_data){	UINT32 i,j,data,nwidth;//,po;	UINT8  *adr=page_add,ecc,ecc_byte,ecc_bit;	UINT8 dev_oob[64],oob[64];	nwidth = NFLASH_WiDTH8;		page_add -= 0x30000000;	page_add /= info_flash[5];		ADD5=ADD4=ADD3=ADD2=0;	//ndirect = 0;	//	nmode = 1 ;	ndirect = 0x4000;		nmode = 1 ;			if(info_flash[5] < 528)	{/*		ADD5=(UINT32)((page_add<<8)>>32);		ADD4=(UINT32)((page_add<<16)>>32);		ADD3=(UINT32)((page_add<<24)>>32);		ADD2=(UINT32)((page_add<<32)>>32);*/		ADD5 = (page_add & 0xff000000)>>24;		ADD4 = (page_add & 0x00ff0000)>>16;		ADD3 = (page_add & 0x0000ff00)>>8;		ADD2 = (page_add & 0x000000ff);    }    else    {		ADD5=(UINT32)((page_add<<16)>>32);		ADD4=(UINT32)((page_add<<24)>>32);		ADD3=(UINT32)((page_add<<32)>>32);		    }    		if(nmode == 2) ////DMA mode	{		FLASH_CTRL_WRITE_REG(NFLASH_FIFO_CONTROL, 0x8000); //clear fifo		FLASH_WRITE_DMA_REG(DMA_MAIN_CFG, 0x1); //enable DMA		FLASH_WRITE_DMA_REG(DMA_CH0_SRC_ADDR, 0x65888800); //src_address		FLASH_WRITE_DMA_REG(DMA_CH0_DST_ADDR, (UINT32)page_data); //dest_address		FLASH_WRITE_DMA_REG(DMA_CH0_LLP, 0x0); //LLP		FLASH_WRITE_DMA_REG(DMA_CH0_SIZE, (info_flash[4]/4)); //size		FLASH_WRITE_DMA_REG(DMA_CH0_CFG, 0x2); //CFG		FLASH_WRITE_DMA_REG(DMA_CH0_CSR, 0x112c3); //CSR	}    	//reset(chip0_en);	//FLASH_CTRL_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0	FLASH_CTRL_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0			if(ndirect==0x0)	{			if(info_flash[1]<64)		{		    FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x0f01ff20); //set only command & address and two data		    opcode = 0x00000000;		}		if(info_flash[1]>=64&&info_flash[1]<256)		{		    FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x3f07ff31); //set only command & address and two data		    opcode = 0x000003000;		}		if(info_flash[1]>256)		{		    FLASH_CTRL_WRITE_REG(NFLASH_COUNT, 0x3f07ff41); //set only command & address and two data		    opcode = 0x00003000;		}		opcode |= (ADD5<<24);		FLASH_CTRL_WRITE_REG(NFLASH_COMMAND_ADDRESS, opcode); //write address 0x00		    		opcode = 0x00000000|(ADD4<<24)|(ADD3<<16)|(ADD2<<8);		FLASH_CTRL_WRITE_REG(NFLASH_ADDRESS, opcode); //write address 0x00				if(nmode == 1) //indirect mode		{			for(i=0;i<info_flash[4];i++)			{				//hal_delay_us(1);				opcode = 0x80002000|chip0_en|nwidth|ndirect; //set start bit & 8bits read command				FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, opcode); 								while(opcode&0x80000000) //polling flash access 31b      				{        			   opcode=FLASH_CTRL_READ_REG(NFLASH_ACCESS);        			   flash_delay();      				}      				          			 	    data = FLASH_CTRL_READ_REG(NFLASH_DATA);          			 	    ///////////  		 	      			 	          			 	    if((i&0x03)==0x01)    						data>>=8;    					else if((i&0x03)==0x02)    						data>>=16;    					else if((i&0x03)==0x03)    						data>>=24;      			 	    page_data[i] = (UINT8)data;      			 	    //flash_delay();      			 	    data =0;			}		}		else if(nmode == 2) ////DMA mode		{			opcode = 0x00888800;			FLASH_CTRL_WRITE_REG(NFLASH_FIFO_ADDRESS, opcode); 			FLASH_CTRL_WRITE_REG(NFLASH_FIFO_CONTROL, 0x80002000);			opcode=FLASH_READ_DMA_REG(DMA_TC);      						while(!(opcode&0x01)) //polling flash access 31b      			{        		  opcode=FLASH_READ_DMA_REG(DMA_TC);         		  flash_delay();      			}	        opcode=FLASH_CTRL_READ_REG(NFLASH_FIFO_CONTROL); 						while(opcode&0x80000000) //polling flash access 31b      			{        		  opcode=FLASH_CTRL_READ_REG(NFLASH_FIFO_CONTROL);        		  flash_delay();      			}      		//Disable channel 0 DMA      		FLASH_WRITE_DMA_REG(DMA_CH0_CSR, 0x0);      		//DMA TC int status Rg      		//write clear int      		FLASH_WRITE_DMA_REG(DMA_INT_TC_CLR, 0x1);      		//Flash status Reg      		//write clear fifo_int      		FLASH_CTRL_WRITE_REG(FLASH_STATUS, 0x20000);		}		}	else //direct mode	{		FLASH_CTRL_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);		//memcpy(page_data, adr, info_flash[5]);		//memcpy(dev_oob, (adr+info_flash[5]), info_flash[6]);				//for(i=0;i<info_flash[5];i++)		for(i=0;i<info_flash[4];i++)		{			//hal_delay_us(7);			page_data[i] = *adr++;		}		/*

⌨️ 快捷键说明

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