最近在看wince5.0 的bootloader的block0image即nboot的源代码。。在NBL1的nand.c文件中有个CorrectECC8Data(unsigned char *pEncodingBaseAddr)。。这个函数如果检测到了不可矫正的位错误就会返回1。。。。返回1时。。NAND_Read函数就返回false。。。然后NBL1读取NBL2就失败了。。但是我把NAND_Read函数那边retrun flase;屏蔽掉后系统能读到NBL2。。。也能正常启动。。。我用的flash是三星的K9GAG08U0M...(4k+128byte)页大小的。。
现在我的问题是:
1、不是说存放block0image的flash的第一块是保证是可用块的。。那还需要ecc校验吗?
2、那我把那个ecc校验的代码按代码注释的地方屏蔽掉后。。系统可以正常启动。。那这个校验有什么作用呢?
望大家给个指点。。小弟感激不尽。。。
- C/C++ code
//NBL1中读取Nbl2的代码//K9GAG08U0M为mlc的flash NAND_Init(); Read_DeviceID(0, &ucDID, &ucHID); Uart_SendString("Device ID : 0x"); Uart_SendBYTE(ucDID, 1); Uart_SendString("Hidden ID : 0x"); Uart_SendBYTE(ucHID, 1); if ((ucDID == 0xd5 && ucHID == 0x14) || (ucDID == 0xd5 && ucHID == 0x94) || (ucDID == 0xd7 && ucHID == 0x55) // for MLC || (ucDID == 0xd3 && ucHID == 0x10) || (ucDID == 0xd7 && ucHID == 0xd5)) // for SLC { b4KPage = TRUE; uNumOfLoadPage = LOAD_PAGE_SIZE/2; } // Turn the LEDs off.// Led_Display(LED_OFF);// pBuf = (unsigned char *)LOAD_ADDRESS_PHYSICAL;// while(1); // MLC // Page 0, 1 : Steploader // Page 2 ~ 5 : empty page // Page 6 ~ PAGES_PER_BLOCK-3 : effective page // read pages with 0, 1 and 6 to PAGES_PER_BLOCK-3#ifdef SUPPORTSLC nPage = LOAD_IMAGE_PAGE_OFFSET;#endif#ifdef SUPPORTMLC nPage = 10;#endif for (nCnt = 0; nCnt < uNumOfLoadPage; nCnt++) { if (nPage >= (NAND_PAGE_PER_BLOCK-2) || (NAND_Read(0, nPage, pBuf, b4KPage) == FALSE)) { // Uncorrectable ECC Error Uart_SendString("ECC Error @ Page 0x"); Uart_SendBYTE(nPage, 1); //Led_Display(0x9); while(1); //NAND_Read 返回false 后就直接死循环 } nPage++; if (b4KPage == TRUE) pBuf += NAND_BYTE_PER_PAGE*2; else pBuf += NAND_BYTE_PER_PAGE; }
- C/C++ code
//NAND_Read函数和 CorrectECC8Data函数的实现。。。//BOOL NAND_Read(DWORD dwBank, DWORD dwPage, unsigned char *pBuf, BOOL b4KPage){ DWORD SpareDataDummy; DWORD dwOffset; DWORD dwCnt; DWORD dwSpareAddress = 2048 + 1; //include Bad block unsigned char uSctCnt; BOOL bRet = TRUE; if (b4KPage == TRUE) uSctCnt = 8; else uSctCnt = 4; rNFCONF = ( rNFCONF&~(0x3<<23) ) |(2<<30)|(1<<23)|(0x7<<12)|(0x7<<8)|(0x7<<4); rNFCONT = ( rNFCONT&~(0x1<<18) ) |(0<<18)|(0<<11)|(0<<10)|(0<<9)|(1<<6)|(1<<0); // Init NFCONT rNFSTAT |= ((1<<6)|(1<<5)|(1<<4)); NAND_Reset(dwBank); NF_MECC_Lock(); // Main ECC Lock NF_CE_L(dwBank); rNFSTAT |= (1<<4); // RnB Clear NF_CMD(CMD_READ); NF_SET_ADDR(dwPage, 0x00); NF_CMD(CMD_READ_CONFIRM); NF_DETECT_RB(); rNFSTAT |= (1<<4); // RnB Clear //READ Spare ECC Data for(dwCnt = 0; dwCnt < uSctCnt; dwCnt++) { NF_MECC_Lock(); // Main ECC Lock rNFSTAT |= (1<<4); // RnB Clear if(!dwCnt) { NF_CMD(CMD_READ); NF_SET_ADDR(dwPage, 0); NF_CMD(CMD_READ_CONFIRM); NF_DETECT_RB(); rNFSTAT |= (1<<4); // RnB Clear } else { dwOffset = dwCnt * 512; NF_CMD(CMD_RANDOM_DATA_OUTPUT); NF_ADDR(dwOffset&0xFF); NF_ADDR((dwOffset>>8)&0xFF); NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM); } NF_MECC_UnLock(); // Main ECC Unlock NF_MECC_Reset(); // Initialize ECC //read 512byte _Read_512Byte(pBuf + 512*dwCnt); if (b4KPage == TRUE) dwOffset = 4096 + (dwCnt * 13); else dwOffset = 2048 + (dwCnt * 13); NF_CMD(CMD_RANDOM_DATA_OUTPUT); NF_ADDR(dwOffset&0xFF); NF_ADDR((dwOffset>>8)&0xFF); NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM); //read Spare ECC Data SpareDataDummy = NF_DATA_R4(); SpareDataDummy = NF_DATA_R4(); SpareDataDummy = NF_DATA_R4(); SpareDataDummy = NF_DATA_R(); NF_MECC_Lock(); // Main ECC Lock while(!(rNFSTAT&(1<<6))); // Check decoding done rNFSTAT = rNFSTAT | (1<<6); // Decoding done Clear while( rNF8ECCERR0 & (unsigned int)(1<<31) ) ; // 8bit ECC Decoding Busy Check. if(CorrectECC8Data((pBuf + 512*dwCnt))) { // return FALSE; //这边注释掉后NBL1就可以正常读取NBL2。。且NBL2能正常执行。。读取eboot 并启动系统。。。//这边注释掉后CorrectECC8Data函数对于不能纠正的bit错误就没有返回了。。//如果数据有错没纠正。。那系统为什么还能启动? } } NF_CE_H(dwBank); return TRUE;}int CorrectECC8Data(unsigned char *pEncodingBaseAddr){ unsigned int i,uErrorByte[9]; unsigned char uErrorBit[9]; unsigned int uErrorType; uErrorType = (rNF8ECCERR0>>25)&0xf;// Searching Error Type //How many Error bits does exist? uErrorByte[1] = rNF8ECCERR0&0x3ff;// Searching Error Byte //Where is the error byte? uErrorByte[2] = (rNF8ECCERR0>>15)&0x3ff; uErrorByte[3] = (rNF8ECCERR1)&0x3ff; uErrorByte[4] = (rNF8ECCERR1>>11)&0x3ff; uErrorByte[5] = (rNF8ECCERR1>>22)&0x3ff; uErrorByte[6] = (rNF8ECCERR2)&0x3ff; uErrorByte[7] = (rNF8ECCERR2>>11)&0x3ff; uErrorByte[8] = (rNF8ECCERR2>>22)&0x3ff; uErrorBit[1] = rNFMLC8BITPT0&0xff;// Searching Error Bit //Where is the error bit? uErrorBit[2] = (rNFMLC8BITPT0>>8)&0xff; uErrorBit[3] = (rNFMLC8BITPT0>>16)&0xff; uErrorBit[4] = (rNFMLC8BITPT0>>24)&0xff; uErrorBit[5] = rNFMLC8BITPT1&0xff; uErrorBit[6] = (rNFMLC8BITPT1>>8)&0xff; uErrorBit[7] = (rNFMLC8BITPT1>>16)&0xff; uErrorBit[8] = (rNFMLC8BITPT1>>24)&0xff; if(uErrorType == 0x0) { return 0; } if(uErrorType == 0x9) { return 1; } for(i=1;i<=uErrorType ;i++) { if(uErrorByte[i] < 512) pEncodingBaseAddr[uErrorByte[i]]^=uErrorBit[i]; else {; } } return 0; }