/****************************************************************************/ /* */ /* 广州创龙电子科技有限公司 */ /* */ /* Copyright 2015 Tronlong All rights reserved */ /* */ /****************************************************************************/ /****************************************************************************/ /* */ /* NandFlash 读写测试 */ /* */ /* 2015年05月25日 */ /* */ /****************************************************************************/ #include "hw_emifa2.h" #include "hw_types.h" #include "soc_C6748.h" #include "uartStdio.h" #include "interrupt.h" #include "emifa.h" #include "nandlib.h" #include "nand_emifa2.h" #include "nandDma.h" #include "TL138.h" /****************************************************************************/ /* */ /* 宏定义 */ /* */ /****************************************************************************/ // 定义 NAND 数据线位宽,片选,页大小,块大小,设备ID #define NAND_DATA_XFER_MODE (NAND_XFER_MODE_DMA) #define NAND_BUSWIDTH (NAND_BUSWIDTH_8BIT) #define NAND_CHIP_SELECT (EMIFA_CHIP_SELECT_3) #define NAND_PAGE_SIZE_IN_BYTES (NAND_PAGESIZE_2048BYTES) #define NAND_BLOCK_SIZE_IN_BYTES (NAND_BLOCKSIZE_128KB) #define NAND_NUMOF_BLK (1024) #define NAND_MANUFATURER_MICRON_ID (0xEC) #define NAND_DEVICE_ID (0xF1) // 定义 NAND 读写大小,ECC 大小 #define NAND_DATA_BUFF_SIZE (NAND_PAGE_SIZE_IN_BYTES) #define NAND_ECC_BUFF_SIZE ((NAND_PAGE_SIZE_IN_BYTES/NAND_BYTES_PER_TRNFS) \ * NAND_MAX_ECC_BYTES_PER_TRNFS) // 定义默认读写的块,页和页数 #define NAND_DEFAULT_START_PAGE (5) #define NAND_DEFAULT_BLK (8) #define NAND_DEFAULT_NMBR_OF_PAGES (1) // 定义数据校验状态标志 #define NAND_DATA_INTEGRITY_PASS (0) #define NAND_DATA_INTEGRITY_FAIL (1) /* 定义 NAND 的时序信息 */ // 最大外部等待周期 #define NAND_MAX_EXT_WAIT (0xFF) // EMIFA 读写的 Setup,strobe,hold 的时间 #define NAND_WRITE_SETUP_TIME_IN_NS (0u) #define NAND_WRITE_STROBE_TIME_IN_NS (30u) #define NAND_WRITE_HOLD_TIME_IN_NS (30u) #define NAND_READ_SETUP_TIME_IN_NS (20u) #define NAND_READ_STROBE_TIME_IN_NS (40u) #define NAND_READ_HOLD_TIME_IN_NS (0u) #define NAND_TURN_ARND_TIME_IN_NS (0u) // 复位的 EMIFA 的 Setup,strobe,hold 时间 #define EMIFA_WRITE_SETUP_RESETVAL (0x0F) #define EMIFA_WRITE_STROBE_RESETVAL (0x3F) #define EMIFA_WRITE_HOLD_RESETVAL (0x07) #define EMIFA_READ_SETUP_RESETVAL (0x0F) #define EMIFA_READ_STROBE_RESETVAL (0x3F) #define EMIFA_READ_HOLD_RESETVAL (0x07) #define EMIFA_TA_RESETVAL (0x03) // NAND 模块时钟 #define NAND_MODULE_CLK ((91u)*(1000u)*(1000u)) #define NAND_MODULE_CLK_IN_MHZ (NAND_MODULE_CLK / 1000000) /****************************************************************************/ /* */ /* 全局变量 */ /* */ /****************************************************************************/ #pragma DATA_ALIGN(txData, 4); volatile unsigned char txData[NAND_DATA_BUFF_SIZE]; #pragma DATA_ALIGN(rxData, 4); volatile unsigned char rxData[NAND_DATA_BUFF_SIZE]; unsigned char eccData[NAND_ECC_BUFF_SIZE]; /****************************************************************************/ /* */ /* 初始化 NAND 的读写和 ecc 数据 */ /* */ /****************************************************************************/ static void NANDBuffersInit() { unsigned int byteCnt; txData[0] = 'S'; txData[1] = 'T'; txData[2] = 'A'; txData[3] = 'R'; txData[4] = 'T'; txData[5] = 'E'; txData[6] = 'R'; txData[7] = 'W'; txData[8] = 'A'; txData[9] = 'R'; txData[10] = 'E'; for(byteCnt = 11; byteCnt < NAND_PAGE_SIZE_IN_BYTES; byteCnt++) { txData[byteCnt]= ((byteCnt) & 0xFF); } for(byteCnt = 0; byteCnt < NAND_PAGE_SIZE_IN_BYTES; byteCnt++) { rxData[byteCnt]= 0x00; } for(byteCnt = 0; byteCnt < NAND_ECC_BUFF_SIZE; byteCnt++) { eccData[byteCnt] = 0; } } /****************************************************************************/ /* */ /* 对读写数据做比较校验 */ /* */ /* NAND_DATA_INTEGRITY_PASS -- On pass */ /* NAND_DATA_INTEGRITY_FAIL -- On fail */ /* */ /****************************************************************************/ static unsigned int NANDDataIntegrityCheck() { unsigned int status = NAND_DATA_INTEGRITY_PASS; unsigned int byteCnt; for(byteCnt = 0; byteCnt < NAND_PAGE_SIZE_IN_BYTES; byteCnt++) { if(rxData[byteCnt] != txData[byteCnt]) { status = NAND_DATA_INTEGRITY_FAIL; break; } } return (status); } /****************************************************************************/ /* */ /* 初始化 EMIF NAND 时序信息 */ /* */ /****************************************************************************/ static void NANDTimingInfoInit(void *TimingInfo) { int moduleClkInMHz = NAND_MODULE_CLK_IN_MHZ; EMIFANANDTimingInfo_t *nandTimingInfo; nandTimingInfo = (EMIFANANDTimingInfo_t * )TimingInfo; /* 设置异步等待时序 */ nandTimingInfo->writeSetup = (((moduleClkInMHz * NAND_WRITE_SETUP_TIME_IN_NS)/1000u) & EMIFA_WRITE_SETUP_RESETVAL); nandTimingInfo->writeStrobe = (((moduleClkInMHz * NAND_WRITE_STROBE_TIME_IN_NS)/1000u) & EMIFA_WRITE_STROBE_RESETVAL); nandTimingInfo->writeHold = (((moduleClkInMHz * NAND_WRITE_HOLD_TIME_IN_NS)/1000u) & EMIFA_WRITE_HOLD_RESETVAL); nandTimingInfo->readSetup = (((moduleClkInMHz * NAND_READ_SETUP_TIME_IN_NS)/1000u) & EMIFA_READ_SETUP_RESETVAL); nandTimingInfo->readStrobe = (((moduleClkInMHz * NAND_READ_STROBE_TIME_IN_NS)/1000u) & EMIFA_READ_STROBE_RESETVAL); nandTimingInfo->readHold = (((moduleClkInMHz * NAND_READ_HOLD_TIME_IN_NS)/1000u) & EMIFA_READ_HOLD_RESETVAL); nandTimingInfo->turnAround = (((moduleClkInMHz * NAND_TURN_ARND_TIME_IN_NS)/1000u) & EMIFA_TA_RESETVAL); } /****************************************************************************/ /* */ /* 初始化 NAND 的信息 */ /* */ /****************************************************************************/ static void NANDInfoInit(NandInfo_t *nandInfo, unsigned int cs) { NandCtrlInfo_t *hNandCtrlInfo = nandInfo->hNandCtrlInfo; NandDmaInfo_t *hNandDmaInfo = nandInfo->hNandDmaInfo; NandEccInfo_t *hNandEccInfo = nandInfo->hNandEccInfo; /* 初始化NAND设备信息 */ nandInfo->opMode = NAND_DATA_XFER_MODE; nandInfo->eccType = NAND_ECC_ALGO_RS_4BIT; nandInfo->chipSelectCnt = 1; nandInfo->dieCnt = 1; nandInfo->chipSelects[0] = cs; nandInfo->busWidth = NAND_BUSWIDTH; nandInfo->pageSize = NAND_PAGE_SIZE_IN_BYTES; nandInfo->blkSize = NAND_BLOCK_SIZE_IN_BYTES; nandInfo->manId = NAND_MANUFATURER_MICRON_ID; nandInfo->devId = NAND_DEVICE_ID; nandInfo->dataRegAddr = (SOC_EMIFA_CS3_ADDR + 0x00); nandInfo->addrRegAddr = (SOC_EMIFA_CS3_ADDR + 0x08); nandInfo->cmdRegAddr = (SOC_EMIFA_CS3_ADDR + 0x10); /* 初始化NAND控制器信息 */ hNandCtrlInfo->CtrlInit = EMIFANANDInit; hNandCtrlInfo->WaitPinStatusGet = EMIFANANDWaitPinStatusGet; hNandCtrlInfo->currChipSelect = cs; hNandCtrlInfo->baseAddr = SOC_EMIFA_0_REGS; hNandCtrlInfo->eccSupported = ( NAND_ECC_ALGO_HAMMING_1BIT | NAND_ECC_ALGO_RS_4BIT ); hNandCtrlInfo->waitPin = EMIFA_EMA_WAIT_PIN0; hNandCtrlInfo->waitPinPol = EMIFA_EMA_WAIT_PIN_POLARITY_HIGH; hNandCtrlInfo->wpPinPol = 0; hNandCtrlInfo->chipSelectBaseAddr[0] = SOC_EMIFA_CS3_ADDR; hNandCtrlInfo->chipSelectRegionSize[0] = EMIFA_CHIP_SELECT_3_SIZE; NANDTimingInfoInit(hNandCtrlInfo->hNandTimingInfo); /* 初始化NAND ECC信息 */ hNandEccInfo->baseAddr = 0; hNandEccInfo->ECCInit = EMIFANANDECCInit; hNandEccInfo->ECCEnable = EMIFANANDECCEnable; hNandEccInfo->ECCDisable = EMIFANANDECCDisable; hNandEccInfo->ECCWriteSet = EMIFANANDECCWriteSet; hNandEccInfo->ECCReadSet = EMIFANANDECCReadSet; hNandEccInfo->ECCCalculate = EMIFANANDECCCalculate; hNandEccInfo->ECCCheckAndCorrect = EMIFANANDECCCheckAndCorrect; /* 初始化NAND DMA信息 */ hNandDmaInfo->DMAXfer = EMIFANANDDMAXfer; hNandDmaInfo->DMAInit = EMIFANANDEdmaInit; hNandDmaInfo->DMAXferSetup = EMIFANANDXferSetup; hNandDmaInfo->DMAXferStatusGet = EMIFANANDXferStatusGet; } /****************************************************************************/ /* */ /* 主函数 */ /* */ /****************************************************************************/ #define SYS_BASE 0x01C14000 #define HOST0CFG *(volatile unsigned int*)(SYS_BASE + 0x040) //ARM HOST0CFG #define KICK0R *(volatile unsigned int*)(SYS_BASE + 0x038) #define KICK1R *(volatile unsigned int*)(SYS_BASE + 0x03c) #define PINMUX0 *(volatile unsigned int*)(SYS_BASE + 0x120) //PINMUX0 #define PINMUX1 *(volatile unsigned int*)(SYS_BASE + 0x124) //PINMUX1 #define PINMUX2 *(volatile unsigned int*)(SYS_BASE + 0x128) //PINMUX2 #define PINMUX3 *(volatile unsigned int*)(SYS_BASE + 0x12C) //PINMUX3 #define PINMUX4 *(volatile unsigned int*)(SYS_BASE + 0x130) //PINMUX4 #define PINMUX5 *(volatile unsigned int*)(SYS_BASE + 0x134) //PINMUX5 #define PINMUX6 *(volatile unsigned int*)(SYS_BASE + 0x138) //PINMUX6 #define PINMUX7 *(volatile unsigned int*)(SYS_BASE + 0x13C) //PINMUX7 #define PINMUX8 *(volatile unsigned int*)(SYS_BASE + 0x140) //PINMUX8 #define PINMUX9 *(volatile unsigned int*)(SYS_BASE + 0x144) //PINMUX9 #define PINMUX10 *(volatile unsigned int*)(SYS_BASE + 0x148) //PINMUX10 #define PINMUX11 *(volatile unsigned int*)(SYS_BASE + 0x14C) //PINMUX11 #define PINMUX12 *(volatile unsigned int*)(SYS_BASE + 0x150) //PINMUX12 #define PINMUX13 *(volatile unsigned int*)(SYS_BASE + 0x154) //PINMUX13 #define PINMUX14 *(volatile unsigned int*)(SYS_BASE + 0x158) //PINMUX14 #define PINMUX15 *(volatile unsigned int*)(SYS_BASE + 0x15C) //PINMUX15 #define PINMUX16 *(volatile unsigned int*)(SYS_BASE + 0x160) //PINMUX16 #define PINMUX17 *(volatile unsigned int*)(SYS_BASE + 0x164) //PINMUX17 #define PINMUX18 *(volatile unsigned int*)(SYS_BASE + 0x168) //PINMUX18 #define PINMUX19 *(volatile unsigned int*)(SYS_BASE + 0x16C) //PINMUX19 #define CFGCHIP0 *(volatile unsigned int*)(SYS_BASE + 0x17C) #define CFGCHIP2 *(volatile unsigned int*)(SYS_BASE + 0x184) #define CFGCHIP3 *(volatile unsigned int*)(SYS_BASE + 0x188) void PINMUX(void) { PINMUX0 = 0x88888888; PINMUX1 = 0x82828288; PINMUX2 = 0x88888888; PINMUX3 = 0x88888888; PINMUX4 = 0x22222288; PINMUX5 = 0x11118102; PINMUX6 = 0x11111111; PINMUX7 = 0x11111111; PINMUX8 = 0x11111111; PINMUX9 = 0x11111111; PINMUX10 = 0x11118888; PINMUX11 = 0x11111111; PINMUX12 = 0x11111111; PINMUX13 = 0x44448888; PINMUX14 = 0x44444488; PINMUX15 = 0x44444444; PINMUX16 = 0x88888844; PINMUX17 = 0x88888888; PINMUX18 = 0x88888888; PINMUX19 = 0x18888888; } int main(void) { int blkNum; int pageNum; int numOfPages; unsigned int retVal; unsigned int eraseBlkFlg; /* NAND的信息结构体申请 */ NandInfo_t nandInfo; NandCtrlInfo_t nandCtrlInfo; NandEccInfo_t nandEccInfo; NandDmaInfo_t nandDmaInfo; EMIFANANDTimingInfo_t nandTimingInfo; PINMUX(); /* Pin mux 和 clock 设置 */ EMIFAClkConfig(); NANDPinMuxSetup(); /* 初始化NAND信息结构体 */ nandCtrlInfo.hNandTimingInfo = (void *) &nandTimingInfo; nandInfo.hNandCtrlInfo = &nandCtrlInfo; nandInfo.hNandEccInfo = &nandEccInfo; nandInfo.hNandDmaInfo = &nandDmaInfo; NANDInfoInit(&nandInfo, NAND_CHIP_SELECT); /* 打开NAND设备 */ retVal = NANDOpen(&nandInfo); /* 对默认地址读写 */ pageNum = NAND_DEFAULT_START_PAGE; blkNum = NAND_DEFAULT_BLK; numOfPages = NAND_DEFAULT_NMBR_OF_PAGES; eraseBlkFlg = 1; while( numOfPages > 0 ) { if( eraseBlkFlg ) { retVal = NANDBlockErase(&nandInfo, blkNum); if( retVal == NAND_STATUS_PASSED ) { UARTPuts(" Succeeded.",-1); } else { NANDMarkBlockAsBad(&nandInfo, blkNum); blkNum++; pageNum = 0; eraseBlkFlg = 1; continue; } eraseBlkFlg = 0; } NANDBuffersInit(); retVal = NANDPageWrite(&nandInfo, blkNum, pageNum, &txData[0], &eccData[0]); if( (retVal & NAND_STATUS_WAITTIMEOUT) ) { // UARTPuts(" Failed.(Device Is Busy).", -1); while(1); } else if( (retVal & NAND_STATUS_DEVWRPROTECT) ) { // UARTPuts(" Failed.(Device Is Write Protected).", -1); while(1); } else if( (retVal & NAND_STATUS_READWRITE_DMA_FAIL) ) { // UARTPuts(" Failed.(EDMA Transfer Failed.).", -1); while(1); } else { UARTPuts(" Succeeded.", -1); } /* ECC数据初始化为与NANDPageWrite一样 */ NANDBuffersInit(); retVal= NANDPageRead(&nandInfo, blkNum, pageNum, &rxData[0], &eccData[0]); if( (retVal & NAND_STATUS_READ_ECC_ERROR_CORRECTED) ) { // UARTPuts(" Succeeded With ECC Errors And Corrected.", -1); } else if( (retVal & NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR) ) { // UARTPuts(" Failed.(Uncorrectable ECC errors) ", -1); while(1); } else if( (retVal & NAND_STATUS_READWRITE_DMA_FAIL) ) { // UARTPuts(" Failed.(EDMA Transfer Failed.)", -1); while(1); } else { // UARTPuts(" Succeeded.",-1); } // UARTPuts("\r\n NAND Data Integrity Test :", -1); retVal = NANDDataIntegrityCheck(); if(retVal == NAND_DATA_INTEGRITY_PASS) { UARTPuts(" Passed\r\n", -1); } else { UARTPuts(" Failed....!!!\r\n", -1); } pageNum++; numOfPages--; if( pageNum == ((nandInfo.pagesPerBlk) ) ) { pageNum = 0; eraseBlkFlg = 1; blkNum++; } } while(1); }