//------------------------------------------------------------------------------
/// Unmaps a logical block by releasing the corresponding physical block (if
/// any).
/// Returns 0 if successful; otherwise returns a NandCommon_ERROR code.
/// \param mapped  Pointer to a MappedNandFlash instance.
/// \param logicalBlock  Number of logical block to unmap.
//------------------------------------------------------------------------------
unsigned char MappedNandFlash_Unmap(
    struct MappedNandFlash *mapped,
    unsigned short logicalBlock)
{
    signed short physicalBlock = mapped->logicalMapping[logicalBlock];
    unsigned char error;

    TRACE_INFO("MappedNandFlash_Unmap(LB#%d)\r\n", logicalBlock);
    ASSERT(
        logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)),
        "MappedNandFlash_Unmap: logicalBlock out-of-range\r\n");

    if (physicalBlock != -1) {

        error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), physicalBlock);
        if (error) {

            return error;
        }
    }
    mapped->logicalMapping[logicalBlock] = -1;
    mapped->mappingModified = 1;

    return 0;
}
//------------------------------------------------------------------------------
/// Initializes a MappedNandFlash instance. Scans the device to look for and
/// existing logical block mapping; otherwise starts from scratch (no block
/// mapped).
/// Returns 0 if successful; otherwise returns a NandCommon_ERROR_xxx code.
/// \param mapped  Pointer to a MappedNandFlash instance.
/// \param model  Pointer to the underlying nand chip model. Can be 0.
/// \param commandAddress  Address at which commands are sent.
/// \param addressAddress  Address at which addresses are sent.
/// \param dataAddress  Address at which data is sent.
/// \param pinChipEnable  Pin controlling the CE signal of the NandFlash.
/// \param pinReadyBusy  Pin used to monitor the ready/busy signal of the Nand.
/// \param baseBlock Basic physical block address of mapped area.
/// \param sizeInBlocks Number of blocks that is mapped.
//------------------------------------------------------------------------------
unsigned char MappedNandFlash_Initialize(
    struct MappedNandFlash *mapped,
    const struct NandFlashModel *model,
    unsigned int commandAddress,
    unsigned int addressAddress,
    unsigned int dataAddress,
    const Pin pinChipEnable,
    const Pin pinReadyBusy,
    unsigned short baseBlock,
    unsigned short sizeInBlocks)
{
    unsigned char error;
    unsigned short numBlocks;
    unsigned short block;
    signed short logicalMappingBlock = 0;

    TRACE_INFO("MappedNandFlash_Initialize()\r\n");

    // Initialize ManagedNandFlash
    error = ManagedNandFlash_Initialize(MANAGED(mapped),
                                        model,
                                        commandAddress,
                                        addressAddress,
                                        dataAddress,
                                        pinChipEnable,
                                        pinReadyBusy,
                                        baseBlock,
                                        sizeInBlocks);
    if (error) {

        return error;
    }

    // Scan to find logical mapping
    mapped->mappingModified = 0;
    error = FindLogicalMappingBlock(mapped, &logicalMappingBlock);
    if (!error) {

        // Extract mapping from block
        mapped->logicalMappingBlock = logicalMappingBlock;
        return LoadLogicalMapping(mapped, logicalMappingBlock);
    }
    else if (error == NandCommon_ERROR_NOMAPPING) {

        // Start with no block mapped
        mapped->logicalMappingBlock = -1;
        numBlocks = ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
        for (block=0; block < numBlocks; block++) {

            mapped->logicalMapping[block] = -1;
        }
    }
    else {

        TRACE_ERROR("MappedNandFlash_Initialize: Initialize device\r\n");
        return error;
    }

    return 0;
}
/**
 * \brief   Returns the number of available blocks in a translated nandflash.
 *
 * \param translated  Pointer to a TranslatedNandFlash instance.
 * \return the number of available blocks in a translated nandflash.
 */
unsigned short TranslatedNandFlash_GetDeviceSizeInBlocks( const struct TranslatedNandFlash *translated)
{
    return ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(translated))
           - MINNUMUNALLOCATEDBLOCKS
           - ManagedNandFlash_CountBlocks(MANAGED(translated),
                                          NandBlockStatus_BAD)
           - 1; /* Logical mapping block*/
}
Ejemplo n.º 4
0
static void
managedstring_finalize( GObject *gobject )
{
	Managedstring *managedstring = MANAGEDSTRING( gobject );

#ifdef DEBUG
	printf( "managedstring_finalize: \"%s\", ", managedstring->string );
	iobject_print( IOBJECT( managedstring ) );
#endif /*DEBUG*/

#ifdef DEBUG
{
	PElement pe;

	PEPOINTE( &pe, &managedstring->e );
	if( !PEISNOVAL( &pe ) ) 
		managed_expanded -= 1;
	managed_total -= 1;
}
#endif /*DEBUG*/

	heap_unregister_element( MANAGED( managedstring )->heap, 
		&managedstring->e );
	g_hash_table_remove( managedstring_all, managedstring );
	IM_FREE( managedstring->string );

	G_OBJECT_CLASS( parent_class )->finalize( gobject );
}
Ejemplo n.º 5
0
static uclptr_t STRING_create (const void* sample_data)
{
	if (sizeof(char*) <= sizeof(cell_t))
	{
		uclptr_t storage_index = cell_alloc();
		if (storage_index != NIL)
		{
			int length = strlen(sample_data) + 1;
			//char **storage_cell_ptr = (char**)&uclmem[storage_index];
			char **storage_cell_ptr = (char**)&CONTAINER(storage_index);
			MANAGED(storage_index) = 1;
			*storage_cell_ptr = (char*)malloc(length);
			memset (*storage_cell_ptr, 0, length);
			strcpy (*storage_cell_ptr, sample_data);
			return storage_index;
		}
	}
	else /* физический указатель очень велик и не помещается даже на место целой ячейки */
	{
		int length = strlen(sample_data) + 1;
		char *src = (char*)malloc(length);
		strcpy (src, sample_data);
		return chop (&src, sizeof(void*));
	}
	return NIL;
}
/**
 * \brief  Reads the data and/or spare area of a page in a mapped logical block.
 * 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 mapped  Pointer to a MappedNandFlash instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return 0 if successful; otherwise, returns NandCommon_ERROR_BLOCKNOTMAPPED
 * if the block is not mapped, or a NandCommon_ERROR_xxx code.
 */
unsigned char MappedNandFlash_ReadPage(
    const struct MappedNandFlash *mapped,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    signed short physicalBlock;

    TRACE_INFO("MappedNandFlash_ReadPage(LB#%d:P#%d)\n\r", block, page);

    /* Check if block is mapped*/
    physicalBlock = mapped->logicalMapping[block];
    if (physicalBlock == -1) {

        TRACE_INFO( "MappedNandFlash_ReadPage: Block %d not mapped\n\r", block);
        return NandCommon_ERROR_BLOCKNOTMAPPED;
    }

    /* Read page from corresponding physical block*/
    return ManagedNandFlash_ReadPage(MANAGED(mapped),
                                     physicalBlock,
                                     page,
                                     data,
                                     spare);
}
/**
 * \brief  Writes  the data and/or spare area of a page in a mapped logical block.
 * 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 mapped  Pointer to a MappedNandFlash instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to write inside given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return 0 if successful; otherwise, returns NandCommon_ERROR_BLOCKNOTMAPPED
 * if the block is not mapped, or a NandCommon_ERROR_xxx code.
 */
unsigned char MappedNandFlash_WritePage(
    const struct MappedNandFlash *mapped,
    unsigned short block,
    unsigned short page,
    void *data,
    void *spare)
{
    signed short physicalBlock;

    TRACE_INFO("MappedNandFlash_WritePage(LB#%d:P#%d)\n\r", block, page);

    /* Check if block is mapped*/
    physicalBlock = mapped->logicalMapping[block];
    if (physicalBlock == -1) {

        TRACE_ERROR("MappedNandFlash_WritePage: Block must be mapped\n\r");
        return NandCommon_ERROR_BLOCKNOTMAPPED;
    }

    /* Write page on physical block*/
    return ManagedNandFlash_WritePage(MANAGED(mapped),
                                      physicalBlock,
                                      page,
                                      data,
                                      spare);
}
/**
 * \brief  Reads the data and/or the spare area of a page on a translated nandflash.
 * If the block is not currently mapped but could be (i.e. there are available
 * physical blocks), then the data/spare is filled with 0xFF.
 *
 * \param translated  Pointer to a TranslatedNandFlash instance.
 * \param block  Logical block number.
 * \param page  Number of page to read inside logical block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return 0 if successful; otherwise returns NandCommon_ERROR_NOMOREBLOCKS
 */
unsigned char TranslatedNandFlash_ReadPage( const struct TranslatedNandFlash *translated, unsigned short block,
                                            unsigned short page, void *data, void *spare )
{
    unsigned char error ;

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

    /* If the page to read is in the current block, there is a previous physical
       block and the page is clean -> read the page in the old block since the
       new one does not contain meaningful data*/
    if ( (block == translated->currentLogicalBlock) && (translated->previousPhysicalBlock != -1)
         && (PageIsClean(translated, page)) )
    {
        TRACE_DEBUG("Reading page from current block\n\r");
        return ManagedNandFlash_ReadPage( MANAGED( translated ), translated->previousPhysicalBlock,
                                          page, data, spare ) ;
    }
    else
    {
        /* Try to read the page from the logical block*/
        error = MappedNandFlash_ReadPage(MAPPED(translated), block, page, data, spare);

        /* Block was not mapped*/
        if ( error == NandCommon_ERROR_BLOCKNOTMAPPED )
        {
            assert( !spare ) ; /* "Cannot read the spare information of an unmapped block\n\r" */

            /* Check if a block can be allocated*/
            if ( BlockCanBeAllocated( translated ) )
            {
                /* Return 0xFF in buffers with no error*/
                TRACE_DEBUG("Block #%d is not mapped but can be allocated, filling buffer with 0xFF\n\r", block);
                if (data)
                {
                    memset(data, 0xFF, NandFlashModel_GetPageDataSize(MODEL(translated)));
                }
                if (spare)
                {
                    memset(spare, 0xFF, NandFlashModel_GetPageSpareSize(MODEL(translated)));
                }
            }
            else
            {
                TRACE_ERROR("Block #%d is not mapped and there are no more blocks available\n\r", block);
                return NandCommon_ERROR_NOMOREBLOCKS;
            }
        }
        /* Error*/
        else
        {
            if (error)
            {
                return error;
            }
        }
    }

    return 0;
}
/**
 * \brief  Returns the physical block mapped with the given logical block, or -1 if it
 * is not mapped.
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param logicalBlock  Logical block number.
  * \return  the physical block, or -1 if it is not mapped.
 */
signed short MappedNandFlash_LogicalToPhysical(
    const struct MappedNandFlash *mapped,
    unsigned short logicalBlock)
{
    assert( logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_LogicalToPhysical: logicalBlock out-of-range\n\r" */

    return mapped->logicalMapping[logicalBlock];
}
/**
 * \brief  Erase all blocks in the mapped area of nand flash.
 *
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param level   Erase level.
 * \return 0.
 */
unsigned char MappedNandFlash_EraseAll(
    struct MappedNandFlash *mapped,
    unsigned char level)
{
    unsigned int block;
    ManagedNandFlash_EraseAll(MANAGED(mapped), level);
    /* Reset to no block mapped*/
    if (level > NandEraseDIRTY) {
        mapped->logicalMappingBlock = -1;
        mapped->mappingModified = 0;
        for (block=0;
             block < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
             block++) {
            mapped->logicalMapping[block] = -1;
        }
    }
    return 0;
}
//------------------------------------------------------------------------------
/// Returns the physical block mapped with the given logical block, or -1 if it
/// is not mapped.
/// \param mapped  Pointer to a MappedNandFlash instance.
/// \param logicalBlock  Logical block number.
//------------------------------------------------------------------------------
signed short MappedNandFlash_LogicalToPhysical(
    const struct MappedNandFlash *mapped,
    unsigned short logicalBlock)
{
    ASSERT(
        logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)),
        "MappedNandFlash_LogicalToPhysical: logicalBlock out-of-range\r\n");

    return mapped->logicalMapping[logicalBlock];
}
static unsigned char BlockCanBeAllocated(
    const struct TranslatedNandFlash *translated)
{
    unsigned short count;

    /* Count number of free and dirty blocks (unallocated blocks)*/
    count = ManagedNandFlash_CountBlocks(MANAGED(translated), NandBlockStatus_DIRTY)
            + ManagedNandFlash_CountBlocks(MANAGED(translated), NandBlockStatus_FREE);

    /* Check that count is greater than minimum number of unallocated blocks*/
    if (count > MINNUMUNALLOCATEDBLOCKS) {

        return 1;
    }
    else {

        return 0;
    }
}
/**
 * \brief  Allocates a free block to save the current logical mapping on it.
 *
 * \param translated  Pointer to a TranslatedNandFlash instance.
 * \return 0 if successful; otherwise returns a NandCommon_ERROR code.
 */
unsigned char TranslatedNandFlash_SaveLogicalMapping(
    struct TranslatedNandFlash *translated)
{
    unsigned char error;
    unsigned short freeBlock;

    TRACE_INFO("TranslatedNandFlash_SaveLogicalMapping()\n\r");

    /* Save logical mapping in the youngest free block*/
    /* Find the youngest block*/
    error = ManagedNandFlash_FindYoungestBlock(MANAGED(translated),
                                               NandBlockStatus_FREE,
                                               &freeBlock);
    if (error)
    {
        TRACE_ERROR("TranNF_SaveLogicalMapping: No free block\n\r");
        return error;
    }

    /* Check if this is the last free block, in which case dirty blocks are wiped
       prior to saving the mapping */
    if (ManagedNandFlash_CountBlocks(MANAGED(translated),
                                     NandBlockStatus_FREE) == 1)
    {
        TranslatedNandFlash_Flush(translated);
        error = ManagedNandFlash_EraseDirtyBlocks(MANAGED(translated));
        if (error)
        {
            TRACE_ERROR("TranNF_Flush: Could not erase dirty blocks\n\r");
            return error;
        }
    }

    /* Save the mapping*/
    error = MappedNandFlash_SaveLogicalMapping(MAPPED(translated), freeBlock);
    if (error)
    {
        TRACE_ERROR("TranNF_Flush: Failed to save mapping in #%d\n\r", freeBlock);
        return error;
    }

    return 0;
}
//------------------------------------------------------------------------------
/// Maps a logical block number to an actual physical block. This allocates
/// the physical block (meaning it must be FREE), and releases the previous
/// block being replaced (if any).
/// Returns 0 if successful; otherwise returns a NandCommon_ERROR_xxx code.
/// \param mapped  Pointer to a MappedNandFlash instance.
/// \param logicalBlock  Logical block number to map.
/// \param physicalBlock  Physical block to map to the logical one.
//------------------------------------------------------------------------------
unsigned char MappedNandFlash_Map(
    struct MappedNandFlash *mapped,
    unsigned short logicalBlock,
    unsigned short physicalBlock)
{
    unsigned char error;
    signed short oldPhysicalBlock;

    TRACE_INFO("MappedNandFlash_Map(LB#%d -> PB#%d)\r\n",
               logicalBlock, physicalBlock);
    ASSERT(
       logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)),
       "MappedNandFlash_Map: logicalBlock out-of-range\r\n");
    ASSERT(
       physicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)),
       "MappedNandFlash_Map: physicalBlock out-of-range\r\n");

    // Allocate physical block
    error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock);
    if (error) {

        return error;
    }

    // Release currently mapped block (if any)
    oldPhysicalBlock = mapped->logicalMapping[logicalBlock];
    if (oldPhysicalBlock != -1) {

        error =
            ManagedNandFlash_ReleaseBlock(MANAGED(mapped), oldPhysicalBlock);
        if (error) {

            return error;
        }
    }

    // Set mapping
    mapped->logicalMapping[logicalBlock] = physicalBlock;
    mapped->mappingModified = 1;

    return 0;
}
/**
 * \brief  Returns the logical block mapped with the given logical block, or -1 if it
 * is not mapped.
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param physicalBlock  Physical block number.
  * \return  the logical block, or -1 if it is not mapped.
 */
signed short MappedNandFlash_PhysicalToLogical(
    const struct MappedNandFlash *mapped,
    unsigned short physicalBlock)
{
    unsigned short numBlocks =
                    ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
    signed short logicalBlock;

    assert( physicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_PhysicalToLogical: physicalBlock out-of-range\n\r" */

    /* Search the mapping for the desired physical block*/
    for ( logicalBlock=0; logicalBlock < numBlocks; logicalBlock++ )
    {
        if ( mapped->logicalMapping[logicalBlock] == physicalBlock )
        {
            return logicalBlock ;
        }
    }

    return -1;
}
Ejemplo n.º 16
0
uclptr_t chop (void *srcdata, int size) /* рубит указатель на некие данные и их размер */
{
	uclptr_t chunks = NIL;
	int i, num_of_chunks = size / sizeof(uclptr_t); /* количество кусков, на которые будет разбит массив */
	uclptr_t *vdata = (uclptr_t *)srcdata;

	for (i = 0; i < num_of_chunks; i++)
	{
		chunks = cons (chunks, vdata[i]); /* здесь мы нарушаем порядок полей ячейки - для замыкания в цепь используется CAR, а не CDR! */
		MANAGED(chunks) = 1;
	}

	return chunks;
}
/**
 * \brief  Maps a logical block number to an actual physical block. This allocates
 * the physical block (meaning it must be FREE), and releases the previous
 * block being replaced (if any).
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param logicalBlock  Logical block number to map.
 * \param physicalBlock  Physical block to map to the logical one.
 * \return  0 if successful; otherwise returns a NandCommon_ERROR_xxx code.
 */
unsigned char MappedNandFlash_Map(
    struct MappedNandFlash *mapped,
    unsigned short logicalBlock,
    unsigned short physicalBlock)
{
    unsigned char error;
    signed short oldPhysicalBlock;

    TRACE_INFO("MappedNandFlash_Map(LB#%d -> PB#%d)\n\r",
               logicalBlock, physicalBlock);
    assert( logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_Map: logicalBlock out-of-range\n\r" */
    assert( physicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_Map: physicalBlock out-of-range\n\r" */

    /* Allocate physical block*/
    error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock);
    if ( error )
    {
        return error;
    }

    /* Release currently mapped block (if any)*/
    oldPhysicalBlock = mapped->logicalMapping[logicalBlock];
    if (oldPhysicalBlock != -1)
    {
        error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), oldPhysicalBlock);
        if ( error )
        {
            return error;
        }
    }

    /* Set mapping*/
    mapped->logicalMapping[logicalBlock] = physicalBlock;
    mapped->mappingModified = 1;

    return 0;
}
Ejemplo n.º 18
0
static uclptr_t INTEGER32_create (const void* sample_data)
/* Теперь надо посмотреть, влезает ли 32-битное число в поле CDR.
 * Если не влезает, оно будет храниться в отдельной ячейке (сделаем смелое предположение о том, что туда-то уж оно влезет). */
{
	if (sizeof(int32_t) != sizeof(uclptr_t)) /* определяется на этапе компиляции */
	{
		uclptr_t storage_index = cell_alloc(); /* возьмём ещё одну ячейку */
		//int32_t **storage_cell_ptr = (int32_t**)&uclmem[storage_index]; /* представим, что это указатель на int */
		int32_t **storage_cell_ptr = (int32_t**)&CONTAINER(storage_index); /* представим, что это указатель на int */
		MANAGED(storage_index) = 1;
		*storage_cell_ptr = (int32_t*)sample_data; /* положим его туда */
		return storage_index; /* вернём индекс ячейки хранения */
	}
	else return (uint32_t)((intptr_t)sample_data);
}
/**
 * \brief  Terminates the current write operation by copying all the missing pages from
 * the previous physical block.
 *
 * \param translated  Pointer to a TranslatedNandFlash instance.
 * \return 0 if successful; otherwise returns error code
 */
unsigned char TranslatedNandFlash_Flush(struct TranslatedNandFlash *translated)
{
    unsigned int i;
    unsigned char error;
    unsigned int currentPhysicalBlock;

    /* Check if there is a current block and a previous block*/
    if ((translated->currentLogicalBlock == -1)
        || (translated->previousPhysicalBlock == -1))
    {
        return 0;
    }

    TRACE_INFO("TranslatedNandFlash_Flush(PB#%d -> LB#%d)\n\r",
              translated->previousPhysicalBlock, translated->currentLogicalBlock);

    /* Copy missing pages in the current block*/
    currentPhysicalBlock = MappedNandFlash_LogicalToPhysical(
                                MAPPED(translated),
                                translated->currentLogicalBlock);

    for (i=0; i < NandFlashModel_GetBlockSizeInPages(MODEL(translated)); i++)
    {
        if (PageIsClean(translated, i))
        {
            TRACE_DEBUG("Copying back page #%d of block #%d\n\r", i, translated->previousPhysicalBlock);

            /* Copy page*/
            error = ManagedNandFlash_CopyPage(MANAGED(translated),
                                              translated->previousPhysicalBlock,
                                              i,
                                              currentPhysicalBlock,
                                              i);
            if (error)
            {
                TRACE_ERROR("FinishCurrentWrite: copy page #%d\n\r", i);
                return error;
            }
        }
    }

    translated->currentLogicalBlock = -1;
    translated->previousPhysicalBlock = -1;
    return 0;
}
Ejemplo n.º 20
0
static uclptr_t VECTOR_create (const void* sample_data) /* параметр - uint32_t, количество выделяемых ячеек. */
/* Эта функция только создаёт пустой вектор, его наполнение - забота совершенно другой конструкции.
 * */
{
	uint32_t i, n = (uintptr_t)sample_data;
	uint32_t size = (n * sizeof(uclptr_t));	/* смело! А вдруг упрёмся в ограничение? */
	ucl_vector_t *vector;
	uclptr_t storage_index;

	if (sizeof(void*) <= sizeof(cell_t)) /* если указатель на кучу влезает целиком в поле container, то используем эту схему хранения */
	{
		storage_index = cell_alloc();
		if (storage_index != NIL)
		{
			ucl_vector_t **storage_cell_ptr = (ucl_vector_t**)&CONTAINER(storage_index);
			//GC(storage_index) = GC_TRANSIENT;
			MANAGED(storage_index) = 1;
			*storage_cell_ptr = (ucl_vector_t*)malloc(sizeof(ucl_vector_t)); /* выделяем память под дескриптор ветора */
			vector = *storage_cell_ptr;
		}
		else
		{
			printf ("Panic stop: no free memory left!\n");
			exit(-1);
		}
	}
	else /* если физический указатель очень велик и не помещается даже на место целой ячейки, тогда используем другую схему хранения - чоппер! */
	{
		vector = (ucl_vector_t*)malloc(sizeof(ucl_vector_t));
		storage_index = chop (&vector, sizeof(ucl_vector_t*));
	}
	vector->length = n;
	vector->ptr = (uclptr_t*)malloc(size);
	for (i=0; i < vector->length; i++)
	{
		vector->ptr[i] = NIL;
	}
	return storage_index;
}
/**
 * \brief  Saves the logical mapping on a FREE, unmapped physical block. Allocates the
 * new block, releases the previous one (if any) and save the mapping.
 *
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param physicalBlock  Physical block number.
 * \return  0 if successful; otherwise, returns NandCommon_ERROR_WRONGSTATUS
 * if the block is not LIVE, or a NandCommon_ERROR code.
 */
unsigned char MappedNandFlash_SaveLogicalMapping(
    struct MappedNandFlash *mapped,
    unsigned short physicalBlock)
{
    unsigned char error;
    unsigned char data[NandCommon_MAXPAGEDATASIZE];
    unsigned short pageDataSize =
                    NandFlashModel_GetPageDataSize(MODEL(mapped));
    /*unsigned short numBlocks =
                    ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));*/
    unsigned int i;
    unsigned int remainingSize;
    unsigned char *currentBuffer;
    unsigned short currentPage;
    unsigned int writeSize;
    signed short previousPhysicalBlock;

    TRACE_INFO("MappedNandFlash_SaveLogicalMapping(B#%d)\n\r", physicalBlock);

    /* If mapping has not been modified, do nothing*/
    if (!mapped->mappingModified) {

        return 0;
    }

    /* Allocate new block*/
    error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock);
    if (error) {

        return error;
    }

    /* Save mapping*/
    previousPhysicalBlock = mapped->logicalMappingBlock;
    mapped->logicalMappingBlock = physicalBlock;

    /* Save actual mapping in pages #1-#XXX*/
    currentBuffer = (unsigned char *) mapped->logicalMapping;
    remainingSize = sizeof(mapped->logicalMapping);
    currentPage = 1;
    while (remainingSize > 0) {

        writeSize = min(remainingSize, pageDataSize);
        memset(data, 0xFF, pageDataSize);
        memcpy(data, currentBuffer, writeSize);
        error = ManagedNandFlash_WritePage(MANAGED(mapped),
                                           physicalBlock,
                                           currentPage,
                                           data,
                                           0);
        if (error) {

            TRACE_ERROR(
             "MappedNandFlash_SaveLogicalMapping: Failed to write mapping\n\r");
            return error;
        }

        currentBuffer += writeSize;
        remainingSize -= writeSize;
        currentPage++;
    }

    /* Mark page #0 of block with a distinguishible pattern, so the mapping can
       be retrieved at startup*/
    for (i=0; i < pageDataSize; i++) {

        data[i] = PATTERN(i);
    }
    error = ManagedNandFlash_WritePage(MANAGED(mapped),
                                       physicalBlock, 0,
                                       data, 0);
    if (error) {

        TRACE_ERROR(
            "MappedNandFlash_SaveLogicalMapping: Failed to write pattern\n\r");
        return error;
    }

    /* Mapping is not modified anymore*/
    mapped->mappingModified = 0;

    /* Release previous block (if any)*/
    if (previousPhysicalBlock != -1) {

        TRACE_DEBUG("Previous physical block was #%d\n\r",
                    previousPhysicalBlock);
        error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped),
                                              previousPhysicalBlock);
        if (error) {

            return error;
        }
    }

    TRACE_INFO("Mapping saved on block #%d\n\r", physicalBlock);

    return 0;
}
/**
 * \brief  Loads the logical mapping contained in the given physical block.
 * block contains the mapping, its index is stored in the provided variable (if
 * pointer is not 0).
 *
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param physicalBlock  Physical block number.
 * \return  0 if successful; otherwise, returns a NandCommon_ERROR code.
 */
static unsigned char LoadLogicalMapping(
    struct MappedNandFlash *mapped,
    unsigned short physicalBlock)
{
    unsigned char error;
    unsigned char data[NandCommon_MAXPAGEDATASIZE];
    unsigned short pageDataSize =
                    NandFlashModel_GetPageDataSize(MODEL(mapped));
    unsigned short numBlocks =
                    ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
    unsigned int remainingSize;
    unsigned char *currentBuffer;
    unsigned short currentPage;
    unsigned int readSize;
    unsigned int i;
    unsigned char status;
    signed short logicalBlock;
    /*signed short firstBlock, lastBlock;*/

    TRACE_INFO("LoadLogicalMapping(B#%d)\n\r", physicalBlock);

    /* Load mapping from pages #1 - #XXX of block*/
    currentBuffer = (unsigned char *) mapped->logicalMapping;
    remainingSize = sizeof(mapped->logicalMapping);
    currentPage = 1;
    while (remainingSize > 0) {

        /* Read page*/
        readSize = min(remainingSize, pageDataSize);
        error = ManagedNandFlash_ReadPage(MANAGED(mapped),
                                          physicalBlock,
                                          currentPage,
                                          data,
                                          0);
        if (error) {

            TRACE_ERROR(
                      "LoadLogicalMapping: Failed to load mapping\n\r");
            return error;
        }

        /* Copy page info*/
        memcpy(currentBuffer, data, readSize);

        currentBuffer += readSize;
        remainingSize -= readSize;
        currentPage++;
    }

    /* Store mapping block index*/
    mapped->logicalMappingBlock = physicalBlock;

    /* Power-loss recovery*/
    for (i=0; i < numBlocks; i++) {

        /* Check that this is not the logical mapping block*/
        if (i != physicalBlock) {

            status = mapped->managed.blockStatuses[i].status;
            logicalBlock = MappedNandFlash_PhysicalToLogical(mapped, i);

            /* Block is LIVE*/
            if (status == NandBlockStatus_LIVE) {

                /* Block is not mapped -> release it*/
                if (logicalBlock == -1) {

                    TRACE_WARNING_WP("-I- Release unmapped LIVE #%d\n\r",
                                     i);
                    ManagedNandFlash_ReleaseBlock(MANAGED(mapped), i);
                }
            }
            /* Block is DIRTY*/
            else if (status == NandBlockStatus_DIRTY) {

                /* Block is mapped -> fake it as live*/
                if (logicalBlock != -1) {

                    TRACE_WARNING_WP("-I- Mark mapped DIRTY #%d -> LIVE\n\r",
                                     i);
                    mapped->managed.blockStatuses[i].status =
                                                    NandBlockStatus_LIVE;
                }
            }
            /* Block is FREE or BAD*/
            else {

                /* Block is mapped -> remove it from mapping*/
                if (logicalBlock != -1) {

                    TRACE_WARNING_WP("-I- Unmap FREE or BAD #%d\n\r", i);
                    mapped->logicalMapping[logicalBlock] = -1;
                }
            }
        }
    }

    TRACE_WARNING_WP("-I- Mapping loaded from block #%d\n\r", physicalBlock);

    return 0;
}
//------------------------------------------------------------------------------
/// Loads the logical mapping contained in the given physical block.
/// Returns 0 if successful; otherwise, returns a NandCommon_ERROR code.
/// \param mapped  Pointer to a MappedNandFlash instance.
/// \param physicalBlock  Physical block number.
//------------------------------------------------------------------------------
static unsigned char LoadLogicalMapping(
    struct MappedNandFlash *mapped,
    unsigned short physicalBlock)
{
    unsigned char error;
    unsigned short pageDataSize =
                    NandFlashModel_GetPageDataSize(MODEL(mapped));
    unsigned short numBlocks =
                    ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
    unsigned char *pDataBuffer =  RawNandFlash_GetDataBuffer(RAW(mapped));
    unsigned int remainingSize;
    unsigned char *currentBuffer;
    unsigned short currentPage;
    unsigned int readSize;
    unsigned int i;
    unsigned char status;
    signed short logicalBlock;
    //signed short firstBlock, lastBlock;

    TRACE_INFO("LoadLogicalMapping(B#%d)\r\n", physicalBlock);

    // Load mapping from pages #1 - #XXX of block
    currentBuffer = (unsigned char *) mapped->logicalMapping;
    remainingSize = sizeof(mapped->logicalMapping);
    currentPage = 1;
    while (remainingSize > 0) {

        // Read page
        readSize = min(remainingSize, pageDataSize);
        error = ManagedNandFlash_ReadPage(MANAGED(mapped),
                                          physicalBlock,
                                          currentPage,
                                          pDataBuffer,
                                          0);
        if (error) {

            RawNandFlash_ReleaseDataBuffer(RAW(mapped));
            TRACE_ERROR(
                      "LoadLogicalMapping: Failed to load mapping\r\n");
            return error;
        }

        // Copy page info
        memcpy(currentBuffer, pDataBuffer, readSize);

        currentBuffer += readSize;
        remainingSize -= readSize;
        currentPage++;
    }

    // Store mapping block index
    mapped->logicalMappingBlock = physicalBlock;

    // Power-loss recovery
    for (i=0; i < numBlocks; i++) {

        // Check that this is not the logical mapping block
        if (i != physicalBlock) {

            status = mapped->managed.blockStatuses[i].status;
            logicalBlock = MappedNandFlash_PhysicalToLogical(mapped, i);

            // Block is LIVE
            if (status == NandBlockStatus_LIVE) {

                // Block is not mapped -> release it
                if (logicalBlock == -1) {

                    TRACE_WARNING_WP("-I- Release unmapped LIVE #%d\r\n",
                                     i);
                    ManagedNandFlash_ReleaseBlock(MANAGED(mapped), i);
                }
            }
            // Block is DIRTY
            else if (status == NandBlockStatus_DIRTY) {

                // Block is mapped -> fake it as live
                if (logicalBlock != -1) {

                    TRACE_WARNING_WP("-I- Mark mapped DIRTY #%d -> LIVE\r\n",
                                     i);
                    mapped->managed.blockStatuses[i].status =
                                                    NandBlockStatus_LIVE;
                }
            }
            // Block is FREE or BAD
            else {

                // Block is mapped -> remove it from mapping
                if (logicalBlock != -1) {

                    TRACE_WARNING_WP("-I- Unmap FREE or BAD #%d\r\n", i);
                    mapped->logicalMapping[logicalBlock] = -1;
                }
            }
        }
    }

    RawNandFlash_ReleaseDataBuffer(RAW(mapped));
    TRACE_WARNING_WP("-I- Mapping loaded from block #%d\r\n", physicalBlock);

    return 0;
}
/**
 * \brief  Scans a mapped nandflash to find an existing logical block mapping. If a
 * block contains the mapping, its index is stored in the provided variable (if
 * pointer is not 0).
 *
 * \param mapped  Pointer to a MappedNandFlash instance.
 * \param logicalMappingBlock  Pointer to a variable for storing the block number.
 * \return  0 if mapping has been found; otherwise returns
 * NandCommon_ERROR_NOMAPPING if no mapping exists, or another NandCommon_ERROR_xxx code.
 */
static unsigned char FindLogicalMappingBlock(
    const struct MappedNandFlash *mapped,
    signed short *logicalMappingBlock)
{
    unsigned short block;
    unsigned char found;
    unsigned short numBlocks = ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped));
    unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped));
    unsigned char error;
    unsigned char data[NandCommon_MAXPAGEDATASIZE];
    unsigned int i;

    //TRACE_INFO("FindLogicalMappingBlock ~%d\n\r", numBlocks);

    /* Search each LIVE block */
    found = 0;
    block = 0;
    while (!found && (block < numBlocks)) {

        /* Check that block is LIVE*/
        if (MANAGED(mapped)->blockStatuses[block].status == NandBlockStatus_LIVE) {

            /* Read block*/
            TRACE_INFO("Checking LIVE block #%d\n\r", block);
            error = ManagedNandFlash_ReadPage(MANAGED(mapped), block, 0, data, 0);
            if (!error) {

                /* Compare data with logical mapping pattern*/
                i = 0;
                found = 1;
                while ((i < pageDataSize) && found) {

                    if (data[i] != PATTERN(i)) {

                        found = 0;
                    }
                    i++;
                }

                /* If this is the mapping, stop looking*/
                if (found) {

                    TRACE_WARNING_WP("-I- Logical mapping in block #%d\n\r",
                                     block);
                    if (logicalMappingBlock) {

                        *logicalMappingBlock = block;
                    }
                    return 0;
                }
            }
            else if (error != NandCommon_ERROR_WRONGSTATUS) {

                TRACE_ERROR(
                          "FindLogicalMappingBlock: Failed to scan block #%d\n\r",
                          block);
                return error;
            }
        }

        block++;
    }

    TRACE_WARNING("No logical mapping found in device\n\r");
    return NandCommon_ERROR_NOMAPPING;
}
/**
 * \brief  Allocates the best-fitting physical block for the given logical block.
 *
 * \param translated  Pointer to a TranslatedNandFlash instance.
 * \param block  Logical block number.
 * \return 0 if successful; otherwise returns NandCommon_ERROR_NOBLOCKFOUND if
 * there are no more free blocks, or a NandCommon_ERROR code.
 */
static unsigned char AllocateBlock(
    struct TranslatedNandFlash *translated,
    unsigned short block)
{
    unsigned short freeBlock, liveBlock;
    unsigned char error;
    signed int eraseDifference;

    TRACE_DEBUG("Allocating a new block\n\r");

    /* Find youngest free block and youngest live block*/
    if (ManagedNandFlash_FindYoungestBlock(MANAGED(translated),
                                           NandBlockStatus_FREE,
                                           &freeBlock)) {

        TRACE_ERROR("AllocateBlock: Could not find a free block\n\r");
        return NandCommon_ERROR_NOBLOCKFOUND;
    }

    /* If this is the last free block, save the logical mapping in it and clean dirty blocks */
    TRACE_DEBUG("Number of FREE blocks: %d\n\r",
              ManagedNandFlash_CountBlocks(MANAGED(translated), NandBlockStatus_FREE));
    if (ManagedNandFlash_CountBlocks(MANAGED(translated),
                                     NandBlockStatus_FREE) == 1) {

        /* Save mapping and clean dirty blocks*/
        TRACE_DEBUG("Last FREE block, cleaning up ...\n\r");

        error = MappedNandFlash_SaveLogicalMapping(MAPPED(translated), freeBlock);
        if (error)
        {
            TRACE_ERROR("AllocateBlock: Failed to save mapping\n\r");
            return error;
        }
        error = ManagedNandFlash_EraseDirtyBlocks(MANAGED(translated));
        if (error)
        {
            TRACE_ERROR("AllocatedBlock: Failed to erase dirty blocks\n\r");
            return error;
        }

        /* Allocate new block*/
        return AllocateBlock(translated, block);
    }

    /* Find youngest LIVE block to check the erase count difference*/
    if (!ManagedNandFlash_FindYoungestBlock(MANAGED(translated),
                                            NandBlockStatus_LIVE,
                                            &liveBlock))
    {
        /* Calculate erase count difference*/
        TRACE_DEBUG("Free block erase count = %d\n\r", MANAGED(translated)->blockStatuses[freeBlock].eraseCount);
        TRACE_DEBUG("Live block erase count = %d\n\r", MANAGED(translated)->blockStatuses[liveBlock].eraseCount);
        eraseDifference = abs(MANAGED(translated)->blockStatuses[freeBlock].eraseCount
                              - MANAGED(translated)->blockStatuses[liveBlock].eraseCount);

        /* Check if it is too big*/
        if (eraseDifference > MAXERASEDIFFERENCE)
        {
            TRACE_WARNING("Erase difference too big, switching blocks\n\r");
            MappedNandFlash_Map(
                MAPPED(translated),
                MappedNandFlash_PhysicalToLogical(
                    MAPPED(translated),
                    liveBlock),
                freeBlock);
            ManagedNandFlash_CopyBlock(MANAGED(translated),
                                       liveBlock,
                                       freeBlock);

            /* Allocate a new block*/
            return AllocateBlock(translated, block);
        }
    }

    /* Map block*/
    TRACE_DEBUG("Allocating PB#%d for LB#%d\n\r", freeBlock, block);
    MappedNandFlash_Map(MAPPED(translated), block, freeBlock);

    return 0;
}