nandflash.c

Go to the documentation of this file.
00001 /**************************************************************************/
00036 #include <stddef.h>
00037 
00038 #include "em_device.h"
00039 #include "em_dma.h"
00040 #include "em_ebi.h"
00041 #include "dmactrl.h"
00042 #include "nandflash.h"
00043 
00044 /**************************************************************************/
00060 /* Define how NAND flash control signals is connected to the EFM32GG. */
00061 #define NAND_POWER_PORT         1
00062 #define NAND_POWER_PIN          (1 << 15)
00063 #define NAND_READY_PORT         3
00064 #define NAND_READY_PIN          (1 << 15)
00065 #define NAND_CE_PORT            3
00066 #define NAND_CE_PIN             (1 << 14)
00067 #define NAND_WP_PORT            3
00068 #define NAND_WP_PIN             (1 << 13)
00069 #define NAND_ALE_BIT            24
00070 #define NAND_CLE_BIT            25
00071 
00072 /* Values secifically for Numonyx NAND256W3A. */
00073 #define NAND256W3A_SIGNATURE    0x7520
00074 #define NAND256W3A_SIZE         (32 * 1024 * 1024)
00075 #define NAND256W3A_PAGESIZE     512
00076 #define NAND256W3A_BLOCKSIZE    (16 * 1024)
00077 
00078 /* Generic NAND flash definitions. */
00079 #define NAND_PAGEADDR_MASK      (NAND256W3A_PAGESIZE - 1)
00080 #define NAND_BLOCKADDR_MASK     (NAND256W3A_BLOCKSIZE - 1)
00081 
00082 #define NAND_RDA_CMD            0x00
00083 #define NAND_RDB_CMD            0x01
00084 #define NAND_RDC_CMD            0x50
00085 #define NAND_RDSIGN_CMD         0x90
00086 #define NAND_RDSTATUS_CMD       0x70
00087 #define NAND_PAGEPROG1_CMD      0x80
00088 #define NAND_PAGEPROG2_CMD      0x10
00089 #define NAND_CPBPROG1_CMD       0x00
00090 #define NAND_CPBPROG2_CMD       0x8A
00091 #define NAND_CPBPROG3_CMD       0x10
00092 #define NAND_BLOCKERASE1_CMD    0x60
00093 #define NAND_BLOCKERASE2_CMD    0xD0
00094 #define NAND_RST_CMD            0xFF
00095 
00096 #define NAND_STATUS_SR7         0x80
00097 #define NAND_STATUS_SR6         0x40
00098 #define NAND_STATUS_SR0         0x01
00099 
00100 /* NAND access macros. */
00101 #define NAND_DATA8              *pNandData8
00102 #define NAND_DATA16             *pNandData16
00103 #define NAND_DATA32             *pNandData32
00104 #define NAND_ADDR               *pNandAddr
00105 #define NAND_CMD                *pNandCmd
00106 
00107 /* DMA configuration structures. */
00108 static const DMA_Init_TypeDef dmaInit =
00109 {
00110   .hprot        = 0,
00111   .controlBlock = dmaControlBlock
00112 };
00113 
00114 static const DMA_CfgChannel_TypeDef chnCfg =
00115 {
00116   .highPri   = false,     /* Default priority */
00117   .enableInt = false,     /* No interrupt on transfer completion */
00118   .select    = 0,         /* Memory-memory transfers */
00119   .cb        = NULL       /* No transfer completion callback */
00120 };
00121 
00122 static const DMA_CfgDescr_TypeDef descCfgWr =
00123 {
00124   .dstInc  = dmaDataIncNone,
00125   .srcInc  = dmaDataInc4,
00126   .size    = dmaDataSize4,
00127   .arbRate = dmaArbitrate1,
00128   .hprot   = 0
00129 };
00130 
00131 static const DMA_CfgDescr_TypeDef descCfgRd =
00132 {
00133   .dstInc  = dmaDataInc4,
00134   .srcInc  = dmaDataIncNone,
00135   .size    = dmaDataSize4,
00136   .arbRate = dmaArbitrate1,
00137   .hprot   = 0
00138 };
00139 
00140 /* Private variables. */
00141 static NANDFLASH_Info_TypeDef flashInfo;
00142 static bool                   flashInitialized = false;
00143 
00144 static uint8_t volatile       *pNandData8;
00145 static uint16_t volatile      *pNandData16;
00146 static uint32_t volatile      *pNandData32;
00147 static uint8_t volatile       *pNandAddr;
00148 static uint8_t volatile       *pNandCmd;
00149 
00150 /* Private function prototypes. */
00151 __STATIC_INLINE void      chipEnable(bool enable);
00152 static int       flashInterrogate(void);
00153 __STATIC_INLINE void      powerEnable(bool enable);
00154 static uint16_t  readSignature(void);
00155 static uint8_t   readStatus(void);
00156 static void      reset(void);
00157 static void      dmaRead(uint8_t *dst, int count);
00158 static void      dmaWrite(uint8_t *src, int count);
00159 __STATIC_INLINE void      waitReady(void);
00160 __STATIC_INLINE void      writeProtect(bool enable);
00161 
00164 /***************************************************************************/
00174 bool NANDFLASH_AddressValid(uint32_t address)
00175 {
00176   if (flashInitialized)
00177   {
00178     if ((address >= flashInfo.baseAddress) &&
00179         (address < (flashInfo.baseAddress + flashInfo.deviceSize)))
00180     {
00181       return true;
00182     }
00183   }
00184 
00185   return false;
00186 }
00187 
00188 /***************************************************************************/
00206 int NANDFLASH_CopyPage(uint32_t dstAddr, uint32_t srcAddr)
00207 {
00208   int status;
00209 
00210   if (!flashInitialized)
00211   {
00212     EFM_ASSERT(false);
00213     return NANDFLASH_NOT_INITIALIZED;
00214   }
00215 
00216   dstAddr &= ~NAND_PAGEADDR_MASK;
00217   srcAddr &= ~NAND_PAGEADDR_MASK;
00218 
00219   if (!NANDFLASH_AddressValid(dstAddr) ||
00220       !NANDFLASH_AddressValid(srcAddr) ||
00221       /* Address bit 24 must be equal for source and destination page. */
00222       ((dstAddr & (1 << 24)) != (srcAddr & (1 << 24))))
00223   {
00224     EFM_ASSERT(false);
00225     return NANDFLASH_INVALID_ADDRESS;
00226   }
00227 
00228   writeProtect(false);
00229   chipEnable(true);
00230 
00231   NAND_CMD  = NAND_CPBPROG1_CMD;
00232   NAND_ADDR = (uint8_t) srcAddr;
00233   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00234   NAND_ADDR = (uint8_t)(srcAddr >> 9);
00235   NAND_ADDR = (uint8_t)(srcAddr >> 17);
00236 
00237   waitReady();
00238 
00239   NAND_CMD  = NAND_CPBPROG2_CMD;
00240   NAND_ADDR = (uint8_t) dstAddr;
00241   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00242   NAND_ADDR = (uint8_t)(dstAddr >> 9);
00243   NAND_ADDR = (uint8_t)(dstAddr >> 17);
00244   NAND_CMD  = NAND_CPBPROG3_CMD;
00245 
00246   waitReady();
00247 
00248   status = (readStatus() & NAND_STATUS_SR0) ?
00249            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00250 
00251   chipEnable(false);
00252   writeProtect(true);
00253 
00254   return status;
00255 }
00256 
00257 /***************************************************************************/
00266 NANDFLASH_Info_TypeDef *NANDFLASH_DeviceInfo(void)
00267 {
00268   if (flashInitialized)
00269   {
00270     return &flashInfo;
00271   }
00272   return NULL;
00273 }
00274 
00275 /***************************************************************************/
00293 int NANDFLASH_EccCorrect(uint32_t generatedEcc, uint32_t readEcc, uint8_t *data)
00294 {
00296   #define ECC_MASK24    0x00FFFFFF          /* 24 valid ECC parity bits. */
00297   #define ECC_MASK      0x00555555          /* 12 ECC parity bits.       */
00298 
00300   int      count, bitNum, byteAddr;
00301   uint32_t mask;
00302   uint32_t syndrome;
00303   uint32_t eccP;                            /* 12 even ECC parity bits. */
00304   uint32_t eccPn;                           /* 12 odd ECC parity bits.  */
00305 
00306   syndrome = (generatedEcc ^ readEcc) & ECC_MASK24;
00307 
00308   if (syndrome == 0)
00309     return NANDFLASH_STATUS_OK;             /* No errors in data. */
00310 
00311   eccPn = syndrome & ECC_MASK;              /* Get twelve odd parity bits.  */
00312   eccP  = (syndrome >> 1) & ECC_MASK;       /* Get twelve even parity bits. */
00313 
00314   if ((eccPn ^ eccP) == ECC_MASK)           /* 1-bit correctable error ? */
00315   {
00316     bitNum = (eccP & 0x01) |
00317              ((eccP >> 1) & 0x02) |
00318              ((eccP >> 2) & 0x04);
00319 
00320     byteAddr = ((eccP >> 6) & 0x001) |
00321                ((eccP >> 7) & 0x002) |
00322                ((eccP >> 8) & 0x004) |
00323                ((eccP >> 9) & 0x008) |
00324                ((eccP >> 10) & 0x010) |
00325                ((eccP >> 11) & 0x020) |
00326                ((eccP >> 12) & 0x040) |
00327                ((eccP >> 13) & 0x080) |
00328                ((eccP >> 14) & 0x100);
00329 
00330     data[ byteAddr ] ^= 1 << bitNum;
00331 
00332     return NANDFLASH_STATUS_OK;
00333   }
00334 
00335   /* Count number of one's in the syndrome. */
00336   count = 0;
00337   mask  = 0x00800000;
00338   while (mask)
00339   {
00340     if (syndrome & mask)
00341       count++;
00342     mask >>= 1;
00343   }
00344 
00345   if (count == 1)                           /* Error in the ECC itself. */
00346     return NANDFLASH_ECC_ERROR;
00347 
00348   return NANDFLASH_ECC_UNCORRECTABLE;       /* Unable to correct data. */
00349 
00351   #undef ECC_MASK
00352   #undef ECC_MASK24
00353 
00354 }
00355 
00356 /***************************************************************************/
00371 int NANDFLASH_EraseBlock(uint32_t address)
00372 {
00373   int status;
00374 
00375   if (!flashInitialized)
00376   {
00377     EFM_ASSERT(false);
00378     return NANDFLASH_NOT_INITIALIZED;
00379   }
00380 
00381   address &= ~NAND_BLOCKADDR_MASK;
00382 
00383   if (!NANDFLASH_AddressValid(address))
00384   {
00385     EFM_ASSERT(false);
00386     return NANDFLASH_INVALID_ADDRESS;
00387   }
00388 
00389   writeProtect(false);
00390   chipEnable(true);
00391 
00392   NAND_CMD = NAND_BLOCKERASE1_CMD;
00393   /* Coloumn address, bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00394   NAND_ADDR = (uint8_t)(address >> 9);
00395   NAND_ADDR = (uint8_t)(address >> 17);
00396   NAND_CMD  = NAND_BLOCKERASE2_CMD;
00397 
00398   waitReady();
00399 
00400   status = (readStatus() & NAND_STATUS_SR0) ?
00401            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00402 
00403   chipEnable(false);
00404   writeProtect(true);
00405 
00406   return status;
00407 }
00408 
00409 /***************************************************************************/
00425 int NANDFLASH_Init(int dmaCh)
00426 {
00427   if ((dmaCh < -1) || (dmaCh >= DMA_CHAN_COUNT))
00428   {
00429     EFM_ASSERT(false);
00430     return NANDFLASH_INVALID_SETUP;
00431   }
00432 
00433   flashInfo.dmaCh = dmaCh;
00434 
00435   if (dmaCh >= 0)
00436   {
00437     DMA_Init((void*) &dmaInit);              /* Initialize the DMA */
00438     DMA_CfgChannel(dmaCh, (void*) &chnCfg);  /* Configure the DMA channel */
00439   }
00440 
00441   return flashInterrogate();
00442 }
00443 
00444 /***************************************************************************/
00460 int NANDFLASH_MarkBadBlock(uint32_t address)
00461 {
00462   if (!flashInitialized)
00463   {
00464     EFM_ASSERT(false);
00465     return NANDFLASH_NOT_INITIALIZED;
00466   }
00467 
00468   address &= ~NAND_BLOCKADDR_MASK;
00469 
00470   if (!NANDFLASH_AddressValid(address))
00471   {
00472     EFM_ASSERT(false);
00473     return NANDFLASH_INVALID_ADDRESS;
00474   }
00475 
00476   writeProtect(false);
00477   chipEnable(true);
00478 
00479   NAND_CMD  = NAND_RDC_CMD;
00480   NAND_CMD  = NAND_PAGEPROG1_CMD;
00481   NAND_ADDR = (uint8_t) address;
00482   /* Address bit 8 is not used, implicitely defined by NAND_RDC_CMD. */
00483   NAND_ADDR = (uint8_t)(address >> 9);
00484   NAND_ADDR = (uint8_t)(address >> 17);
00485 
00486   /* Write bad block marker 0x00 to the 6th byte in the spare area */
00487   NAND_DATA32 = 0xFFFFFFFF;
00488   NAND_DATA16 = 0x00FF;
00489   NAND_CMD    = NAND_PAGEPROG2_CMD;
00490 
00491   waitReady();
00492   readStatus();
00493 
00494   chipEnable(false);
00495   writeProtect(true);
00496 
00497   return NANDFLASH_STATUS_OK;
00498 }
00499 
00500 /***************************************************************************/
00518 int NANDFLASH_ReadPage(uint32_t address, uint8_t *buffer)
00519 {
00520   uint32_t i, readEcc, *p;
00521 
00522   if (!flashInitialized)
00523   {
00524     EFM_ASSERT(false);
00525     return NANDFLASH_NOT_INITIALIZED;
00526   }
00527 
00528   address &= ~NAND_PAGEADDR_MASK;
00529 
00530   if (!NANDFLASH_AddressValid(address))
00531   {
00532     EFM_ASSERT(false);
00533     return NANDFLASH_INVALID_ADDRESS;
00534   }
00535 
00536   chipEnable(true);
00537 
00538   NAND_CMD  = NAND_RDA_CMD;
00539   NAND_ADDR = (uint8_t) address;
00540   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00541   NAND_ADDR = (uint8_t)(address >> 9);
00542   NAND_ADDR = (uint8_t)(address >> 17);
00543 
00544   waitReady();
00545 
00546   EBI_StartNandEccGen();
00547 
00548   if (flashInfo.dmaCh == -1)
00549   {
00550     p = (uint32_t*) buffer;
00551     for (i = 0; i < flashInfo.pageSize / 4; i++)
00552     {
00553       *p++ = NAND_DATA32;
00554     }
00555   }
00556   else
00557   {
00558     dmaRead(buffer, flashInfo.pageSize);
00559   }
00560 
00561   flashInfo.ecc = EBI_StopNandEccGen();
00562 
00563   if (flashInfo.dmaCh == -1)
00564   {
00565     p = (uint32_t*) flashInfo.spare;
00566     for (i = 0; i < flashInfo.spareSize / 4; i++)
00567     {
00568       *p++ = NAND_DATA32;
00569     }
00570   }
00571   else
00572   {
00573     dmaRead(flashInfo.spare, flashInfo.spareSize);
00574   }
00575 
00576   chipEnable(false);
00577 
00578   readEcc  = flashInfo.spare[ NAND_SPARE_ECC0_POS ];
00579   readEcc += flashInfo.spare[ NAND_SPARE_ECC1_POS ] << 8;
00580   readEcc += flashInfo.spare[ NAND_SPARE_ECC2_POS ] << 16;
00581 
00582   return NANDFLASH_EccCorrect(flashInfo.ecc, readEcc, buffer);
00583 }
00584 
00585 /***************************************************************************/
00599 int NANDFLASH_ReadSpare(uint32_t address, uint8_t *buffer)
00600 {
00601   uint32_t i, *p;
00602 
00603   if (!flashInitialized)
00604   {
00605     EFM_ASSERT(false);
00606     return NANDFLASH_NOT_INITIALIZED;
00607   }
00608 
00609   address &= ~NAND_PAGEADDR_MASK;
00610 
00611   if (!NANDFLASH_AddressValid(address))
00612   {
00613     EFM_ASSERT(false);
00614     return NANDFLASH_INVALID_ADDRESS;
00615   }
00616 
00617   chipEnable(true);
00618 
00619   NAND_CMD  = NAND_RDC_CMD;
00620   NAND_ADDR = (uint8_t) address;
00621   /* Address bit 8 is not used, implicitely defined by NAND_RDC_CMD. */
00622   NAND_ADDR = (uint8_t)(address >> 9);
00623   NAND_ADDR = (uint8_t)(address >> 17);
00624 
00625   waitReady();
00626 
00627   if (flashInfo.dmaCh == -1)
00628   {
00629     p = (uint32_t*) buffer;
00630     for (i = 0; i < flashInfo.spareSize / 4; i++)
00631     {
00632       *p++ = NAND_DATA32;
00633     }
00634   }
00635   else
00636   {
00637     dmaRead(buffer, flashInfo.spareSize);
00638   }
00639 
00640   chipEnable(false);
00641 
00642   return NANDFLASH_STATUS_OK;
00643 }
00644 
00645 /***************************************************************************/
00664 int NANDFLASH_WritePage(uint32_t address, uint8_t *buffer)
00665 {
00666   int      status;
00667   uint32_t i, *p;
00668 
00669   if (!flashInitialized)
00670   {
00671     EFM_ASSERT(false);
00672     return NANDFLASH_NOT_INITIALIZED;
00673   }
00674 
00675   address &= ~NAND_PAGEADDR_MASK;
00676 
00677   if (!NANDFLASH_AddressValid(address))
00678   {
00679     EFM_ASSERT(false);
00680     return NANDFLASH_INVALID_ADDRESS;
00681   }
00682 
00683   writeProtect(false);
00684   chipEnable(true);
00685 
00686   NAND_CMD  = NAND_RDA_CMD;
00687   NAND_CMD  = NAND_PAGEPROG1_CMD;
00688   NAND_ADDR = (uint8_t) address;
00689   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00690   NAND_ADDR = (uint8_t)(address >> 9);
00691   NAND_ADDR = (uint8_t)(address >> 17);
00692 
00693   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00694   while (EBI->STATUS & EBI_STATUS_AHBACT)
00695   {
00696   }
00697   EBI_StartNandEccGen();
00698 
00699   if (flashInfo.dmaCh == -1)
00700   {
00701     p = (uint32_t*) buffer;
00702     for (i = 0; i < flashInfo.pageSize / 4; i++)
00703     {
00704       NAND_DATA32 = *p++;
00705     }
00706   }
00707   else
00708   {
00709     dmaWrite(buffer, flashInfo.pageSize);
00710   }
00711 
00712   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00713   while (EBI->STATUS & EBI_STATUS_AHBACT)
00714   {
00715   }
00716   flashInfo.ecc = EBI_StopNandEccGen();
00717 
00718   /* Write ECC to spare area */
00719   NAND_DATA32 = 0xFFFFFFFF;
00720   NAND_DATA16 = 0xFFFF;
00721   NAND_DATA8  = flashInfo.ecc;
00722   NAND_DATA8  = flashInfo.ecc >> 8;
00723   NAND_DATA8  = flashInfo.ecc >> 16;
00724   NAND_CMD    = NAND_PAGEPROG2_CMD;
00725 
00726   waitReady();
00727 
00728   status = (readStatus() & NAND_STATUS_SR0) ?
00729            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00730 
00731   chipEnable(false);
00732   writeProtect(true);
00733 
00734   return status;
00735 }
00736 
00739 /***************************************************************************/
00742 __STATIC_INLINE void chipEnable(bool enable)
00743 {
00744   if (enable)
00745   {
00746     GPIO->P[NAND_CE_PORT].DOUTCLR = NAND_CE_PIN;
00747   }
00748   else
00749   {
00750     GPIO->P[NAND_CE_PORT].DOUTSET = NAND_CE_PIN;
00751   }
00752 }
00753 
00754 /***************************************************************************/
00757 static int flashInterrogate(void)
00758 {
00759   flashInfo.baseAddress = EBI_BankAddress(EBI_BANK0);
00760 
00761   pNandData8  = (uint8_t volatile*) flashInfo.baseAddress;
00762   pNandData16 = (uint16_t volatile*) pNandData8;
00763   pNandData32 = (uint32_t volatile*) pNandData8;
00764   pNandAddr   = pNandData8 + (1 << NAND_ALE_BIT);
00765   pNandCmd    = pNandData8 + (1 << NAND_CLE_BIT);
00766 
00767   powerEnable(true);
00768   waitReady();
00769   chipEnable(true);
00770   reset();
00771 
00772   if (readSignature() != NAND256W3A_SIGNATURE)
00773   {
00774     EFM_ASSERT(false);
00775     return NANDFLASH_INVALID_DEVICE;
00776   }
00777 
00778   chipEnable(false);
00779 
00780   flashInfo.manufacturerCode = (uint8_t) NAND256W3A_SIGNATURE;
00781   flashInfo.deviceCode       = (uint8_t)(NAND256W3A_SIGNATURE >> 8);
00782   flashInfo.deviceSize       = NAND256W3A_SIZE;
00783   flashInfo.pageSize         = NAND256W3A_PAGESIZE;
00784   flashInfo.spareSize        = NAND256W3A_SPARESIZE;
00785   flashInfo.blockSize        = NAND256W3A_BLOCKSIZE;
00786 
00787   flashInitialized = true;
00788 
00789   return NANDFLASH_STATUS_OK;
00790 }
00791 
00792 /***************************************************************************/
00795 __STATIC_INLINE void powerEnable(bool enable)
00796 {
00797   if (enable)
00798   {
00799     GPIO->P[NAND_POWER_PORT].DOUTSET = NAND_POWER_PIN;
00800   }
00801   else
00802   {
00803     GPIO->P[NAND_POWER_PORT].DOUTCLR = NAND_POWER_PIN;
00804   }
00805 }
00806 
00807 /***************************************************************************/
00810 static uint16_t readSignature(void)
00811 {
00812   NAND_CMD = NAND_RDSIGN_CMD;
00813   return NAND_DATA16;
00814 }
00815 
00816 /***************************************************************************/
00819 static uint8_t readStatus(void)
00820 {
00821   NAND_CMD = NAND_RDSTATUS_CMD;
00822   return NAND_DATA8;
00823 }
00824 
00825 /***************************************************************************/
00828 static void reset(void)
00829 {
00830   NAND_CMD = NAND_RST_CMD;
00831   waitReady();
00832 }
00833 
00834 /***************************************************************************/
00837 static void dmaRead(uint8_t *dst, int count)
00838 {
00839   DMA_CfgDescr(flashInfo.dmaCh, true, (void*) &descCfgRd);
00840   DMA_ActivateAuto(flashInfo.dmaCh, true, dst, (void*) pNandData32, (count / 4) - 1);
00841   while ((dmaControlBlock[flashInfo.dmaCh].CTRL & _DMA_CTRL_CYCLE_CTRL_MASK)
00842          != DMA_CTRL_CYCLE_CTRL_INVALID)
00843   {
00844   }
00845 }
00846 
00847 /***************************************************************************/
00850 static void dmaWrite(uint8_t *src, int count)
00851 {
00852   DMA_CfgDescr(flashInfo.dmaCh, true, (void*) &descCfgWr);
00853   DMA_ActivateAuto(flashInfo.dmaCh, true, (void*) pNandData32, src, (count / 4) - 1);
00854   while ((dmaControlBlock[flashInfo.dmaCh].CTRL & _DMA_CTRL_CYCLE_CTRL_MASK)
00855          != DMA_CTRL_CYCLE_CTRL_INVALID)
00856   {
00857   }
00858 }
00859 
00860 /***************************************************************************/
00863 __STATIC_INLINE void waitReady(void)
00864 {
00865   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00866   while (EBI->STATUS & EBI_STATUS_AHBACT)
00867   {
00868   }
00869   /* Wait on Ready/Busy pin to become high */
00870   while ((GPIO->P[NAND_READY_PORT].DIN & NAND_READY_PIN) == 0)
00871   {
00872   }
00873 }
00874 
00875 /***************************************************************************/
00878 __STATIC_INLINE void writeProtect(bool enable)
00879 {
00880   if (enable)
00881   {
00882     GPIO->P[NAND_WP_PORT].DOUTCLR = NAND_WP_PIN;
00883   }
00884   else
00885   {
00886     GPIO->P[NAND_WP_PORT].DOUTSET = NAND_WP_PIN;
00887   }
00888 }
00889