Exemple #1
0
/**
 * \brief Computes the lock range associated with the given address range.
 *
 * \param dwStart  Start address of lock range.
 * \param dwEnd  End address of lock range.
 * \param pdwActualStart  Actual start address of lock range.
 * \param pdwActualEnd  Actual end address of lock range.
 */
static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd )
{
    Efc* pStartEfc ;
    Efc* pEndEfc ;
    uint16_t wStartPage ;
    uint16_t wEndPage ;
    uint16_t wNumPagesInRegion ;
    uint16_t wActualStartPage ;
    uint16_t wActualEndPage ;

    /* Convert start and end address in page numbers */
    EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ;
    EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ;

    /* Find out the first page of the first region to lock */
    wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
    wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ;
    wActualEndPage = wEndPage ;

    if ( (wEndPage % wNumPagesInRegion) != 0 )
    {
        wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ;
    }
    /* Store actual page numbers */
    EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
    EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
    TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r",
            (unsigned int)*pdwActualStart, (unsigned int)*pdwActualEnd ) ;
}
Exemple #2
0
//------------------------------------------------------------------------------
/// Computes the lock range associated with the given address range.
/// \param start  Start address of lock range.
/// \param end  End address of lock range.
/// \param pActualStart  Actual start address of lock range.
/// \param pActualEnd  Actual end address of lock range.
//------------------------------------------------------------------------------
static void ComputeLockRange(
    unsigned int start,
    unsigned int end,
    unsigned int *pActualStart,
    unsigned int *pActualEnd)
{
    AT91S_EFC *pStartEfc, *pEndEfc;
    unsigned short startPage, endPage;
    unsigned short numPagesInRegion;
    unsigned short actualStartPage, actualEndPage;

    // Convert start and end address in page numbers
    EFC_TranslateAddress(start, &pStartEfc, &startPage, 0);
    EFC_TranslateAddress(end, &pEndEfc, &endPage, 0);

    // Find out the first page of the first region to lock
    numPagesInRegion = AT91C_IFLASH_LOCK_REGION_SIZE / AT91C_IFLASH_PAGE_SIZE;
    actualStartPage = startPage - (startPage % numPagesInRegion);
    actualEndPage = endPage;
    if ((endPage % numPagesInRegion) != 0) {

        actualEndPage += numPagesInRegion - (endPage % numPagesInRegion);
    }

    // Store actual page numbers
    EFC_ComputeAddress(pStartEfc, actualStartPage, 0, pActualStart);
    EFC_ComputeAddress(pEndEfc, actualEndPage, 0, pActualEnd);
    //TRACE_DEBUG("Actual lock range is 0x%06X - 0x%06X\n\r", *pActualStart, *pActualEnd);
}
Exemple #3
0
/**
 * \brief Computes the lock range associated with the given address range.
 *
 * \param dwStart  Start address of lock range.
 * \param dwEnd  End address of lock range.
 * \param pdwActualStart  Actual start address of lock range.
 * \param pdwActualEnd  Actual end address of lock range.
 */
static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd )
{
	const uint32_t IFLASH_PAGE_SIZE = IS_SAM3() ? IFLASH_PAGE_SIZE_SAM3 : IFLASH_PAGE_SIZE_SAM4;
	const uint32_t IFLASH_NB_OF_PAGES = IS_SAM3() ? IFLASH_NB_OF_PAGES_SAM3 : IFLASH_NB_OF_PAGES_SAM4;
	const uint32_t IFLASH_LOCK_REGION_SIZE = IS_SAM3() ? IFLASH_LOCK_REGION_SIZE_SAM3 : IFLASH_LOCK_REGION_SIZE_SAM4;

    Efc* pStartEfc ;
    Efc* pEndEfc ;
    uint16_t wStartPage ;
    uint16_t wEndPage ;
    uint16_t wNumPagesInRegion ;
    uint16_t wActualStartPage ;
    uint16_t wActualEndPage ;

    // Convert start and end address in page numbers
    EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ;
    EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ;

    // Find out the first page of the first region to lock
    wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
    wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ;
    wActualEndPage = wEndPage ;
    wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ;

    if ( wActualEndPage > IFLASH_NB_OF_PAGES ) {
        wActualEndPage = IFLASH_NB_OF_PAGES;
    }

    // Store actual page numbers
    EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
    EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
    TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ;
}
Exemple #4
0
/**
 * \brief Writes a data buffer in the internal flash
 *
 * \note This function works in polling mode, and thus only returns when the
 * data has been effectively written.
 * \param address  Write address.
 * \param pBuffer  Data buffer.
 * \param size  Size of data buffer in bytes.
 * \return 0 if successful, otherwise returns an error code.
 */
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize )
{
    Efc* pEfc ;
    uint16_t page ;
    uint16_t offset ;
    uint32_t writeSize ;
    uint32_t pageAddress ;
    uint16_t padding ;
    uint32_t dwError ;
    uint32_t dwIdx ;
    uint32_t *pAlignedDestination ;
    uint8_t  *pucPageBuffer = (uint8_t *)_pdwPageBuffer;

    assert( pvBuffer ) ;
    assert( dwAddress >=IFLASH_ADDR ) ;
    assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ;

    /* Translate write address */
    EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ;

    /* Write all pages */
    while ( dwSize > 0 )
    {
        /* Copy data in temporary buffer to avoid alignment problems */
        writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ;
        EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ;
        padding = IFLASH_PAGE_SIZE - offset - writeSize ;

        /* Pre-buffer data */
        memcpy( pucPageBuffer, (void *) pageAddress, offset);

        /* Buffer data */
        memcpy( pucPageBuffer + offset, pvBuffer, writeSize);

        /* Post-buffer data */
        memcpy( pucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);

        /* Write page
         * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption
         */
        pAlignedDestination = (uint32_t*)pageAddress ;
        for (dwIdx = 0; dwIdx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ dwIdx) {
            *pAlignedDestination++ = _pdwPageBuffer[dwIdx];
        }

        /* Note for sam3s16 and sam4s:
         * It is not possible to use Erase and write Command (EWP) on all Flash (this
         * command is available on the First 2 Small Sector, 16K Bytes). For the next
         * block, Erase them first then use Write page command.
         */
        /* Send writing command */
        dwError = EFC_PerformCommand( pEfc, EFC_FCMD_WP, page, _dwUseIAP ) ;
        if ( dwError )
        {
            return dwError ;
        }

        /* Progression */
        pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ;
        dwSize -= writeSize ;
        page++;
        offset = 0;
    }

    return 0 ;
}
Exemple #5
0
//------------------------------------------------------------------------------
/// Writes a data buffer in the internal flash. This function works in polling
/// mode, and thus only returns when the data has been effectively written.
/// Returns 0 if successful; otherwise returns an error code.
/// \param address  Write address.
/// \param pBuffer  Data buffer.
/// \param size  Size of data buffer in bytes.
//------------------------------------------------------------------------------
unsigned char FLASHD_Write(
    unsigned int address,
    const void *pBuffer,
    unsigned int size)
{
    AT91S_EFC *pEfc;
    unsigned short page;
    unsigned short offset;
    unsigned int writeSize;
    unsigned int pageAddress;
    unsigned short padding;
    unsigned char error;

    unsigned int sizeTmp;
    unsigned int *pAlignedDestination; 
    unsigned int *pAlignedSource;

    ////SANITY_CHECK(address >= (unsigned int)AT91C_IFLASH);
    ////SANITY_CHECK(pBuffer);
    ////SANITY_CHECK((address + size) <= (unsigned int)(AT91C_IFLASH + AT91C_IFLASH_SIZE));

    
#if OS_CRITICAL_METHOD == 3u   /* Allocate storage for CPU status register   */
    OS_CPU_SR  cpu_sr = 0u;
#endif
    OS_ENTER_CRITICAL(); 
        
    
    // Translate write address
    EFC_TranslateAddress(address, &pEfc, &page, &offset);

    // Write all pages
    while (size > 0) {

        // Copy data in temporary buffer to avoid alignment problems
        writeSize = min(AT91C_IFLASH_PAGE_SIZE - offset, size);
        EFC_ComputeAddress(pEfc, page, 0, &pageAddress);
        padding = AT91C_IFLASH_PAGE_SIZE - offset - writeSize;

        // Pre-buffer data (mask with 0xFF)
        memcpy(pPageBuffer, (void *) pageAddress, offset);

        // Buffer data
        memcpy(pPageBuffer + offset, pBuffer, writeSize);

        // Post-buffer data
        memcpy(pPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);

        // Write page
        // Writing 8-bit and 16-bit data is not allowed 
        // and may lead to unpredictable data corruption
#ifdef EFC_EVEN_ODD_PROG
        // Write even words first with auto erase
        pAlignedDestination = (unsigned int*)pageAddress;
        pAlignedSource = (unsigned int*)pPageBuffer;
        sizeTmp = AT91C_IFLASH_PAGE_SIZE;
        while (sizeTmp >= 4) {

            *pAlignedDestination = *pAlignedSource;
            pAlignedDestination += 2;
            pAlignedSource += 2;
            sizeTmp -= 8;
        }
        // Send writing command
        error = EFC_PerformCommand(pEfc, AT91C_MC_FCMD_START_PROG, page);
        if (error) {
            OS_EXIT_CRITICAL();
            return error;
        }

        // Then write odd words without auto erase
        EFC_SetEraseBeforeProgramming(AT91C_BASE_EFC0, 0);
#ifdef AT91C_BASE_EFC1
        EFC_SetEraseBeforeProgramming(AT91C_BASE_EFC1, 0);
#endif
        pAlignedDestination = (unsigned int*)pageAddress + 1;
        pAlignedSource = (unsigned int*)pPageBuffer + 1;
        sizeTmp = AT91C_IFLASH_PAGE_SIZE;
        while (sizeTmp >= 4) {

            *pAlignedDestination = *pAlignedSource;
            pAlignedDestination += 2;
            pAlignedSource += 2;
            sizeTmp -= 8;
        }

        // Send writing command
        error = EFC_PerformCommand(pEfc, AT91C_MC_FCMD_START_PROG, page);
        if (error) {
            OS_EXIT_CRITICAL();
            return error;
        }

        EFC_SetEraseBeforeProgramming(AT91C_BASE_EFC0, 1);
#ifdef AT91C_BASE_EFC1
        EFC_SetEraseBeforeProgramming(AT91C_BASE_EFC1, 1);
#endif

#else 
        pAlignedDestination = (unsigned int*)pageAddress;
        pAlignedSource = (unsigned int*)pPageBuffer;        
        sizeTmp = AT91C_IFLASH_PAGE_SIZE;
        while (sizeTmp >= 4) {

            *pAlignedDestination++ = *pAlignedSource++;
            sizeTmp -= 4;
        }        
        
        // Send writing command
        error = EFC_PerformCommand(pEfc, AT91C_MC_FCMD_START_PROG, page);
        if (error) {
            OS_EXIT_CRITICAL();
            return error;
        }
#endif
        // Progression
        address += AT91C_IFLASH_PAGE_SIZE;
        pBuffer = (void *) ((unsigned int) pBuffer + writeSize);
        size -= writeSize;
        page++;
        offset = 0;

#if defined(AT91C_BASE_EFC1)
        // Handle EFC crossover
        if ((pEfc == AT91C_BASE_EFC0) && (page >= (AT91C_IFLASH_NB_OF_PAGES / 2))) {

            pEfc = AT91C_BASE_EFC1;
            page = 0;
        }
#endif
    } //while end
    
    OS_EXIT_CRITICAL();
    
    return 0;
}
//------------------------------------------------------------------------------
/// Writes a data buffer in the internal flash. This function works in polling
/// mode, and thus only returns when the data has been effectively written.
/// Returns 0 if successful; otherwise returns an error code.
/// \param address  Write address.
/// \param pBuffer  Data buffer.
/// \param size  Size of data buffer in bytes.
//------------------------------------------------------------------------------
unsigned char FLASHD_Write(
    unsigned int address,
    const void *pBuffer,
    unsigned int size)
{
    unsigned short page;
    unsigned short offset;
    unsigned int writeSize;
    unsigned int pageAddress;
    unsigned short padding;
    unsigned char error;

    unsigned int sizeTmp;
    unsigned int *pAlignedDestination; 
    unsigned int *pAlignedSource;
    
    SANITY_CHECK(address >= AT91C_IFLASH);
    SANITY_CHECK(pBuffer);
    SANITY_CHECK((address + size) <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));

    // Translate write address
    EFC_TranslateAddress(address, &page, &offset);

    // Write all pages
    while (size > 0) {

        // Copy data in temporary buffer to avoid alignment problems
        writeSize = min(AT91C_IFLASH_PAGE_SIZE - offset, size);
        EFC_ComputeAddress(page, 0, &pageAddress);
        padding = AT91C_IFLASH_PAGE_SIZE - offset - writeSize;

        // Pre-buffer data
        memcpy(pPageBuffer, (void *) pageAddress, offset);

        // Buffer data
        memcpy(pPageBuffer + offset, pBuffer, writeSize);

        // Post-buffer data
        memcpy(pPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);

        // Write page
        // Writing 8-bit and 16-bit data is not allowed 
        // and may lead to unpredictable data corruption
        pAlignedDestination = (unsigned int*)pageAddress;
        pAlignedSource = (unsigned int*)pPageBuffer;        
        sizeTmp = AT91C_IFLASH_PAGE_SIZE;
        while (sizeTmp >= 4) {

            *pAlignedDestination++ = *pAlignedSource++;
            sizeTmp -= 4;
        }        
               
        // Send writing command
        error = EFC_PerformCommand(AT91C_EFC_FCMD_EWP, page);
        if (error) {

            return error;
        }

        // Progression
        address += AT91C_IFLASH_PAGE_SIZE;
        pBuffer = (void *) ((unsigned int) pBuffer + writeSize);
        size -= writeSize;
        page++;
        offset = 0;
    }

    return 0;
}
Exemple #7
0
/**
 * \brief Writes a data buffer in the internal flash
 *
 * \note This function works in polling mode, and thus only returns when the
 * data has been effectively written.
 * \param address  Write address.
 * \param pBuffer  Data buffer.
 * \param size  Size of data buffer in bytes.
 * \return 0 if successful, otherwise returns an error code.
 */
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize )
{
	const uint32_t IFLASH_PAGE_SIZE = IS_SAM3() ? IFLASH_PAGE_SIZE_SAM3 : IFLASH_PAGE_SIZE_SAM4;

    Efc* pEfc ;
    uint16_t page ;
    uint16_t offset ;
    uint32_t writeSize ;
    uint32_t pageAddress ;
    uint16_t padding ;
    uint32_t dwError ;
    uint32_t sizeTmp ;
    uint32_t *pAlignedDestination ;
    uint32_t *pAlignedSource ;

    assert( pvBuffer ) ;
    assert( dwAddress >=IFLASH_ADDR ) ;
    assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ;

    /* Translate write address */
    EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ;

    /* Write all pages */
    while ( dwSize > 0 )
    {
        /* Copy data in temporary buffer to avoid alignment problems */
        writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ;
        EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ;
        padding = IFLASH_PAGE_SIZE - offset - writeSize ;

        /* Pre-buffer data */
        memcpy( _aucPageBuffer, (void *) pageAddress, offset);

        /* Buffer data */
        memcpy( _aucPageBuffer + offset, pvBuffer, writeSize);

        /* Post-buffer data */
        memcpy( _aucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);

        /* Write page
         * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption
         */
        pAlignedDestination = (uint32_t*)pageAddress ;
        pAlignedSource = (uint32_t*)_adwPageBuffer ;
        sizeTmp = IFLASH_PAGE_SIZE ;

        while ( sizeTmp >= 4 )
        {
            *pAlignedDestination++ = *pAlignedSource++;
            sizeTmp -= 4;
        }

       	// On SAM3 we do erase and write page here.
       	// On SAM4 we can't use EWP, we erased pages before, we only use WP here.
        // First 2*8kb on SAM4 can use EWP.
       	if(IS_SAM3() || (page < 32)) {
       		dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EWP, page, _dwUseIAP);
       	} else {
       		dwError = EFC_PerformCommand(pEfc, EFC_FCMD_WP, page, _dwUseIAP);
       	}

        if (dwError) {
            return dwError;
        }

        /* Progression */
        dwAddress += IFLASH_PAGE_SIZE ;
        pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ;
        dwSize -= writeSize ;
        page++;
        offset = 0;
    }

    return 0 ;
}