SAM3S8/SD8 Software Package: libraries/memories/nandflash/NfcRawNandFlash.c Source File

SAM3S8/SD8 Software Package 1.2

# NfcRawNandFlash.c

Go to the documentation of this file.

    00001 /* ----------------------------------------------------------------------------
    00002  *         ATMEL Microcontroller Software Support
    00003  * ----------------------------------------------------------------------------
    00004  * Copyright (c) 2009, Atmel Corporation
    00005  *
    00006  * All rights reserved.
    00007  *
    00008  * Redistribution and use in source and binary forms, with or without
    00009  * modification, are permitted provided that the following conditions are met:
    00010  *
    00011  * - Redistributions of source code must retain the above copyright notice,
    00012  * this list of conditions and the disclaimer below.
    00013  *
    00014  * Atmel's name may not be used to endorse or promote products derived from
    00015  * this software without specific prior written permission.
    00016  *
    00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
    00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
    00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
    00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00027  * ----------------------------------------------------------------------------
    00028  */
    00029
    00030 /**
    00031  * \file
    00032  *
    00033  * Hardware low level layer Nandflash driver with NFC.
    00034  *
    00035  */
    00036
    00037 /*#define DMA_TRANSFER      */
    00038
    00039 /*----------------------------------------------------------------------------
    00040  *        Headers
    00041  *----------------------------------------------------------------------------*/
    00042
    00043 #include "memories.h"
    00044
    00045 #include <assert.h>
    00046 #include <string.h>
    00047
    00048 #if defined(CHIP_NAND_CTRL)
    00049
    00050 /*----------------------------------------------------------------------------
    00051  *        Internal definitions
    00052  *----------------------------------------------------------------------------*/
    00053
    00054 /** Nand flash chip status codes */
    00055 #define STATUS_READY                    (1 << 6)
    00056 #define STATUS_ERROR                    (1 << 0)
    00057
    00058 /** Nand flash commands*/
    00059 #define COMMAND_READ_1                  0x00
    00060 #define COMMAND_READ_2                  0x30
    00061 #define COMMAND_COPYBACK_READ_1         0x00
    00062 #define COMMAND_COPYBACK_READ_2         0x35
    00063 #define COMMAND_COPYBACK_PROGRAM_1      0x85
    00064 #define COMMAND_COPYBACK_PROGRAM_2      0x10
    00065 #define COMMAND_RANDOM_OUT              0x05
    00066 #define COMMAND_RANDOM_OUT_2            0xE0
    00067 #define COMMAND_RANDOM_IN               0x85
    00068 #define COMMAND_READID                  0x90
    00069 #define COMMAND_WRITE_1                 0x80
    00070 #define COMMAND_WRITE_2                 0x10
    00071 #define COMMAND_ERASE_1                 0x60
    00072 #define COMMAND_ERASE_2                 0xD0
    00073 #define COMMAND_STATUS                  0x70
    00074 #define COMMAND_RESET                   0xFF
    00075
    00076
    00077 /** Nand flash commands (small blocks)*/
    00078 #define COMMAND_READ_A                  0x00
    00079 #define COMMAND_READ_C                  0x50
    00080
    00081
    00082 /*----------------------------------------------------------------------------
    00083  *        Internal Macros
    00084  *----------------------------------------------------------------------------*/
    00085 #define READ_DATA8(raw) \
    00086     (*((volatile unsigned char *) raw->dataAddress))
    00087 #define READ_DATA16(raw) \
    00088     (*((volatile unsigned short *) raw->dataAddress))
    00089
    00090 /** Internal cast macros*/
    00091 #define MODEL(raw)  ((struct NandFlashModel *) raw)
    00092
    00093 /** Number of tries for erasing a block*/
    00094 #define NUMERASETRIES           2
    00095 /** Number of tries for writing a block*/
    00096 #define NUMWRITETRIES           2
    00097 /** Number of tries for copying a block*/
    00098 #define NUMCOPYTRIES            2
    00099
    00100 /*----------------------------------------------------------------------------
    00101  *        External Variables
    00102  *----------------------------------------------------------------------------*/
    00103 /** Global nand flash temp buffer */
    00104 extern uint8_t gdwNandFlashTempBuffer[];
    00105
    00106 /*----------------------------------------------------------------------------
    00107  *        Internal functions
    00108  *----------------------------------------------------------------------------*/
    00109
    00110 /**
    00111  * \brief Translates the given column and row address into first and other (1-4) address
    00112  *  cycles. The resulting values are stored in the provided variables if they are not null.
    00113  * \param columnAddress  Column address to translate.
    00114  * \param rowAddress  Row address to translate.
    00115  * \param pAddressCycle0  First address cycle.
    00116  * \param pAddressCycle1234 four address cycles.
    00117  */
    00118 void NFC_TranslateAddress(
    00119     const struct RawNandFlash *raw,
    00120     unsigned short columnAddress,
    00121     unsigned int rowAddress,
    00122     unsigned int *pAddressCycle0,
    00123     unsigned int *pAddressCycle1234,
    00124     unsigned char useFiveAddress)
    00125 {
    00126     unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(raw));
    00127     unsigned int numPages = NandFlashModel_GetDeviceSizeInPages(MODEL(raw));
    00128     unsigned char numAddressCycles = 0;
    00129     unsigned int addressCycle0 = 0;
    00130     unsigned int addressCycle1234 = 0;
    00131
    00132     /* Check the data bus width of the NandFlash */
    00133     if (NandFlashModel_GetDataBusWidth(MODEL(raw)) == 16) {
    00134         /* Div 2 is because we address in word and not in byte */
    00135         columnAddress >>= 1;
    00136     }
    00137     /* When 5 address cycle are used.*/
    00138     if (useFiveAddress) {
    00139
    00140         while (pageDataSize > 0) {
    00141             if (numAddressCycles == 0) {
    00142                 addressCycle0 = (columnAddress & 0xFF);
    00143             }
    00144             else {
    00145                 addressCycle1234 |= (columnAddress & 0xFF) << ((numAddressCycles - 1) * 8);
    00146             }
    00147             pageDataSize >>= 8;
    00148             columnAddress >>= 8;
    00149             numAddressCycles ++;
    00150         }
    00151         while (numPages > 0) {
    00152             if (numAddressCycles == 0) {
    00153                 addressCycle0 = (rowAddress & 0xFF);
    00154             }
    00155             else {
    00156                 addressCycle1234 |= (rowAddress & 0xFF) << ((numAddressCycles - 1) * 8);
    00157             }
    00158             numPages >>= 8;
    00159             rowAddress >>= 8;
    00160             numAddressCycles ++;
    00161         }
    00162     }
    00163     /* When less than 5 address cycle are used.*/
    00164     else {
    00165         while (numPages > 0) {
    00166             addressCycle1234 |= (rowAddress & 0xFF) << ((numAddressCycles) * 8);
    00167             numPages >>= 8;
    00168             rowAddress >>= 8;
    00169             numAddressCycles ++;
    00170         }
    00171     }
    00172     /* Store values*/
    00173     if (pAddressCycle0) {
    00174         *pAddressCycle0 = addressCycle0;
    00175     }
    00176     if (pAddressCycle1234) {
    00177         *pAddressCycle1234 = addressCycle1234;
    00178     }
    00179     return;
    00180 }
    00181
    00182 /**
    00183  * \brief Check if program or erase operation is completed in current operation.
    00184  * \param columnAddress  Column address to translate.
    00185  * \param raw  Pointer to a RawNandFlash instance.
    00186  */
    00187 static unsigned char IsOperationComplete(const struct RawNandFlash *raw)
    00188 {
    00189     unsigned char status;
    00190
    00191     HSMC4_SendCommand(AT91C_HSMC4_HOSTCMD |               /* Command.*/
    00192                    0 |                                    /* Host read data.*/
    00193                    0 |                                    /* Host is disabled.*/
    00194                    AT91C_HSMC4_CSID_1 |                   /* CSID.*/
    00195                    AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_NONE | /* No address cycle.*/
    00196                    (COMMAND_STATUS << 2),                 /* CMD1 (COMMAND_STATUS).*/
    00197                    0,                                     /* Dummy address cylce 1,2,3,4.*/
    00198                    0                                      /* Dummy address cylce 0.*/
    00199     );
    00200     status = READ_DATA8(raw);
    00201     if (((status & STATUS_READY) != STATUS_READY) || ((status & STATUS_ERROR) != 0)) {
    00202         return 0;
    00203     }
    00204     return 1;
    00205 }
    00206
    00207 /**
    00208  * \brief Sends data to the NandFlash chip from the provided buffer.
    00209  * \param raw  Pointer to a RawNandFlash instance.
    00210  * \param buffer  Buffer where the data area will be stored.
    00211  * \param sramOffset  NFC internal sram start offset.
    00212  * \param size   Number of data bytes to send.
    00213  */
    00214 static void CopyDataToNfcInternalSram(
    00215     const struct RawNandFlash *raw,
    00216     unsigned char *data,
    00217     unsigned short sramOffset,
    00218     unsigned short size)
    00219 {
    00220 #ifdef DMA_TRANSFER
    00221     unsigned int startSourceAddr;
    00222     unsigned int startDestAddr;
    00223
    00224     /* Initialize DMA controller.*/
    00225     DMAD_Initialize(BOARD_NAND_DMA_CHANNEL, 0);
    00226     startSourceAddr = (unsigned int)data;
    00227     startDestAddr = (unsigned int)(NFC_SRAM_BASE_ADDRESS + sramOffset);
    00228     /* Configure transfer size and width per transfer.*/
    00229     DMAD_Configure_TransferController(BOARD_NAND_DMA_CHANNEL, size / 4, 2, 2, startSourceAddr, startDestAddr);
    00230     /* Configure single buffer transfer.*/
    00231     DMAD_Configure_Buffer(BOARD_NAND_DMA_CHANNEL, DMA_TRANSFER_SINGLE, DMA_TRANSFER_SINGLE, 0, 0);
    00232     /* Start channel 0 transfer.*/
    00233     DMAD_BufferTransfer(BOARD_NAND_DMA_CHANNEL, size / 4, 0 , 1);
    00234
    00235 #else
    00236     unsigned char * pBuffer;
    00237     unsigned int i;
    00238     pBuffer = (unsigned char *)(NFC_SRAM_BASE_ADDRESS + sramOffset);
    00239     for (i = 0; i < size; i++) {
    00240         *pBuffer++ = *data++;
    00241     }
    00242 #endif
    00243 }
    00244
    00245 /**
    00246  * \brief Sends data to the NandFlash chip from the provided buffer.
    00247  * \param raw  Pointer to a RawNandFlash instance.
    00248  * \param data  Buffer where the data area will be stored.
    00249  * \param sramOffset  NFC internal sram start offset.
    00250  * \param size Number of data bytes to receive.
    00251  */
    00252 static void CopyDataFromNfcInternalSram(
    00253     const struct RawNandFlash *raw,
    00254     unsigned char *data,
    00255     unsigned short sramOffset,
    00256     unsigned short size)
    00257 {
    00258
    00259 #ifdef DMA_TRANSFER
    00260     unsigned int startSourceAddr;
    00261     unsigned int startDestAddr;
    00262
    00263     /* Initialize DMA controller.*/
    00264     DMAD_Initialize(BOARD_NAND_DMA_CHANNEL, 0);
    00265
    00266     startSourceAddr = (unsigned int)(NFC_SRAM_BASE_ADDRESS + sramOffset);
    00267     startDestAddr = (unsigned int)data;
    00268
    00269     /* Configure transfer size and width per transfer.*/
    00270     DMAD_Configure_TransferController(BOARD_NAND_DMA_CHANNEL, size / 4, 2, 2, startSourceAddr, startDestAddr);
    00271     /* Configure single buffer transfer.*/
    00272     DMAD_Configure_Buffer(BOARD_NAND_DMA_CHANNEL, DMA_TRANSFER_SINGLE, DMA_TRANSFER_SINGLE, 0, 0);
    00273     /* Start channel 0 transfer.*/
    00274     DMAD_BufferTransfer(BOARD_NAND_DMA_CHANNEL, size / 4, 0 , 1);
    00275
    00276 #else
    00277     unsigned char * pBuffer;
    00278     unsigned int i;
    00279     pBuffer = (unsigned char *)(NFC_SRAM_BASE_ADDRESS + sramOffset);
    00280     for (i = 0; i < size; i++) {
    00281         *data++ = *pBuffer++;
    00282     }
    00283 #endif
    00284 }
    00285
    00286 /**
    00287  * \brief Erases the specified block of the device.
    00288  *
    00289  * \param raw  Pointer to a RawNandFlash instance.
    00290  * \param block  Number of the physical block to erase.
    00291  * \return 0 if successful; otherwise returns an error code.
    00292  */
    00293 static unsigned char EraseBlock(
    00294     const struct RawNandFlash *raw,
    00295     unsigned short block)
    00296 {
    00297     unsigned char error = 0;
    00298     unsigned int rowAddress;
    00299     unsigned int addressCycle1234;
    00300
    00301     TRACE_DEBUG("EraseBlock(%d)\r\n", block);
    00302
    00303     /* Calculate address used for erase*/
    00304     rowAddress = block * NandFlashModel_GetBlockSizeInPages(MODEL(raw));
    00305
    00306     NFC_TranslateAddress(raw, 0, rowAddress, 0, &addressCycle1234, 0);
    00307
    00308     /* Start erase*/
    00309     HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |                /* Command.*/
    00310                     0 |                                     /* Host read data.*/
    00311                     0 |                                     /* Host is disabled.*/
    00312                     AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00313                     AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_THREE | /* Number of address cycle.*/
    00314                     AT91C_HSMC4_VCMD2 |                     /* CMD2 enabled.*/
    00315                     (COMMAND_ERASE_2 << 10) |               /* CMD2 (ERASE CONFIRME).*/
    00316                     (COMMAND_ERASE_1 << 2),                 /* CMD1 (ERASE).*/
    00317                     addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00318                     0                                       /* Dummy address cylce 0.*/
    00319                     );
    00320
    00321     while( !HSMC4_isReadyBusy() );
    00322     #if !defined (OP_BOOTSTRAP_on)
    00323     if (!IsOperationComplete(raw)) {
    00324         TRACE_ERROR(
    00325                  "EraseBlock: Could not erase block %d.\n\r",
    00326                  block);
    00327         error = NandCommon_ERROR_CANNOTERASE;
    00328     }
    00329     #endif
    00330     return error;
    00331 }
    00332
    00333 /**
    00334  * \brief Writes the data and/or the spare area of a page on a NandFlash chip.
    00335  *
    00336  * \param raw  Pointer to a RawNandFlash instance.
    00337  * \param block  Number of the physical block to erase.
    00338  * \param page  Number of the page to write inside the given block.
    00339  * \param data  Buffer containing the data area.
    00340  * \param spare  Buffer containing the spare area.
    00341  * \return 0 if successful; otherwise returns an error code.
    00342  * \note If one of the buffer pointer is 0, the corresponding area is not written.
    00343  */
    00344 static unsigned char WritePage(
    00345     const struct RawNandFlash *raw,
    00346     unsigned short block,
    00347     unsigned short page,
    00348     void *data,
    00349     void *spare)
    00350 {
    00351
    00352     unsigned char error = 0;
    00353     unsigned int pageDataSize = NandFlashModel_GetPageDataSize(MODEL(raw));
    00354     unsigned int spareDataSize = NandFlashModel_GetPageSpareSize(MODEL(raw));
    00355     unsigned int rowAddress;
    00356     unsigned int addressCycle0;
    00357     unsigned int addressCycle1234;
    00358
    00359     TRACE_DEBUG("WritePage(B#%d:P#%d)\r\n", block, page);
    00360
    00361     /* Calculate physical address of the page*/
    00362     rowAddress = block * NandFlashModel_GetBlockSizeInPages(MODEL(raw)) + page;
    00363     /*
    00364     if (spare){
    00365         HSMC4_EnableSpareWrite();
    00366     }
    00367     else {
    00368         HSMC4_DisableSpareWrite();
    00369     }
    00370     */
    00371      /*Note: special case when ECC parity generation.
    00372        ECC results are available as soon as the counter reaches the end of the main area.
    00373        But when reach PageSize for an example, it could not generate last ECC_PR, The
    00374        workaround enable SPARE_WRITE, whatever real spare area write or not.*/
    00375     HSMC4_EnableSpareWrite();
    00376
    00377     /* Write data area if needed*/
    00378     if (data) {
    00379         CopyDataToNfcInternalSram(raw, (unsigned char *) data, 0, pageDataSize);
    00380         if (spare) {
    00381             CopyDataToNfcInternalSram(raw, (unsigned char *) spare, pageDataSize, spareDataSize);
    00382         }
    00383         NFC_TranslateAddress(raw, 0, rowAddress, &addressCycle0, &addressCycle1234, 1);
    00384     }
    00385     if (spare && !data) {
    00386         CopyDataToNfcInternalSram(raw, (unsigned char *) spare, 0, spareDataSize);
    00387         NFC_TranslateAddress(raw, pageDataSize, rowAddress, &addressCycle0, &addressCycle1234, 1);
    00388     }
    00389
    00390     if (data || spare) {
    00391         /* Start write operation*/
    00392         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |                /* Command.*/
    00393                         AT91C_HSMC4_HOST_WR |                   /* Host write data.*/
    00394                         AT91C_HSMC4_HOST_EN |                   /* Host is enabled.*/
    00395                         AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00396                         AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_FIVE |  /* Number of address cycle.*/
    00397                         0 |                                     /* CMD2 disabled.*/
    00398                         0 |                                     /* CMD2.*/
    00399                         (COMMAND_WRITE_1 << 2),                 /* CMD1.*/
    00400                         addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00401                         addressCycle0                           /* Address cylce 0.*/
    00402                     );
    00403         while( !HSMC4_TransferComplete());
    00404
    00405         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |                /* Command.*/
    00406                         0 |                                     /* No data Transfer.*/
    00407                         0 |                                     /* Host is disabled.*/
    00408                         AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00409                         AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_NONE |  /* No address cycle.*/
    00410                         0 |                                     /* CMD2 disabled.*/
    00411                         0 |                                     /* CMD2.*/
    00412                         (COMMAND_WRITE_2 << 2),                 /* CMD1.*/
    00413                         0,                                      /* Dummy address cylce 1, 2, 3, 4.*/
    00414                         0                                       /* Dummy address cylce 0.*/
    00415                         );
    00416         while( !HSMC4_isReadyBusy());
    00417         if (!IsOperationComplete(raw)) {
    00418             TRACE_ERROR("WritePage: Failed writing data area.\n\r");
    00419             error = NandCommon_ERROR_CANNOTWRITE;
    00420         }
    00421     }
    00422     HSMC4_DisableSpareWrite();
    00423     return error;
    00424 }
    00425
    00426
    00427 /**
    00428  * \brief Copies the data in a page of the NandFlash device to an other page on that same chip.
    00429  *
    00430  * \param raw  Pointer to a RawNandFlash instance.
    00431  * \param sourceBlock  Source block number.
    00432  * \param sourcePage  Source page number inside the source block.
    00433  * \param destBlock  Destination block number.
    00434  * \param destPage  Destination page number inside the destination block.
    00435  * \return 0 if successful; otherwise returns an error code.
    00436  * \note Both pages must have be even or odd; it is not possible to copy
    00437  * and even page to an odd page and vice-versa.
    00438  */
    00439 static unsigned char CopyPage(
    00440     const struct RawNandFlash *raw,
    00441     unsigned short sourceBlock,
    00442     unsigned short sourcePage,
    00443     unsigned short destBlock,
    00444     unsigned short destPage)
    00445 {
    00446     unsigned short numPages = NandFlashModel_GetBlockSizeInPages(MODEL(raw));
    00447     unsigned int sourceRow = sourceBlock * numPages + sourcePage;
    00448     unsigned int destRow = destBlock * numPages + destPage;
    00449     unsigned char error = 0;
    00450     unsigned int addressCycle0;
    00451     unsigned int addressCycle1234;
    00452
    00453     ASSERT((sourcePage & 1) == (destPage & 1),
    00454            "CopyPage: Source and destination page must have the same parity.\n\r");
    00455
    00456     TRACE_DEBUG("CopyPage(B#%d:P#%d -> B#%d:P#%d)\n\r",
    00457               sourceBlock, sourcePage, destBlock, destPage);
    00458
    00459     /* Use the copy-back facility if available*/
    00460     if (NandFlashModel_SupportsCopyBack(MODEL(raw))) {
    00461
    00462         /* Start operation*/
    00463         NFC_TranslateAddress(raw, 0, sourceRow, &addressCycle0, &addressCycle1234, 1);
    00464         /* Start copy-back read*/
    00465         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |            /* Command.*/
    00466                     0 |                                     /* Host read data.*/
    00467                     0 |                                     /* Host is disabled.*/
    00468                     AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00469                     AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_FIVE |  /* Number of address cycle.*/
    00470                     AT91C_HSMC4_VCMD2 |                     /* CMD2 enabled.*/
    00471                     (COMMAND_COPYBACK_READ_2 << 10)|        /* CMD2.*/
    00472                     (COMMAND_COPYBACK_READ_1 << 2),         /* CMD1.*/
    00473                     addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00474                     addressCycle0                           /* Address cylce 0.*/
    00475                     );
    00476         while( !HSMC4_isReadyBusy() );
    00477
    00478         /* Start copy-back write*/
    00479         NFC_TranslateAddress(raw, 0, destRow, &addressCycle0, &addressCycle1234, 1);
    00480         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |            /* Command.*/
    00481                     0 |                                     /* No data transfer.*/
    00482                     0 |                                     /* Host is disabled. */
    00483                     AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00484                     AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_FIVE |  /* Number of address cycle.*/
    00485                     AT91C_HSMC4_VCMD2 |                     /* CMD2 enabled.*/
    00486                     (COMMAND_COPYBACK_PROGRAM_2 << 10)|     /* CMD2.*/
    00487                     (COMMAND_COPYBACK_PROGRAM_1 << 2),      /* CMD1.*/
    00488                     addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00489                     addressCycle0                           /* Address cylce 0.*/
    00490                     );
    00491         while( !HSMC4_isReadyBusy() );
    00492
    00493         /* Check status*/
    00494         if (!IsOperationComplete(raw)) {
    00495             TRACE_ERROR("CopyPage: Failed to copy page.\n\r");
    00496             error = NandCommon_ERROR_CANNOTCOPY;
    00497         }
    00498     }
    00499     else {
    00500
    00501         /* Software copy*/
    00502 //        unsigned char data[NandCommon_MAXPAGEDATASIZE];
    00503         unsigned char spare[NandCommon_MAXPAGESPARESIZE];
    00504         if (RawNandFlash_ReadPage(raw, sourceBlock, sourcePage, gdwNandFlashTempBuffer, spare)) {
    00505
    00506             TRACE_ERROR("CopyPage: Failed to read page to copy\n\r");
    00507             error = NandCommon_ERROR_CANNOTREAD;
    00508         }
    00509         else if (RawNandFlash_WritePage(raw, destBlock, destPage, gdwNandFlashTempBuffer, spare)) {
    00510
    00511             TRACE_ERROR("CopyPage: Failed to write dest. page\n\r");
    00512             error = NandCommon_ERROR_CANNOTWRITE;
    00513         }
    00514     }
    00515
    00516     return error;
    00517 }
    00518
    00519 /*------------------------------------------------------------------------------
    00520  *         Exported functions
    00521  *----------------------------------------------------------------------------*/
    00522
    00523 /**
    00524  * \brief Initializes a RawNandFlash instance based on the given model and physical interface.
    00525  *
    00526  * \param raw  Pointer to a RawNandFlash instance.
    00527  * \param model  Pointer to the underlying nand chip model. Can be 0.
    00528  * \param commandAddress  Address at which commands are sent.
    00529  * \param addressAddress  Address at which addresses are sent.
    00530  * \param dataAddress  Address at which data is sent.
    00531  * \param pinChipEnable  Pin controlling the CE signal of the NandFlash.
    00532  * \param pinReadyBusy  Pin used to monitor the ready/busy signal of the Nand.
    00533  * \return 0 if successful; otherwise returns NandCommon_ERROR_UNKNOWNMODEL.
    00534  */
    00535 unsigned char RawNandFlash_Initialize(
    00536     struct RawNandFlash *raw,
    00537     const struct NandFlashModel *model,
    00538     unsigned int commandAddress,
    00539     unsigned int addressAddress,
    00540     unsigned int dataAddress,
    00541     const Pin pinChipEnable,
    00542     const Pin pinReadyBusy)
    00543 {
    00544     TRACE_DEBUG("RawNandFlash_Initialize()\r\n");
    00545
    00546     /* Initialize fields*/
    00547     raw->commandAddress = commandAddress;
    00548     raw->addressAddress = addressAddress;
    00549     raw->dataAddress = dataAddress;
    00550     raw->pinChipEnable = pinChipEnable;
    00551     raw->pinReadyBusy = pinReadyBusy;
    00552
    00553     /* Reset*/
    00554     RawNandFlash_Reset(raw);
    00555
    00556     /* If model is not provided, autodetect it*/
    00557     if (!model) {
    00558
    00559         TRACE_DEBUG("No model provided, trying autodetection ...\n\r");
    00560         if (NandFlashModel_Find(nandFlashModelList,
    00561                                 NandFlashModelList_SIZE,
    00562                                 RawNandFlash_ReadId(raw),
    00563                                 &(raw->model))) {
    00564
    00565             TRACE_ERROR(
    00566                       "RawNandFlash_Initialize: Could not autodetect chip.\n\r");
    00567             return NandCommon_ERROR_UNKNOWNMODEL;
    00568         }
    00569     }
    00570     else {
    00571
    00572         /* Copy provided model*/
    00573         raw->model = *model;
    00574     }
    00575
    00576     return 0;
    00577 }
    00578
    00579 /**
    00580  * \brief Resets a NandFlash device.
    00581  *
    00582  * \param raw  Pointer to a RawNandFlash instance.
    00583  */
    00584 void RawNandFlash_Reset(const struct RawNandFlash *raw)
    00585 {
    00586     TRACE_DEBUG("RawNandFlash_Reset()\n\r");
    00587     HSMC4_SendCommand(AT91C_HSMC4_HOSTCMD |              /* Command.*/
    00588                    0 |                                   /* Host read data.*/
    00589                    0 |                                   /* Host is disabled.*/
    00590                   AT91C_HSMC4_CSID_1 |                   /* CSID.*/
    00591                   AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_NONE | /* No address Cycle.*/
    00592                   (COMMAND_RESET << 2),                  /* CMD1 (COMMAND_RESET).*/
    00593                   0,                                     /* Dummy address cylce 1,2,3,4.*/
    00594                   0                                      /* Dummy address cylce 0.*/
    00595     );
    00596     while( !HSMC4_isReadyBusy() );
    00597 }
    00598
    00599 /**
    00600  * \brief Reads and returns the identifiers of a NandFlash chip.
    00601  *
    00602  * \param raw  Pointer to a RawNandFlash instance.
    00603  * \return id1|(id2<<8)|(id3<<16)|(id4<<24)
    00604  */
    00605 unsigned int RawNandFlash_ReadId(const struct RawNandFlash *raw)
    00606 {
    00607     unsigned int chipId;
    00608
    00609     TRACE_DEBUG("RawNandFlash_ReadId()\n\r");
    00610     HSMC4_SendCommand(AT91C_HSMC4_HOSTCMD |              /* Command.*/
    00611                    0 |                                   /* Host read Data.*/
    00612                    0 |                                   /* Host is disabled.*/
    00613                   AT91C_HSMC4_CSID_1 |                   /* CSID.*/
    00614                   AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_ONE |  /* One address Cycle.*/
    00615                   (COMMAND_READID << 2),                 /* CMD1 (COMMAND_READID).*/
    00616                   0,                                     /* Dummy address cylce 1,2,3,4.*/
    00617                   0                                      /* Dummy address cylce 0.*/
    00618     );
    00619     chipId  = READ_DATA8(raw);
    00620     chipId |= READ_DATA8(raw) << 8;
    00621     chipId |= READ_DATA8(raw) << 16;
    00622     chipId |= READ_DATA8(raw) << 24;
    00623     return chipId;
    00624 }
    00625
    00626 /**
    00627  * \brief Erases the specified block of the device, retrying several time if it fails.
    00628  *
    00629  * \param raw  Pointer to a RawNandFlash instance.
    00630  * \param block  Number of the physical block to erase.
    00631  * \return 0 if successful; otherwise returns NandCommon_ERROR_UNKNOWNMODEL.
    00632  */
    00633 unsigned char RawNandFlash_EraseBlock(
    00634     const struct RawNandFlash *raw,
    00635     unsigned short block)
    00636 {
    00637     #if !defined(OP_BOOTSTRAP_on)
    00638     unsigned char numTries = NUMERASETRIES;
    00639
    00640     TRACE_DEBUG("RawNandFlash_EraseBlock(B#%d)\n\r", block);
    00641
    00642     while (numTries > 0) {
    00643
    00644         if (!EraseBlock(raw, block)) {
    00645
    00646             return 0;
    00647         }
    00648         numTries--;
    00649     }
    00650
    00651     TRACE_ERROR("RawNandFlash_EraseBlock: Failed to erase block after %d tries\n\r", NUMERASETRIES);
    00652     return NandCommon_ERROR_BADBLOCK;
    00653     #else
    00654     return EraseBlock(raw, block);
    00655     #endif
    00656 }
    00657
    00658 /**
    00659  * \brief Reads the data and/or the spare areas of a page of a NandFlash into the  provided buffers.
    00660  *
    00661  * \param raw  Pointer to a RawNandFlash instance.
    00662  * \param block  Number of the physical block to read.
    00663  * \param page  Number of the page to read inside the given block.
    00664  * \param data  Buffer where the data area will be read.
    00665  * \param spare  Buffer where the spare area will be read.
    00666  * \return 0 if successful; otherwise returns 1.
    00667  * \note If one of the buffer pointer is 0, the corresponding area is not read.
    00668  */
    00669 unsigned char RawNandFlash_ReadPage(
    00670     const struct RawNandFlash *raw,
    00671     unsigned short block,
    00672     unsigned short page,
    00673     void *data,
    00674     void *spare)
    00675 {
    00676     volatile unsigned int cntTry = 0;
    00677
    00678     unsigned char hasSmallBlocks = NandFlashModel_HasSmallBlocks(MODEL(raw));
    00679     unsigned int pageDataSize = NandFlashModel_GetPageDataSize(MODEL(raw));
    00680     unsigned int pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(raw));
    00681     unsigned int colAddress;
    00682     unsigned int rowAddress;
    00683     unsigned int addressCycle0;
    00684     unsigned int addressCycle1234;
    00685     ASSERT(data || spare, "RawNandFlash_ReadPage: At least one area must be read\n\r");
    00686     TRACE_DEBUG("RawNandFlash_ReadPage(B#%d:P#%d)\r\n", block, page);
    00687     /* Calculate actual address of the page*/
    00688     rowAddress = block * NandFlashModel_GetBlockSizeInPages(MODEL(raw)) + page;
    00689     /* Start operation*/
    00690     if (data) {
    00691         colAddress = 0;
    00692     }
    00693     else {
    00694         /* to read spare area in sequential access*/
    00695         colAddress = pageDataSize;
    00696     }
    00697
    00698     if (spare) {
    00699         HSMC4_EnableSpareRead();
    00700     }
    00701     else {
    00702         HSMC4_DisableSpareRead();
    00703     }
    00704     NFC_TranslateAddress(raw, colAddress, rowAddress, &addressCycle0, &addressCycle1234, 1);
    00705     /* Use either small blocks or large blocks data area read*/
    00706     if (hasSmallBlocks) {
    00707         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |            /* Command.*/
    00708                     0 |                                     /* Host read data.*/
    00709                     AT91C_HSMC4_HOST_EN |                   /* Host is enable.*/
    00710                     AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00711                     AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_FIVE |  /* Number of address cycle.*/
    00712                     0 |                                     /* CMD2 disabled.*/
    00713                     0 |                                     /* CMD2.*/
    00714                     (COMMAND_READ_A << 2),                  /* CMD1.*/
    00715                     addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00716                     addressCycle0                           /* Address cylce 0.*/
    00717                     );
    00718     }
    00719     else {
    00720         HSMC4_SendCommand (AT91C_HSMC4_HOSTCMD |            /* Command.*/
    00721                     0 |                                     /* Host read data.*/
    00722                     AT91C_HSMC4_HOST_EN |                   /* Host is enabled.*/
    00723                     AT91C_HSMC4_CSID_1 |                    /* CSID.*/
    00724                     AT91C_HSMC4_ACYCLE_HSMC4_ACYCLE_FIVE |  /* Number of address cycle.*/
    00725                     AT91C_HSMC4_VCMD2 |                     /* CMD2 enabled.*/
    00726                     (COMMAND_READ_2 << 10)|                 /* CMD2.*/
    00727                     (COMMAND_READ_1 << 2),                  /* CMD1.*/
    00728                     addressCycle1234,                       /* Address cylce 1, 2, 3, 4.*/
    00729                     addressCycle0                           /* Address cylce 0.*/
    00730                     );
    00731     }
    00732     /* Wait for the nand to be ready*/
    00733     cntTry = 0;
    00734     while( !HSMC4_isReadyBusy() && (cntTry++) < 1000000);
    00735     cntTry = 0;
    00736     while( !HSMC4_TransferComplete() && (cntTry++) < 1000000);
    00737     /* Read data area if needed*/
    00738     if (data) {
    00739         CopyDataFromNfcInternalSram(raw, (unsigned char *) data, 0, pageDataSize);
    00740         if (spare) {
    00741             CopyDataFromNfcInternalSram(raw, (unsigned char *) spare, pageDataSize, pageSpareSize);
    00742         }
    00743     }
    00744      else {
    00745          /* Read spare area only*/
    00746          CopyDataFromNfcInternalSram(raw, (unsigned char *) spare, 0, pageSpareSize);
    00747     }
    00748     return 0;
    00749 }
    00750
    00751 /**
    00752  * \brief Writes the data and/or the spare areas of a page of a NandFlash into the  provided buffers.
    00753  *
    00754  * \param raw  Pointer to a RawNandFlash instance.
    00755  * \param block  Number of the physical block to write resides.
    00756  * \param page Number of the page to write inside the given block.
    00757  * \param data  Buffer where the data area will be stored.
    00758  * \param spare  Buffer where the spare area will be stored.
    00759  * \return 0 if successful; otherwise returns NandCommon_ERROR_BADBLOCK.
    00760  * \note If one of the buffer pointer is 0, the corresponding area is not written.
    00761  */
    00762 unsigned char RawNandFlash_WritePage(
    00763     const struct RawNandFlash *raw,
    00764     unsigned short block,
    00765     unsigned short page,
    00766     void *data,
    00767     void *spare)
    00768 {
    00769     unsigned char numTries = NUMWRITETRIES;
    00770
    00771     TRACE_DEBUG("RawNandFlash_WritePage(B#%d:P#%d)\r\n", block, page);
    00772
    00773     while (numTries > 0) {
    00774
    00775         if (!WritePage(raw, block, page, data, spare)) {
    00776
    00777             return 0;
    00778         }
    00779         numTries--;
    00780     }
    00781
    00782     TRACE_ERROR("RawNandFlash_WritePage: Failed to write page after %d tries\n\r", NUMWRITETRIES);
    00783     return NandCommon_ERROR_BADBLOCK;
    00784 }
    00785
    00786 /**
    00787  * \brief Copy the data in a page of the NandFlash device to an other page on that same chip.
    00788  *
    00789  * \param raw  Pointer to a RawNandFlash instance.
    00790  * \param sourceBlock  Source block number.
    00791  * \param sourcePage  Source page number inside the source block.
    00792  * \param destBlock  Destination block number.
    00793  * \param destPage  Destination page number inside the destination block.
    00794  * \return 0 if successful; otherwise returns an NandCommon_ERROR_BADBLOCK.
    00795  * \note Both pages must have be even or odd; it is not possible to copy
    00796  * and even page to an odd page and vice-versa.
    00797  */
    00798 unsigned char RawNandFlash_CopyPage(
    00799     const struct RawNandFlash *raw,
    00800     unsigned short sourceBlock,
    00801     unsigned short sourcePage,
    00802     unsigned short destBlock,
    00803     unsigned short destPage)
    00804 {
    00805     unsigned char numTries = NUMCOPYTRIES;
    00806
    00807     TRACE_DEBUG("RawNandFlash_CopyPage(B#%d:P#%d -> B#%d:P#%d)\n\r",
    00808               sourceBlock, sourcePage, destBlock, destPage);
    00809
    00810     while (numTries) {
    00811
    00812         if (!CopyPage(raw, sourceBlock, sourcePage, destBlock, destPage)) {
    00813
    00814             return 0;
    00815         }
    00816         numTries--;
    00817     }
    00818
    00819     TRACE_ERROR("RawNandFlash_CopyPage: Failed to copy page after %d tries\n\r", NUMCOPYTRIES);
    00820     return NandCommon_ERROR_BADBLOCK;
    00821 }
    00822
    00823 /**
    00824  * \brief Copies the data of one whole block of a NandFlash device to another block.
    00825  *
    00826  * \param raw  Pointer to a RawNandFlash instance.
    00827  * \param sourceBlock  Source block number.
    00828  * \param destBlock  Destination block number.
    00829  * \return 0 if successful; otherwise returns an NandCommon_ERROR_BADBLOCK.
    00830  */
    00831 unsigned char RawNandFlash_CopyBlock(
    00832     const struct RawNandFlash *raw,
    00833     unsigned short sourceBlock,
    00834     unsigned short destBlock)
    00835 {
    00836     unsigned short numPages = NandFlashModel_GetBlockSizeInPages(MODEL(raw));
    00837     unsigned int i;
    00838
    00839     ASSERT(sourceBlock != destBlock,
    00840            "RawNandFlash_CopyBlock: Source block must be different from dest block\n\r");
    00841     TRACE_DEBUG("RawNandFlash_CopyBlock(B#%d->B#%d)\n\r",
    00842               sourceBlock, destBlock);
    00843
    00844     /* Copy all pages*/
    00845     for (i=0; i < numPages; i++) {
    00846
    00847         if (RawNandFlash_CopyPage(raw, sourceBlock, i, destBlock, i)) {
    00848
    00849             TRACE_ERROR(
    00850                       "RawNandFlash_CopyBlock: Failed to copy page %u\n\r",
    00851                       i);
    00852             return NandCommon_ERROR_BADBLOCK;
    00853         }
    00854     }
    00855     return 0;
    00856 }
    00857
    00858 #endif
    00859

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines