Exemplo n.º 1
0
//------------------------------------------------------------------------------
/// Writes the data and/or spare area of a nandflash page, after calculating an
/// ECC for the data area and storing it in the spare. If no data buffer is
/// provided, the ECC is read from the existing page spare. If no spare buffer
/// is provided, the spare area is still written with the ECC information
/// calculated on the data buffer.
/// Returns 0 if successful; otherwise returns an error code.
/// \param ecc Pointer to an EccNandFlash instance.
/// \param block  Number of the block to write in.
/// \param page  Number of the page to write inside the given block.
/// \param data  Data area buffer, can be 0.
/// \param spare  Spare area buffer, can be 0.
//------------------------------------------------------------------------------
unsigned char EccNandFlash_WritePage(
    struct EccNandFlash *ecc,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    unsigned char error;
    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc));
    unsigned short pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc));
    unsigned char *pSpareBuffer = RawNandFlash_GetSpareBuffer(RAW(ecc));

    ASSERT(data || spare, "EccNandFlash_WritePage: At least one area must be written\n\r");
    TRACE_DEBUG("EccNandFlash_WritePage(B#%d:P#%d)\n\r", block, page);
#ifndef HARDWARE_ECC
    // Compute ECC on the new data, if provided
    // If not provided, hamming code set to 0xFFFF.. to keep existing bytes
    memset(ecc->hamming, 0xFF, NandCommon_MAXSPAREECCBYTES);
    if (data) {

        // Compute hamming code on data
        Hamming_Compute256x(data, pageDataSize, ecc->hamming);
    }

    // Store code in spare buffer (if no buffer provided, use a temp. one)
    if (!spare) {

        spare = pSpareBuffer;
        memset(spare, 0xFF, pageSpareSize);
    }
    NandSpareScheme_WriteEcc(NandFlashModel_GetScheme(MODEL(ecc)), spare, ecc->hamming);

    // Perform write operation
    error = RawNandFlash_WritePage(RAW(ecc), block, page, data, spare);
    if (error)
        goto error;

#else
    // Store code in spare buffer (if no buffer provided, use a temp. one)
    if (!spare) {
        spare = pSpareBuffer;
        memset(spare, 0xFF, pageSpareSize);
    }
    // Perform write operation
    error = RawNandFlash_WritePage(RAW(ecc), block, page, data, spare);
    if (error)
      goto error;

    HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc)));
    // Perform write operation
    NandSpareScheme_WriteEcc(NandFlashModel_GetScheme(MODEL(ecc)), spare, hsiao);
    error = RawNandFlash_WritePage(RAW(ecc), block, page, 0, spare);
    if (error) 
      goto error;
#endif        
    RawNandFlash_ReleaseSpareBuffer(RAW(ecc));
    return 0;
    
error:
      RawNandFlash_ReleaseSpareBuffer(RAW(ecc));
      TRACE_ERROR("EccNandFlash_WritePage: Failed to write page\n\r");
      return error;
}
Exemplo n.º 2
0
//------------------------------------------------------------------------------
/// Reads the data and/or spare of a page of a nandflash chip, and verify that
/// the data is valid using the ECC information contained in the spare. If one
/// buffer pointer is 0, the corresponding area is not saved.
/// Returns 0 if the data has been read and is valid; otherwise returns either
/// NandCommon_ERROR_CORRUPTEDDATA or ...
/// \param ecc  Pointer to an EccNandFlash instance.
/// \param block  Number of block to read from.
/// \param page  Number of page to read inside given block.
/// \param data  Data area buffer.
/// \param spare  Spare area buffer.
//------------------------------------------------------------------------------
unsigned char EccNandFlash_ReadPage(
    struct EccNandFlash *ecc,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    unsigned char error;
    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc));
    unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc));
    unsigned char *pDataBuffer;
    unsigned char *pSpareBuffer;

    TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page);

    pDataBuffer = (data)   ? data  : RawNandFlash_GetDataBuffer(RAW(ecc));
    pSpareBuffer = (spare) ? spare : RawNandFlash_GetSpareBuffer(RAW(ecc));
    
#ifndef HARDWARE_ECC
    // Start by reading the spare and the data
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, pDataBuffer, pSpareBuffer);
    if (error) {
       TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                block, page);
        goto error;
    }

    // Retrieve ECC information from page and verify the data
    NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), pSpareBuffer, ecc->hamming);
    error = Hamming_Verify256x(pDataBuffer, pageDataSize, ecc->hamming);
#else
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, tmpSpare);
    if (error) {
        TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                block, page);
        goto error;
    }

    // Retrieve ECC information from page
    NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, ecc->hsiaoInSpare);
    HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc)));
    // Verify the data
    error = HSMC4_VerifyHsiao((unsigned char*) data,
                              pageDataSize, 
                              ecc->hsiaoInSpare,
                              ecc->hsiao,
                              NandFlashModel_GetDataBusWidth(MODEL(ecc)));
#endif    
    if (error && (error != Hamming_ERROR_SINGLEBIT)) {
        error = NandCommon_ERROR_CORRUPTEDDATA;
        TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                block, page);
        goto error;
    }
#ifndef HARDWARE_ECC
#else
     if (spare) {

        memcpy(spare, pSpareBuffer, pageSpareSize);
    }    
#endif
error: 
    if (data == (unsigned char *) 0)
      RawNandFlash_ReleaseDataBuffer(RAW(ecc));
    if (spare == (unsigned char *) 0)
        RawNandFlash_ReleaseSpareBuffer(RAW(ecc));
    return error;   
}
Exemplo n.º 3
0
/**
 * \brief  Writes the data and/or spare area of a nandflash page, after calculating an
 * ECC for the data area and storing it in the spare. If no data buffer is
 * provided, the ECC is read from the existing page spare. If no spare buffer
 * is provided, the spare area is still written with the ECC information
 * calculated on the data buffer.
 * \param ecc  Pointer to an EccNandFlash instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer.
 * \param spare  Spare area buffer.
 * \return 0 if successful; otherwise returns an error code.
 */
unsigned char EccNandFlash_WritePage(
    const struct EccNandFlash *ecc,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    unsigned char error;
    unsigned char tmpSpare[NandCommon_MAXPAGESPARESIZE];
    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc));
    unsigned short pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc));
#ifndef HARDWARE_ECC
    unsigned char hamming[NandCommon_MAXSPAREECCBYTES];
#else
    unsigned char hsiao[NandCommon_MAXSPAREECCBYTES];
#endif

    assert( (data != NULL) || (spare != NULL) ) ;
//    TRACE_DEBUG(  "EccNandFlash_WritePage: At least one area must be written\n\r" ) ;
    TRACE_DEBUG("EccNandFlash_WritePage(B#%d:P#%d)\n\r", block, page);
#ifndef HARDWARE_ECC
    /* Compute ECC on the new data, if provided */
    /* If not provided, hamming code set to 0xFFFF.. to keep existing bytes */
    memset(hamming, 0xFF, NandCommon_MAXSPAREECCBYTES);
    if (data) {

        /* Compute hamming code on data */
        Hamming_Compute256x(data, pageDataSize, hamming);
    }

    /* Store code in spare buffer (if no buffer provided, use a temp. one) */
    if (!spare) {

        spare = tmpSpare;
        memset(spare, 0xFF, pageSpareSize);
    }
    NandSpareScheme_WriteEcc(NandFlashModel_GetScheme(MODEL(ecc)), spare, hamming);

    /* Perform write operation */
    error = RawNandFlash_WritePage(RAW(ecc), block, page, data, spare);
    if (error) {

        TRACE_ERROR("EccNandFlash_WritePage: Failed to write page\n\r");
        return error;
    }

#else
    /* Store code in spare buffer (if no buffer provided, use a temp. one) */
    if (!spare) {
        spare = tmpSpare;
        memset(spare, 0xFF, pageSpareSize);
    }
    /* Perform write operation */
    error = RawNandFlash_WritePage(RAW(ecc), block, page, data, spare);
    if (error) {

        TRACE_ERROR("EccNandFlash_WritePage: Failed to write page\n\r");
        return error;
    }
    HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc)));
    /* Perform write operation */
    NandSpareScheme_WriteEcc(NandFlashModel_GetScheme(MODEL(ecc)), spare, hsiao);
    error = RawNandFlash_WritePage(RAW(ecc), block, page, 0, spare);
    if (error) {
        TRACE_ERROR("EccNandFlash_WritePage: Failed to write page\n\r");
        return error;
    }
#endif
    return 0;
}
Exemplo n.º 4
0
//------------------------------------------------------------------------------
/// Reads the data and/or spare of a page of a nandflash chip, and verify that
/// the data is valid using the ECC information contained in the spare. If one
/// buffer pointer is 0, the corresponding area is not saved.
/// Returns 0 if the data has been read and is valid; otherwise returns either
/// NandCommon_ERROR_CORRUPTEDDATA or ...
/// \param ecc  Pointer to an EccNandFlash instance.
/// \param block  Number of block to read from.
/// \param page  Number of page to read inside given block.
/// \param data  Data area buffer.
/// \param spare  Spare area buffer.
//------------------------------------------------------------------------------
unsigned char EccNandFlash_ReadPage(
    const struct EccNandFlash *ecc,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    unsigned char tmpSpare[NandCommon_MAXPAGESPARESIZE];
    unsigned char error;
#ifndef HARDWARE_ECC    
    unsigned char tmpData[NandCommon_MAXPAGEDATASIZE];
    unsigned char hamming[NandCommon_MAXSPAREECCBYTES];
#else    
    unsigned char hsiaoInSpare[NandCommon_MAXSPAREECCBYTES];
    unsigned char hsiao[NandCommon_MAXSPAREECCBYTES];
#endif
    unsigned char tmpNoEcc;

    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc));
    unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc));

    TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page);
#ifndef HARDWARE_ECC
    // Start by reading the spare data
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, 0, tmpSpare);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r");
        return error;
    }

    // Then reading the data
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, tmpData, 0);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r");
        return error;
    }

    tmpNoEcc = EccNandlfash_GetNoECC();
    if(!tmpNoEcc){
        // Retrieve ECC information from page and verify the data
        NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hamming);
        error = Hamming_Verify256x(tmpData, pageDataSize, hamming);
    }
#else
    // Start by reading the spare area
    // Note: Can't read data and spare at the same time, otherwise, the ECC parity generation will be incorrect.
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, 0, tmpSpare);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                    block, page);
        return error;
    }
        // Retrieve ECC information from page and verify the data
    NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hsiaoInSpare);
    
    // Reading the main data area
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, 0);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                    block, page);
        return error;
    }
    HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc)));
    error = HSMC4_VerifyHsiao((unsigned char*) data,
                              pageDataSize, 
                              hsiaoInSpare,
                              hsiao,
                              NandFlashModel_GetDataBusWidth(MODEL(ecc)));
#endif    
    if (error && (error != Hamming_ERROR_SINGLEBIT) && (!tmpNoEcc)) {

        TRACE_ERROR("EccNandFlash_ReadPage: at B%d.P%d Unrecoverable data\n\r",
                    block, page);
        return NandCommon_ERROR_CORRUPTEDDATA;
    }
#ifndef HARDWARE_ECC
    // Copy data and/or spare into final buffers
    if (data) {

        memcpy(data, tmpData, pageDataSize);
    }
    if (spare) {

        memcpy(spare, tmpSpare, pageSpareSize);
    }
#else
     if (spare) {

        memcpy(spare, tmpSpare, pageSpareSize);
    }    
#endif
    return 0;
}
Exemplo n.º 5
0
/**
 * \brief  Reads the data and/or spare of a page of a nandflash chip, and verify that
 * the data is valid using the ECC information contained in the spare. If one
 * buffer pointer is 0, the corresponding area is not saved.
 * \param ecc  Pointer to an EccNandFlash instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer.
 * \param spare  Spare area buffer.
 * \return 0 if the data has been read and is valid; otherwise returns either
 * NandCommon_ERROR_CORRUPTEDDATA or ...
 */
unsigned char EccNandFlash_ReadPage(
    const struct EccNandFlash *ecc,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    unsigned char tmpSpare[NandCommon_MAXPAGESPARESIZE];
    unsigned char error;
#ifndef HARDWARE_ECC
//    unsigned char tmpData[NandCommon_MAXPAGEDATASIZE];
    unsigned char hamming[NandCommon_MAXSPAREECCBYTES];
#else
    unsigned char hsiaoInSpare[NandCommon_MAXSPAREECCBYTES];
    unsigned char hsiao[NandCommon_MAXSPAREECCBYTES];
#endif

    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc));
    unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc));

    TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page);
#ifndef HARDWARE_ECC
    /* Start by reading the spare and the data */
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, gdwNandFlashTempBuffer, tmpSpare);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r");
        return error;
    }

    /* Retrieve ECC information from page and verify the data */
    NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hamming);
    error = Hamming_Verify256x(gdwNandFlashTempBuffer, pageDataSize, hamming);
#else
    error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, tmpSpare);
    if (error) {

        TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r",
                    block, page);
        return error;
    }
    /* Retrieve ECC information from page */
    NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hsiaoInSpare);
    HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc)));
    /* Verify the data */
    error = HSMC4_VerifyHsiao((unsigned char*) data,
                              pageDataSize,
                              hsiaoInSpare,
                              hsiao,
                              NandFlashModel_GetDataBusWidth(MODEL(ecc)));
#endif
    if (error && (error != Hamming_ERROR_SINGLEBIT)) {

        TRACE_ERROR("EccNandFlash_ReadPage: at B%d.P%d Unrecoverable data\n\r",
                    block, page);
        return NandCommon_ERROR_CORRUPTEDDATA;
    }
#ifndef HARDWARE_ECC
    /* Copy data and/or spare into final buffers */
    if (data) {

        memcpy(data, gdwNandFlashTempBuffer, pageDataSize);
    }
    if (spare) {

        memcpy(spare, tmpSpare, pageSpareSize);
    }
#else
     if (spare) {

        memcpy(spare, tmpSpare, pageSpareSize);
    }
#endif
    return 0;
}