예제 #1
0
//------------------------------------------------------------------------------
/// Reads the data and/or the spare area of a page on a managed nandflash. If
/// the data pointer is not 0, then the block MUST be LIVE.
/// Returns NandCommon_ERROR_WRONGSTATUS if the block is not LIVE and the data
/// pointer is not null; Otherwise, returns EccNandFlash_ReadPage().
/// \param managed  Pointer to a ManagedNandFlash instance.
/// \param block  Block to read page from, based on managed area.
/// \param page  Number of page to read inside the given block.
/// \param data  Data area buffer, can be 0.
/// \param spare  Spare area buffer, can be 0.
//------------------------------------------------------------------------------
unsigned char ManagedNandFlash_ReadPage(
    const struct ManagedNandFlash *managed,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    // Check that the block is LIVE if data is requested
    if ((managed->blockStatuses[block].status != NandBlockStatus_LIVE)
        && (managed->blockStatuses[block].status != NandBlockStatus_DIRTY)) {

        TRACE_ERROR("ManagedNandFlash_ReadPage: Block must be LIVE or DIRTY.\n\r");
        return NandCommon_ERROR_WRONGSTATUS;
    }

    // Read data with ECC verification
    return EccNandFlash_ReadPage(ECC(managed),
                                 managed->baseBlock + block,
                                 page, data, spare);
}
예제 #2
0
/**
 * \brief Reads the data and/or the spare area of a page on a SkipBlock nandflash.
 *
 * \param skipBlock  Pointer to a SkipBlockNandFlash instance.
 * \param block  Number of block to read page from.
 * \param page  Number of page to read inside the given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \note If one of the buffer pointer is 0, then the block MUST not be BAD.
 * \return NandCommon_ERROR_BADBLOCK if the block is BAD; Otherwise, returns EccNandFlash_ReadPage().
 */
uint8_t SkipBlockNandFlash_ReadPage(
    const struct SkipBlockNandFlash *skipBlock,
    uint16_t block,
    uint16_t page,
    void *data,
    void *spare)
{
    #if !defined(OP_BOOTSTRAP_on)
    /* Check that the block is not BAD if data is requested */
    if (SkipBlockNandFlash_CheckBlock(skipBlock, block) != GOODBLOCK) {

        TRACE_ERROR("SkipBlockNandFlash_ReadPage: Block is BAD.\n\r");
        return NandCommon_ERROR_BADBLOCK;
    }

    /* Read data with ECC verification */
    return EccNandFlash_ReadPage(ECC(skipBlock), block, page, data, spare);
    #else
	return RawNandFlash_ReadPage(RAW(skipBlock), block, page, data, spare);
    #endif
}
예제 #3
0
/**
 * \brief Reads the data of a whole block on a SkipBlock nandflash.
 *
 * \param skipBlock  Pointer to a SkipBlockNandFlash instance.
 * \param block  Number of block to read page from.
 * \param page  Number of page to read inside the given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return NandCommon_ERROR_BADBLOCK if the block is BAD; Otherwise, returns EccNandFlash_ReadPage().
 */
uint8_t SkipBlockNandFlash_ReadBlock(
    const struct SkipBlockNandFlash *skipBlock,
    uint16_t block,
    void *data)
{
    /* Number of pages per block */
    uint32_t numPagesPerBlock, pageSize;
    /* Page index */
    uint16_t i;
    /* Error returned by SkipBlockNandFlash_WritePage */
    uint8_t error = 0;

    /* Retrieve model information */
    pageSize = NandFlashModel_GetPageDataSize(MODEL(skipBlock));
    numPagesPerBlock = NandFlashModel_GetBlockSizeInPages(MODEL(skipBlock));

    /* Check that the block is not BAD if data is requested */
    if (SkipBlockNandFlash_CheckBlock(skipBlock, block) != GOODBLOCK) {

        TRACE_ERROR("SkipBlockNandFlash_ReadBlock: Block is BAD.\n\r");
        return NandCommon_ERROR_BADBLOCK;
    }

    /* Read all the pages of the block */
    for (i = 0; i < numPagesPerBlock; i++) {
        error = EccNandFlash_ReadPage(ECC(skipBlock), block, i, data, 0);
        if (error) {

            TRACE_ERROR("SkipBlockNandFlash_ReadBlock: Cannot read page %d of block %d.\n\r", i, block);
            return error;
        }
        data = (void *) ((uint8_t *) data + pageSize);
    }

    return 0;
}
예제 #4
0
//------------------------------------------------------------------------------
/// Copy the data & spare area of one page to another page. The source block
/// can be either LIVE or DIRTY, and the destination block must be LIVE; they
/// must both have the same parity.
/// Returns 0 if successful; NandCommon_ERROR_WRONGSTATUS if one or more page
/// is not live; otherwise returns an NandCommon_ERROR_xxx code.
/// \param managed  Pointer to a ManagedNandFlash instance.
/// \param sourceBlock  Source block number based on managed area.
/// \param sourcePage  Number of source page inside the source block.
/// \param destBlock  Destination block number based on managed area.
/// \param destPage  Number of destination page inside the dest block.
//------------------------------------------------------------------------------
unsigned char ManagedNandFlash_CopyPage(
    const struct ManagedNandFlash *managed,
    unsigned short sourceBlock,
    unsigned short sourcePage,
    unsigned short destBlock,
    unsigned short destPage)
{
    unsigned char *pDataBuffer =  RawNandFlash_GetDataBuffer(RAW(managed));
    unsigned char *pSpareBuffer = RawNandFlash_GetSpareBuffer(RAW(managed));
    unsigned char error;

    ASSERT((sourcePage & 1) == (destPage & 1),
           "ManagedNandFlash_CopyPage: source & dest pages must have the same parity\n\r");

    TRACE_INFO("ManagedNandFlash_CopyPage(B#%d:P#%d -> B#%d:P#%d)\n\r",
              sourceBlock, sourcePage, destBlock, destPage);

    // Check block statuses
    if ((managed->blockStatuses[sourceBlock].status != NandBlockStatus_LIVE)
         && (managed->blockStatuses[sourceBlock].status != NandBlockStatus_DIRTY)) {

        TRACE_ERROR("ManagedNandFlash_CopyPage: Source block must be LIVE or DIRTY.\n\r");
        return NandCommon_ERROR_WRONGSTATUS;
    }
    if (managed->blockStatuses[destBlock].status != NandBlockStatus_LIVE) {

        TRACE_ERROR("ManagedNandFlash_CopyPage: Destination block must be LIVE.\n\r");
        return NandCommon_ERROR_WRONGSTATUS;
    }

    // If destination page is page #0, block status information must not be
    // overwritten
    if (destPage == 0) {


        // Read data & spare to copy
        error = EccNandFlash_ReadPage(ECC(managed),
                                      managed->baseBlock + sourceBlock,
                                      sourcePage,
                                      pDataBuffer, pSpareBuffer);
        if (error)
            goto error;

        // Write destination block status information in spare
        NandSpareScheme_WriteExtra(NandFlashModel_GetScheme(MODEL(managed)),
                                   pSpareBuffer,
                                   &(managed->blockStatuses[destBlock]),
                                   4,
                                   0);

        // Write page
        error = RawNandFlash_WritePage(RAW(managed),
                                       managed->baseBlock + destBlock,
                                       destPage,
                                       pDataBuffer, pSpareBuffer);
        if (error)
            goto error;
    }
    // Otherwise, a normal copy can be done
    else {

        error = RawNandFlash_CopyPage(RAW(managed),
                                     managed->baseBlock + sourceBlock,
                                     sourcePage,
                                     managed->baseBlock + destBlock,
                                     destPage);
    }

error:
   RawNandFlash_ReleaseDataBuffer(RAW(managed));
   RawNandFlash_ReleaseSpareBuffer(RAW(managed));
   return error;
}