nandflash.c

Go to the documentation of this file.
00001 /**************************************************************************/
00018 #include <stddef.h>
00019 
00020 #include "em_device.h"
00021 #include "em_dma.h"
00022 #include "em_ebi.h"
00023 #include "dmactrl.h"
00024 #include "nandflash.h"
00025 
00026 /**************************************************************************/
00042 /* Define how NAND flash control signals is connected to the EFM32GG. */
00043 #define NAND_POWER_PORT         1
00044 #define NAND_POWER_PIN          (1 << 15)
00045 #define NAND_READY_PORT         3
00046 #define NAND_READY_PIN          (1 << 15)
00047 #define NAND_CE_PORT            3
00048 #define NAND_CE_PIN             (1 << 14)
00049 #define NAND_WP_PORT            3
00050 #define NAND_WP_PIN             (1 << 13)
00051 #define NAND_ALE_BIT            24
00052 #define NAND_CLE_BIT            25
00053 
00054 /* Values secifically for Numonyx NAND256W3A. */
00055 #define NAND256W3A_SIGNATURE    0x7520
00056 #define NAND256W3A_SIZE         (32 * 1024 * 1024)
00057 #define NAND256W3A_PAGESIZE     512
00058 #define NAND256W3A_BLOCKSIZE    (16 * 1024)
00059 
00060 /* Generic NAND flash definitions. */
00061 #define NAND_PAGEADDR_MASK      (NAND256W3A_PAGESIZE - 1)
00062 #define NAND_BLOCKADDR_MASK     (NAND256W3A_BLOCKSIZE - 1)
00063 
00064 #define NAND_RDA_CMD            0x00
00065 #define NAND_RDB_CMD            0x01
00066 #define NAND_RDC_CMD            0x50
00067 #define NAND_RDSIGN_CMD         0x90
00068 #define NAND_RDSTATUS_CMD       0x70
00069 #define NAND_PAGEPROG1_CMD      0x80
00070 #define NAND_PAGEPROG2_CMD      0x10
00071 #define NAND_CPBPROG1_CMD       0x00
00072 #define NAND_CPBPROG2_CMD       0x8A
00073 #define NAND_CPBPROG3_CMD       0x10
00074 #define NAND_BLOCKERASE1_CMD    0x60
00075 #define NAND_BLOCKERASE2_CMD    0xD0
00076 #define NAND_RST_CMD            0xFF
00077 
00078 #define NAND_STATUS_SR7         0x80
00079 #define NAND_STATUS_SR6         0x40
00080 #define NAND_STATUS_SR0         0x01
00081 
00082 /* NAND access macros. */
00083 #define NAND_DATA8              *pNandData8
00084 #define NAND_DATA16             *pNandData16
00085 #define NAND_DATA32             *pNandData32
00086 #define NAND_ADDR               *pNandAddr
00087 #define NAND_CMD                *pNandCmd
00088 
00089 /* DMA configuration structures. */
00090 static const DMA_Init_TypeDef dmaInit =
00091 {
00092   .hprot        = 0,
00093   .controlBlock = dmaControlBlock
00094 };
00095 
00096 static const DMA_CfgChannel_TypeDef chnCfg =
00097 {
00098   .highPri   = false,     /* Default priority */
00099   .enableInt = false,     /* No interrupt on transfer completion */
00100   .select    = 0,         /* Memory-memory transfers */
00101   .cb        = NULL       /* No transfer completion callback */
00102 };
00103 
00104 static const DMA_CfgDescr_TypeDef descCfgWr =
00105 {
00106   .dstInc  = dmaDataIncNone,
00107   .srcInc  = dmaDataInc4,
00108   .size    = dmaDataSize4,
00109   .arbRate = dmaArbitrate1,
00110   .hprot   = 0
00111 };
00112 
00113 static const DMA_CfgDescr_TypeDef descCfgRd =
00114 {
00115   .dstInc  = dmaDataInc4,
00116   .srcInc  = dmaDataIncNone,
00117   .size    = dmaDataSize4,
00118   .arbRate = dmaArbitrate1,
00119   .hprot   = 0
00120 };
00121 
00122 /* Private variables. */
00123 static NANDFLASH_Info_TypeDef flashInfo;
00124 static bool                   flashInitialized = false;
00125 
00126 static uint8_t volatile       *pNandData8;
00127 static uint16_t volatile      *pNandData16;
00128 static uint32_t volatile      *pNandData32;
00129 static uint8_t volatile       *pNandAddr;
00130 static uint8_t volatile       *pNandCmd;
00131 
00132 /* Private function prototypes. */
00133 __STATIC_INLINE void      chipEnable(bool enable);
00134 static int       flashInterrogate(void);
00135 __STATIC_INLINE void      powerEnable(bool enable);
00136 static uint16_t  readSignature(void);
00137 static uint8_t   readStatus(void);
00138 static void      reset(void);
00139 static void      dmaRead(uint8_t *dst, int count);
00140 static void      dmaWrite(uint8_t *src, int count);
00141 __STATIC_INLINE void      waitReady(void);
00142 __STATIC_INLINE void      writeProtect(bool enable);
00143 
00146 /***************************************************************************/
00156 bool NANDFLASH_AddressValid(uint32_t address)
00157 {
00158   if (flashInitialized)
00159   {
00160     if ((address >= flashInfo.baseAddress) &&
00161         (address < (flashInfo.baseAddress + flashInfo.deviceSize)))
00162     {
00163       return true;
00164     }
00165   }
00166 
00167   return false;
00168 }
00169 
00170 /***************************************************************************/
00188 int NANDFLASH_CopyPage(uint32_t dstAddr, uint32_t srcAddr)
00189 {
00190   int status;
00191 
00192   if (!flashInitialized)
00193   {
00194     EFM_ASSERT(false);
00195     return NANDFLASH_NOT_INITIALIZED;
00196   }
00197 
00198   dstAddr &= ~NAND_PAGEADDR_MASK;
00199   srcAddr &= ~NAND_PAGEADDR_MASK;
00200 
00201   if (!NANDFLASH_AddressValid(dstAddr) ||
00202       !NANDFLASH_AddressValid(srcAddr) ||
00203       /* Address bit 24 must be equal for source and destination page. */
00204       ((dstAddr & (1 << 24)) != (srcAddr & (1 << 24))))
00205   {
00206     EFM_ASSERT(false);
00207     return NANDFLASH_INVALID_ADDRESS;
00208   }
00209 
00210   writeProtect(false);
00211   chipEnable(true);
00212 
00213   NAND_CMD  = NAND_CPBPROG1_CMD;
00214   NAND_ADDR = (uint8_t) srcAddr;
00215   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00216   NAND_ADDR = (uint8_t)(srcAddr >> 9);
00217   NAND_ADDR = (uint8_t)(srcAddr >> 17);
00218 
00219   waitReady();
00220 
00221   NAND_CMD  = NAND_CPBPROG2_CMD;
00222   NAND_ADDR = (uint8_t) dstAddr;
00223   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00224   NAND_ADDR = (uint8_t)(dstAddr >> 9);
00225   NAND_ADDR = (uint8_t)(dstAddr >> 17);
00226   NAND_CMD  = NAND_CPBPROG3_CMD;
00227 
00228   waitReady();
00229 
00230   status = (readStatus() & NAND_STATUS_SR0) ?
00231            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00232 
00233   chipEnable(false);
00234   writeProtect(true);
00235 
00236   return status;
00237 }
00238 
00239 /***************************************************************************/
00248 NANDFLASH_Info_TypeDef *NANDFLASH_DeviceInfo(void)
00249 {
00250   if (flashInitialized)
00251   {
00252     return &flashInfo;
00253   }
00254   return NULL;
00255 }
00256 
00257 /***************************************************************************/
00275 int NANDFLASH_EccCorrect(uint32_t generatedEcc, uint32_t readEcc, uint8_t *data)
00276 {
00278   #define ECC_MASK24    0x00FFFFFF          /* 24 valid ECC parity bits. */
00279   #define ECC_MASK      0x00555555          /* 12 ECC parity bits.       */
00280 
00282   int      count, bitNum, byteAddr;
00283   uint32_t mask;
00284   uint32_t syndrome;
00285   uint32_t eccP;                            /* 12 even ECC parity bits. */
00286   uint32_t eccPn;                           /* 12 odd ECC parity bits.  */
00287 
00288   syndrome = (generatedEcc ^ readEcc) & ECC_MASK24;
00289 
00290   if (syndrome == 0)
00291     return NANDFLASH_STATUS_OK;             /* No errors in data. */
00292 
00293   eccPn = syndrome & ECC_MASK;              /* Get twelve odd parity bits.  */
00294   eccP  = (syndrome >> 1) & ECC_MASK;       /* Get twelve even parity bits. */
00295 
00296   if ((eccPn ^ eccP) == ECC_MASK)           /* 1-bit correctable error ? */
00297   {
00298     bitNum = (eccP & 0x01) |
00299              ((eccP >> 1) & 0x02) |
00300              ((eccP >> 2) & 0x04);
00301 
00302     byteAddr = ((eccP >> 6) & 0x001) |
00303                ((eccP >> 7) & 0x002) |
00304                ((eccP >> 8) & 0x004) |
00305                ((eccP >> 9) & 0x008) |
00306                ((eccP >> 10) & 0x010) |
00307                ((eccP >> 11) & 0x020) |
00308                ((eccP >> 12) & 0x040) |
00309                ((eccP >> 13) & 0x080) |
00310                ((eccP >> 14) & 0x100);
00311 
00312     data[ byteAddr ] ^= 1 << bitNum;
00313 
00314     return NANDFLASH_STATUS_OK;
00315   }
00316 
00317   /* Count number of one's in the syndrome. */
00318   count = 0;
00319   mask  = 0x00800000;
00320   while (mask)
00321   {
00322     if (syndrome & mask)
00323       count++;
00324     mask >>= 1;
00325   }
00326 
00327   if (count == 1)                           /* Error in the ECC itself. */
00328     return NANDFLASH_ECC_ERROR;
00329 
00330   return NANDFLASH_ECC_UNCORRECTABLE;       /* Unable to correct data. */
00331 
00333   #undef ECC_MASK
00334   #undef ECC_MASK24
00335 
00336 }
00337 
00338 /***************************************************************************/
00353 int NANDFLASH_EraseBlock(uint32_t address)
00354 {
00355   int status;
00356 
00357   if (!flashInitialized)
00358   {
00359     EFM_ASSERT(false);
00360     return NANDFLASH_NOT_INITIALIZED;
00361   }
00362 
00363   address &= ~NAND_BLOCKADDR_MASK;
00364 
00365   if (!NANDFLASH_AddressValid(address))
00366   {
00367     EFM_ASSERT(false);
00368     return NANDFLASH_INVALID_ADDRESS;
00369   }
00370 
00371   writeProtect(false);
00372   chipEnable(true);
00373 
00374   NAND_CMD = NAND_BLOCKERASE1_CMD;
00375   /* Coloumn address, bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00376   NAND_ADDR = (uint8_t)(address >> 9);
00377   NAND_ADDR = (uint8_t)(address >> 17);
00378   NAND_CMD  = NAND_BLOCKERASE2_CMD;
00379 
00380   waitReady();
00381 
00382   status = (readStatus() & NAND_STATUS_SR0) ?
00383            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00384 
00385   chipEnable(false);
00386   writeProtect(true);
00387 
00388   return status;
00389 }
00390 
00391 /***************************************************************************/
00407 int NANDFLASH_Init(int dmaCh)
00408 {
00409   if ((dmaCh < -1) || (dmaCh >= DMA_CHAN_COUNT))
00410   {
00411     EFM_ASSERT(false);
00412     return NANDFLASH_INVALID_SETUP;
00413   }
00414 
00415   flashInfo.dmaCh = dmaCh;
00416 
00417   if (dmaCh >= 0)
00418   {
00419     DMA_Init((void*) &dmaInit);              /* Initialize the DMA */
00420     DMA_CfgChannel(dmaCh, (void*) &chnCfg);  /* Configure the DMA channel */
00421   }
00422 
00423   return flashInterrogate();
00424 }
00425 
00426 /***************************************************************************/
00442 int NANDFLASH_MarkBadBlock(uint32_t address)
00443 {
00444   if (!flashInitialized)
00445   {
00446     EFM_ASSERT(false);
00447     return NANDFLASH_NOT_INITIALIZED;
00448   }
00449 
00450   address &= ~NAND_BLOCKADDR_MASK;
00451 
00452   if (!NANDFLASH_AddressValid(address))
00453   {
00454     EFM_ASSERT(false);
00455     return NANDFLASH_INVALID_ADDRESS;
00456   }
00457 
00458   writeProtect(false);
00459   chipEnable(true);
00460 
00461   NAND_CMD  = NAND_RDC_CMD;
00462   NAND_CMD  = NAND_PAGEPROG1_CMD;
00463   NAND_ADDR = (uint8_t) address;
00464   /* Address bit 8 is not used, implicitely defined by NAND_RDC_CMD. */
00465   NAND_ADDR = (uint8_t)(address >> 9);
00466   NAND_ADDR = (uint8_t)(address >> 17);
00467 
00468   /* Write bad block marker 0x00 to the 6th byte in the spare area */
00469   NAND_DATA32 = 0xFFFFFFFF;
00470   NAND_DATA16 = 0x00FF;
00471   NAND_CMD    = NAND_PAGEPROG2_CMD;
00472 
00473   waitReady();
00474   readStatus();
00475 
00476   chipEnable(false);
00477   writeProtect(true);
00478 
00479   return NANDFLASH_STATUS_OK;
00480 }
00481 
00482 /***************************************************************************/
00500 int NANDFLASH_ReadPage(uint32_t address, uint8_t *buffer)
00501 {
00502   uint32_t i, readEcc, *p;
00503 
00504   if (!flashInitialized)
00505   {
00506     EFM_ASSERT(false);
00507     return NANDFLASH_NOT_INITIALIZED;
00508   }
00509 
00510   address &= ~NAND_PAGEADDR_MASK;
00511 
00512   if (!NANDFLASH_AddressValid(address))
00513   {
00514     EFM_ASSERT(false);
00515     return NANDFLASH_INVALID_ADDRESS;
00516   }
00517 
00518   chipEnable(true);
00519 
00520   NAND_CMD  = NAND_RDA_CMD;
00521   NAND_ADDR = (uint8_t) address;
00522   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00523   NAND_ADDR = (uint8_t)(address >> 9);
00524   NAND_ADDR = (uint8_t)(address >> 17);
00525 
00526   waitReady();
00527 
00528   EBI_StartNandEccGen();
00529 
00530   if (flashInfo.dmaCh == -1)
00531   {
00532     p = (uint32_t*) buffer;
00533     for (i = 0; i < flashInfo.pageSize / 4; i++)
00534     {
00535       *p++ = NAND_DATA32;
00536     }
00537   }
00538   else
00539   {
00540     dmaRead(buffer, flashInfo.pageSize);
00541   }
00542 
00543   flashInfo.ecc = EBI_StopNandEccGen();
00544 
00545   if (flashInfo.dmaCh == -1)
00546   {
00547     p = (uint32_t*) flashInfo.spare;
00548     for (i = 0; i < flashInfo.spareSize / 4; i++)
00549     {
00550       *p++ = NAND_DATA32;
00551     }
00552   }
00553   else
00554   {
00555     dmaRead(flashInfo.spare, flashInfo.spareSize);
00556   }
00557 
00558   chipEnable(false);
00559 
00560   readEcc  = flashInfo.spare[ NAND_SPARE_ECC0_POS ];
00561   readEcc += flashInfo.spare[ NAND_SPARE_ECC1_POS ] << 8;
00562   readEcc += flashInfo.spare[ NAND_SPARE_ECC2_POS ] << 16;
00563 
00564   return NANDFLASH_EccCorrect(flashInfo.ecc, readEcc, buffer);
00565 }
00566 
00567 /***************************************************************************/
00581 int NANDFLASH_ReadSpare(uint32_t address, uint8_t *buffer)
00582 {
00583   uint32_t i, *p;
00584 
00585   if (!flashInitialized)
00586   {
00587     EFM_ASSERT(false);
00588     return NANDFLASH_NOT_INITIALIZED;
00589   }
00590 
00591   address &= ~NAND_PAGEADDR_MASK;
00592 
00593   if (!NANDFLASH_AddressValid(address))
00594   {
00595     EFM_ASSERT(false);
00596     return NANDFLASH_INVALID_ADDRESS;
00597   }
00598 
00599   chipEnable(true);
00600 
00601   NAND_CMD  = NAND_RDC_CMD;
00602   NAND_ADDR = (uint8_t) address;
00603   /* Address bit 8 is not used, implicitely defined by NAND_RDC_CMD. */
00604   NAND_ADDR = (uint8_t)(address >> 9);
00605   NAND_ADDR = (uint8_t)(address >> 17);
00606 
00607   waitReady();
00608 
00609   if (flashInfo.dmaCh == -1)
00610   {
00611     p = (uint32_t*) buffer;
00612     for (i = 0; i < flashInfo.spareSize / 4; i++)
00613     {
00614       *p++ = NAND_DATA32;
00615     }
00616   }
00617   else
00618   {
00619     dmaRead(buffer, flashInfo.spareSize);
00620   }
00621 
00622   chipEnable(false);
00623 
00624   return NANDFLASH_STATUS_OK;
00625 }
00626 
00627 /***************************************************************************/
00646 int NANDFLASH_WritePage(uint32_t address, uint8_t *buffer)
00647 {
00648   int      status;
00649   uint32_t i, *p;
00650 
00651   if (!flashInitialized)
00652   {
00653     EFM_ASSERT(false);
00654     return NANDFLASH_NOT_INITIALIZED;
00655   }
00656 
00657   address &= ~NAND_PAGEADDR_MASK;
00658 
00659   if (!NANDFLASH_AddressValid(address))
00660   {
00661     EFM_ASSERT(false);
00662     return NANDFLASH_INVALID_ADDRESS;
00663   }
00664 
00665   writeProtect(false);
00666   chipEnable(true);
00667 
00668   NAND_CMD  = NAND_RDA_CMD;
00669   NAND_CMD  = NAND_PAGEPROG1_CMD;
00670   NAND_ADDR = (uint8_t) address;
00671   /* Address bit 8 is not used, implicitely defined by NAND_RDA_CMD. */
00672   NAND_ADDR = (uint8_t)(address >> 9);
00673   NAND_ADDR = (uint8_t)(address >> 17);
00674 
00675   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00676   while (EBI->STATUS & EBI_STATUS_AHBACT)
00677   {
00678   }
00679   EBI_StartNandEccGen();
00680 
00681   if (flashInfo.dmaCh == -1)
00682   {
00683     p = (uint32_t*) buffer;
00684     for (i = 0; i < flashInfo.pageSize / 4; i++)
00685     {
00686       NAND_DATA32 = *p++;
00687     }
00688   }
00689   else
00690   {
00691     dmaWrite(buffer, flashInfo.pageSize);
00692   }
00693 
00694   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00695   while (EBI->STATUS & EBI_STATUS_AHBACT)
00696   {
00697   }
00698   flashInfo.ecc = EBI_StopNandEccGen();
00699 
00700   /* Write ECC to spare area */
00701   NAND_DATA32 = 0xFFFFFFFF;
00702   NAND_DATA16 = 0xFFFF;
00703   NAND_DATA8  = flashInfo.ecc;
00704   NAND_DATA8  = flashInfo.ecc >> 8;
00705   NAND_DATA8  = flashInfo.ecc >> 16;
00706   NAND_CMD    = NAND_PAGEPROG2_CMD;
00707 
00708   waitReady();
00709 
00710   status = (readStatus() & NAND_STATUS_SR0) ?
00711            NANDFLASH_WRITE_ERROR : NANDFLASH_STATUS_OK;
00712 
00713   chipEnable(false);
00714   writeProtect(true);
00715 
00716   return status;
00717 }
00718 
00721 /***************************************************************************/
00724 __STATIC_INLINE void chipEnable(bool enable)
00725 {
00726   if (enable)
00727   {
00728     GPIO->P[NAND_CE_PORT].DOUTCLR = NAND_CE_PIN;
00729   }
00730   else
00731   {
00732     GPIO->P[NAND_CE_PORT].DOUTSET = NAND_CE_PIN;
00733   }
00734 }
00735 
00736 /***************************************************************************/
00739 static int flashInterrogate(void)
00740 {
00741   flashInfo.baseAddress = EBI_BankAddress(EBI_BANK0);
00742 
00743   pNandData8  = (uint8_t volatile*) flashInfo.baseAddress;
00744   pNandData16 = (uint16_t volatile*) pNandData8;
00745   pNandData32 = (uint32_t volatile*) pNandData8;
00746   pNandAddr   = pNandData8 + (1 << NAND_ALE_BIT);
00747   pNandCmd    = pNandData8 + (1 << NAND_CLE_BIT);
00748 
00749   powerEnable(true);
00750   waitReady();
00751   chipEnable(true);
00752   reset();
00753 
00754   if (readSignature() != NAND256W3A_SIGNATURE)
00755   {
00756     EFM_ASSERT(false);
00757     return NANDFLASH_INVALID_DEVICE;
00758   }
00759 
00760   chipEnable(false);
00761 
00762   flashInfo.manufacturerCode = (uint8_t) NAND256W3A_SIGNATURE;
00763   flashInfo.deviceCode       = (uint8_t)(NAND256W3A_SIGNATURE >> 8);
00764   flashInfo.deviceSize       = NAND256W3A_SIZE;
00765   flashInfo.pageSize         = NAND256W3A_PAGESIZE;
00766   flashInfo.spareSize        = NAND256W3A_SPARESIZE;
00767   flashInfo.blockSize        = NAND256W3A_BLOCKSIZE;
00768 
00769   flashInitialized = true;
00770 
00771   return NANDFLASH_STATUS_OK;
00772 }
00773 
00774 /***************************************************************************/
00777 __STATIC_INLINE void powerEnable(bool enable)
00778 {
00779   if (enable)
00780   {
00781     GPIO->P[NAND_POWER_PORT].DOUTSET = NAND_POWER_PIN;
00782   }
00783   else
00784   {
00785     GPIO->P[NAND_POWER_PORT].DOUTCLR = NAND_POWER_PIN;
00786   }
00787 }
00788 
00789 /***************************************************************************/
00792 static uint16_t readSignature(void)
00793 {
00794   NAND_CMD = NAND_RDSIGN_CMD;
00795   return NAND_DATA16;
00796 }
00797 
00798 /***************************************************************************/
00801 static uint8_t readStatus(void)
00802 {
00803   NAND_CMD = NAND_RDSTATUS_CMD;
00804   return NAND_DATA8;
00805 }
00806 
00807 /***************************************************************************/
00810 static void reset(void)
00811 {
00812   NAND_CMD = NAND_RST_CMD;
00813   waitReady();
00814 }
00815 
00816 /***************************************************************************/
00819 static void dmaRead(uint8_t *dst, int count)
00820 {
00821   DMA_CfgDescr(flashInfo.dmaCh, true, (void*) &descCfgRd);
00822   DMA_ActivateAuto(flashInfo.dmaCh, true, dst, (void*) pNandData32, (count / 4) - 1);
00823   while ((dmaControlBlock[flashInfo.dmaCh].CTRL & _DMA_CTRL_CYCLE_CTRL_MASK)
00824          != DMA_CTRL_CYCLE_CTRL_INVALID)
00825   {
00826   }
00827 }
00828 
00829 /***************************************************************************/
00832 static void dmaWrite(uint8_t *src, int count)
00833 {
00834   DMA_CfgDescr(flashInfo.dmaCh, true, (void*) &descCfgWr);
00835   DMA_ActivateAuto(flashInfo.dmaCh, true, (void*) pNandData32, src, (count / 4) - 1);
00836   while ((dmaControlBlock[flashInfo.dmaCh].CTRL & _DMA_CTRL_CYCLE_CTRL_MASK)
00837          != DMA_CTRL_CYCLE_CTRL_INVALID)
00838   {
00839   }
00840 }
00841 
00842 /***************************************************************************/
00845 __STATIC_INLINE void waitReady(void)
00846 {
00847   /* Wait for EBI idle in case of EBI writeBuffer is enabled */
00848   while (EBI->STATUS & EBI_STATUS_AHBACT)
00849   {
00850   }
00851   /* Wait on Ready/Busy pin to become high */
00852   while ((GPIO->P[NAND_READY_PORT].DIN & NAND_READY_PIN) == 0)
00853   {
00854   }
00855 }
00856 
00857 /***************************************************************************/
00860 __STATIC_INLINE void writeProtect(bool enable)
00861 {
00862   if (enable)
00863   {
00864     GPIO->P[NAND_WP_PORT].DOUTCLR = NAND_WP_PIN;
00865   }
00866   else
00867   {
00868     GPIO->P[NAND_WP_PORT].DOUTSET = NAND_WP_PIN;
00869   }
00870 }
00871