//------------------------------------------------------------------------------
/// Unlocks all the regions in the given address range. The actual unlock range is
/// reported through two output parameters.
/// Returns 0 if successful; otherwise returns an error code.
/// \param start  Start address of unlock range.
/// \param end  End address of unlock range.
/// \param pActualStart  Start address of the actual unlock range (optional).
/// \param pActualEnd  End address of the actual unlock range (optional).
//------------------------------------------------------------------------------
unsigned char FLASHD_Unlock(
    unsigned int start,
    unsigned int end,
    unsigned int *pActualStart,
    unsigned int *pActualEnd)
{
    AT91S_EFC *pStartEfc, *pEndEfc, *pEfc;
    unsigned int actualStart, actualEnd;
    unsigned short startPage, endPage;
    unsigned char error;
    unsigned short numPagesInRegion = AT91C_IFLASH_LOCK_REGION_SIZE / AT91C_IFLASH_PAGE_SIZE;
    
    // Compute actual unlock range and store it
    ComputeLockRange(start, end, &actualStart, &actualEnd);
    if (pActualStart) {

        *pActualStart = actualStart;
    }
    if (pActualEnd) {

        *pActualEnd = actualEnd;
    }

    // Compute page numbers
    EFC_TranslateAddress(&pStartEfc, actualStart, &startPage, 0);
    EFC_TranslateAddress(&pEndEfc, actualEnd, &endPage, 0);

    // Unlock all pages
    // If there is an EFC crossover, unlock all pages from first EFC
#if defined(AT91C_BASE_EFC1)
    if (pStartEfc != pEndEfc) {

        while (startPage < (AT91C_IFLASH_NB_OF_PAGES / 2)) {

            error = EFC_PerformCommand(pStartEfc, AT91C_MC_FCMD_UNLOCK, startPage);
            if (error) {

                return error;
            }
            startPage += numPagesInRegion;
        }
        startPage = 0;
    }
#endif
    pEfc = pEndEfc;

    // Unlock remaining pages
    while (startPage < endPage) {

        error = EFC_PerformCommand(pEfc, AT91C_MC_FCMD_UNLOCK, startPage);
        if (error) {

            return error;
        }
        startPage += numPagesInRegion;
    }

    return 0;
}
Beispiel #2
0
//------------------------------------------------------------------------------
/// Erases the entire flash.
/// Returns 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
unsigned char FLASHD_Erase(void)
{
    unsigned char error;

    error = EFC_PerformCommand(AT91C_BASE_EFC0, AT91C_MC_FCMD_ERASE_ALL, 0);
#ifdef AT91C_BASE_EFC1
    if (error) {

        return error;
    }
    error = EFC_PerformCommand(AT91C_BASE_EFC1, AT91C_MC_FCMD_ERASE_ALL, 0);
#endif

    return error;
}
Beispiel #3
0
/**
 * \brief Read the unique ID.
 *
 * \param uniqueID pointer on a 4bytes char containing the unique ID value.
 * \returns 0 if successful; otherwise returns an error code.
 */
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID )
{
    uint32_t dwError ;

    assert( pdwUniqueID != NULL ) ;

    pdwUniqueID[0] = 0 ;
    pdwUniqueID[1] = 0 ;
    pdwUniqueID[2] = 0 ;
    pdwUniqueID[3] = 0 ;

    EFC_StartCommand( EFC, EFC_FCMD_STUI, 0 ) ;

    pdwUniqueID[0] = *(uint32_t*) IFLASH_ADDR;
    pdwUniqueID[1] = *(uint32_t*)(IFLASH_ADDR + 4) ;
    pdwUniqueID[2] = *(uint32_t*)(IFLASH_ADDR + 8) ;
    pdwUniqueID[3] = *(uint32_t*)(IFLASH_ADDR + 12) ;

    dwError = EFC_PerformCommand( EFC, EFC_FCMD_SPUI, 0, _dwUseIAP ) ;
    if ( dwError )
    {
        return dwError ;
    }

    return 0 ;
}
Beispiel #4
0
/**
 * \brief Unlocks all the regions in the given address range. The actual unlock range is
 * reported through two output parameters.
 * \param start  Start address of unlock range.
 * \param end  End address of unlock range.
 * \param pActualStart  Start address of the actual unlock range (optional).
 * \param pActualEnd  End address of the actual unlock range (optional).
 * \return 0 if successful, otherwise returns an error code.
 */
extern uint32_t FLASHD_Unlock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
    Efc* pEfc ;
    uint32_t actualStart, actualEnd ;
    uint16_t startPage, endPage ;
    uint32_t dwError ;
    uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;

    /* Compute actual unlock range and store it */
    ComputeLockRange(start, end, &actualStart, &actualEnd);
    if ( pActualStart != NULL )
    {
        *pActualStart = actualStart ;
    }
    if ( pActualEnd != NULL )
    {
        *pActualEnd = actualEnd ;
    }

    /* Compute page numbers */
    EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
    EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;

    /* Unlock all pages */
    while ( startPage < endPage )
    {
        dwError = EFC_PerformCommand( pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP ) ;
        if ( dwError )
        {
            return dwError ;
        }
        startPage += numPagesInRegion ;
    }
    return 0 ;
}
Beispiel #5
0
//------------------------------------------------------------------------------
/// Erases the entire flash.
/// Returns 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
unsigned char FLASHD_Erase(unsigned int address)
{
    AT91S_EFC *pEfc;
    unsigned short page;
    unsigned short offset;
    unsigned char error;
    
#ifdef AT91C_BASE_EFC1
    // Convert wrapped address to physical address.
    address &= 0x19FFFF;
    SANITY_CHECK((address >=AT91C_IFLASH) || (address >=AT91C_IFLASH1));
    // Check EFC crossover 2 bank
    if (address >=AT91C_IFLASH1) {
        SANITY_CHECK(address <= (AT91C_IFLASH1 + AT91C_IFLASH1_SIZE));
    }
    else {
        SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));
    }
#else
    SANITY_CHECK((address >=AT91C_IFLASH) || (address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE)));
#endif
    // Translate write address
    EFC_TranslateAddress(&pEfc, address, &page, &offset);
    
    error = EFC_PerformCommand(pEfc, AT91C_EFC_FCMD_EA, 0);
    
    return error;
}
//------------------------------------------------------------------------------
/// Erases the entire flash.
/// Returns 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
unsigned char FLASHD_Erase(void)
{
    unsigned char error;

    error = EFC_PerformCommand(AT91C_EFC_FCMD_EA, 0);

    return error;
}
Beispiel #7
0
//------------------------------------------------------------------------------
/// Set Security Bit Command (SSB).
/// Returns 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
unsigned char FLASHD_SetSecurityBit(void)
{
    AT91S_EFC *pEfc = AT91C_BASE_EFC0;
 
    if( FLASHD_IsSecurityBitSet() == 0) {
        return EFC_PerformCommand(pEfc, AT91C_MC_FCMD_SET_SECURITY, 0);
    }
    else {
        return 0;
    }
}
Beispiel #8
0
//------------------------------------------------------------------------------
/// Returns the number of locked regions inside the given address range.
/// \param start  Start address of range.
/// \param end  End address of range.
//------------------------------------------------------------------------------
unsigned char FLASHD_IsLocked(unsigned int start, unsigned int end)
{
    AT91S_EFC *pEfc;
    unsigned short startPage, endPage;
    unsigned char startRegion, endRegion;
    unsigned int numPagesInRegion;
    unsigned int status;
    unsigned char error;
    unsigned int numLockedRegions = 0;
    
    SANITY_CHECK(end >= start);
#ifdef AT91C_BASE_EFC1
    // Convert wrapped address to physical address.
    start &= 0x19FFFF;
    end &= 0x19FFFF;
    // Check EFC crossover 2 bank
    SANITY_CHECK(((start >=AT91C_IFLASH) && (end <= AT91C_IFLASH + AT91C_IFLASH_SIZE))
                 || ((start >=AT91C_IFLASH1) && (end <= AT91C_IFLASH1 + AT91C_IFLASH1_SIZE)));
#else
    SANITY_CHECK((start >=AT91C_IFLASH) && (end <= AT91C_IFLASH + AT91C_IFLASH_SIZE));
#endif
    
    // Compute page numbers
    EFC_TranslateAddress(&pEfc, start, &startPage, 0);
    EFC_TranslateAddress(0, end, &endPage, 0);
    
    // Compute region numbers
    numPagesInRegion = AT91C_IFLASH_LOCK_REGION_SIZE / AT91C_IFLASH_PAGE_SIZE;
    startRegion = startPage / numPagesInRegion;
    endRegion = endPage / numPagesInRegion;
    if ((endPage % numPagesInRegion) != 0) {
        
        endRegion++;
    }
    
    // Retrieve lock status
    error = EFC_PerformCommand(pEfc, AT91C_EFC_FCMD_GLB, 0);
    ASSERT(!error, "-F- Error while trying to fetch lock bits status (0x%02X)\r\n", error);
    status = EFC_GetResult(pEfc);
    
    // Check status of each involved region
    while (startRegion < endRegion) {
        
        if ((status & (1 << startRegion)) != 0) {
            
            numLockedRegions++;
        }
        startRegion++;
    }
    
    return numLockedRegions;
}
Beispiel #9
0
//------------------------------------------------------------------------------
/// Sets the selected GPNVM bit.
/// Returns 0 if successful; otherwise returns an error code.
/// \param gpnvm  GPNVM index.
//------------------------------------------------------------------------------
unsigned char FLASHD_SetGPNVM(unsigned char gpnvm)
{
    SANITY_CHECK(gpnvm < CHIP_EFC_NUM_GPNVMS);
    
    if (!FLASHD_IsGPNVMSet(gpnvm)) {
        
        return EFC_PerformCommand(AT91C_BASE_EFC, AT91C_EFC_FCMD_SFB, gpnvm);
    }
    else {
        
        return 0;
    }
}
Beispiel #10
0
/**
 * \brief Clears the selected GPNVM bit.
 *
 * \param gpnvm  GPNVM bit index.
 * \returns 0 if successful; otherwise returns an error code.
 */
extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM )
{
    assert( ucGPNVM < GPNVM_NUM_MAX ) ;

    if ( FLASHD_IsGPNVMSet( ucGPNVM ) )
    {
        return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ;
    }
    else
    {
        return 0 ;
    }
}
//------------------------------------------------------------------------------
/// Clears the selected GPNVM bit.
/// Returns 0 if successful; otherwise returns an error code.
/// \param gpnvm  GPNVM index.
//------------------------------------------------------------------------------
unsigned char FLASHD_ClearGPNVM(unsigned char gpnvm)
{
    SANITY_CHECK(gpnvm < EFC_NUM_GPNVMS);

    if (FLASHD_IsGPNVMSet(gpnvm)) {

        return EFC_PerformCommand(AT91C_EFC_FCMD_CFB, gpnvm);
    }
    else {

        return 0;
    }
}
Beispiel #12
0
/**
 * \brief Sets the selected GPNVM bit.
 *
 * \param gpnvm  GPNVM bit index.
 * \returns 0 if successful; otherwise returns an error code.
 */
extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM )
{
    assert( ucGPNVM < 3 ) ;

    if ( !FLASHD_IsGPNVMSet( ucGPNVM ) )
    {
        return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ;
    }
    else
    {
        return 0 ;
    }
}
Beispiel #13
0
/**
 * \brief Erases flash by sector.
 *
 * \param dwAddress  Start address of be erased sector.
 *
 * \return 0 if successful; otherwise returns an error code.
 */
extern uint32_t FLASHD_EraseSector( uint32_t dwAddress )
{
    Efc* pEfc ;
    uint16_t wPage ;
    uint16_t wOffset ;
    uint32_t dwError ;

    assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ;

    /* Translate write address */
    EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ;
    dwError = EFC_PerformCommand( pEfc, EFC_FCMD_ES, wPage, _dwUseIAP ) ;

    return dwError ;
}
Beispiel #14
0
//------------------------------------------------------------------------------
/// Erases the entire flash.
/// Returns 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
unsigned char FLASHD_Erase(unsigned int address)
{
    AT91S_EFC *pEfc;
    unsigned short page;
    unsigned short offset;
    unsigned char error;

    SANITY_CHECK((address >=AT91C_IFLASH) || (address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE)));

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

    error = EFC_PerformCommand(pEfc, AT91C_MC_FCMD_ERASE_ALL, 0);

    return error;
}
Beispiel #15
0
/**
 * \brief Returns the number of locked regions inside the given address range.
 *
 * \param start  Start address of range
 * \param end    End address of range.
 */
extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end )
{
    uint32_t i, j;
    Efc *pEfc ;
    uint16_t startPage, endPage ;
    uint8_t startRegion, endRegion ;
    uint32_t numPagesInRegion ;
    uint32_t status[IFLASH_NB_OF_LOCK_BITS / 32u] ;
    uint32_t numLockedRegions = 0 ;

    assert( end >= start ) ;
    assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ;

    /* Compute page numbers */
    EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ;
    EFC_TranslateAddress( 0, end, &endPage, 0 ) ;

    /* Compute region numbers */
    numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
    startRegion = startPage / numPagesInRegion ;
    endRegion = endPage / numPagesInRegion ;
    if ((endPage % numPagesInRegion) != 0)
    {
        endRegion++ ;
    }

    /* Retrieve lock status */
    EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ;
    for (i = 0; i < (IFLASH_NB_OF_LOCK_BITS / 32u); i++)
    {
        status[i] = EFC_GetResult( pEfc ) ;
    }

    /* Check status of each involved region */
    while ( startRegion < endRegion )
    {
        i = startRegion / 32u;
        j = startRegion % 32u;
        if ( (status[i] & (1 << j)) != 0 )
        {
            numLockedRegions++ ;
        }
        startRegion++ ;
    }

    return numLockedRegions ;
}
Beispiel #16
0
/**
 * \brief Erases flash by pages.
 *
 * \param dwAddress  Start address of be erased pages.
 * \param dwPageNum  Number of pages to be erased with EPA command (4, 8, 16, 32)
 *
 * \return 0 if successful; otherwise returns an error code.
 */
extern uint32_t FLASHD_ErasePages( uint32_t dwAddress, uint32_t dwPageNum )
{
    Efc* pEfc ;
    uint16_t wPage ;
    uint16_t wOffset ;
    uint32_t dwError ;
    static uint32_t dwFarg ;

    assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ;

    /* Translate write address */
    EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ;

    /* Get FARG field for EPA command:
     * The first page to be erased is specified in the FARG[15:2] field of
     * the MC_FCR register. The first page number must be modulo 4, 8,16 or 32
     * according to the number of pages to erase at the same time.
     *
     * The 2 lowest bits of the FARG field define the number of pages to
     * be erased (FARG[1:0]).
     */
    if (dwPageNum == 32)
    {
        wPage &= ~(32u - 1u);
        dwFarg = (wPage << 2) | 3; /* 32 pages */
    }
    else if (dwPageNum == 16)
    {
        wPage &= ~(16u - 1u);
        dwFarg = (wPage << 2) | 2; /* 16 pages */
    }
    else if (dwPageNum == 8)
    {
        wPage &= ~(8u - 1u);
        dwFarg = (wPage << 2) | 1; /* 8 pages */
    }
    else
    {
        wPage &= ~(4u - 1u);
        dwFarg = (wPage << 2) | 0; /* 4 pages */
    }

    dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EPA, dwFarg, _dwUseIAP ) ;

    return dwError ;
}
Beispiel #17
0
/**
 * \brief Returns the number of locked regions inside the given address range.
 *
 * \param start  Start address of range
 * \param end    End address of range.
 */
extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end )
{
	const uint32_t IFLASH_PAGE_SIZE = IS_SAM3() ? IFLASH_PAGE_SIZE_SAM3 : IFLASH_PAGE_SIZE_SAM4;
	const uint32_t IFLASH_LOCK_REGION_SIZE = IS_SAM3() ? IFLASH_LOCK_REGION_SIZE_SAM3 : IFLASH_LOCK_REGION_SIZE_SAM4;

    Efc *pEfc ;
    uint16_t startPage, endPage ;
    uint8_t startRegion, endRegion ;
    uint32_t numPagesInRegion ;
    uint32_t status ;
    __attribute__((unused)) uint32_t dwError ;
    uint32_t numLockedRegions = 0 ;

    assert( end >= start ) ;
    assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ;

    // Compute page numbers
    EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ;
    EFC_TranslateAddress( 0, end, &endPage, 0 ) ;

    // Compute region numbers
    numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
    startRegion = startPage / numPagesInRegion ;
    endRegion = endPage / numPagesInRegion ;
    if ((endPage % numPagesInRegion) != 0)
    {
        endRegion++ ;
    }

    // Retrieve lock status
    dwError = EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ;
    assert( !dwError ) ;
    status = EFC_GetResult( pEfc ) ;

    // Check status of each involved region
    while ( startRegion < endRegion )
    {
        if ( (status & (1 << startRegion)) != 0 )
        {
            numLockedRegions++ ;
        }
        startRegion++ ;
    }

    return numLockedRegions ;
}
Beispiel #18
0
/**
 * \brief Check if the given GPNVM bit is set or not.
 *
 * \param gpnvm  GPNVM bit index.
 * \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
 */
extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM )
{
    uint32_t dwStatus ;

    assert( ucGPNVM < GPNVM_NUM_MAX ) ;

    /* Get GPNVMs status */
    EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ;
    dwStatus = EFC_GetResult( EFC ) ;

    /* Check if GPNVM is set */
    if ( (dwStatus & (1 << ucGPNVM)) != 0 )
    {
        return 1 ;
    }
    else
    {
        return 0 ;
    }
}
Beispiel #19
0
//------------------------------------------------------------------------------
/// Unlocks all the regions in the given address range. The actual unlock range is
/// reported through two output parameters.
/// Returns 0 if successful; otherwise returns an error code.
/// \param start  Start address of unlock range.
/// \param end  End address of unlock range.
/// \param pActualStart  Start address of the actual unlock range (optional).
/// \param pActualEnd  End address of the actual unlock range (optional).
//------------------------------------------------------------------------------
unsigned char FLASHD_Unlock(
                            unsigned int start,
                            unsigned int end,
                            unsigned int *pActualStart,
                            unsigned int *pActualEnd)
{
    AT91S_EFC *pEfc;
    unsigned int actualStart, actualEnd;
    unsigned short startPage, endPage;
    unsigned char error;
    unsigned short numPagesInRegion = AT91C_IFLASH_LOCK_REGION_SIZE / AT91C_IFLASH_PAGE_SIZE;
    
    // Compute actual unlock range and store it
    ComputeLockRange(start, end, &actualStart, &actualEnd);
    if (pActualStart) {
        
        *pActualStart = actualStart;
    }
    if (pActualEnd) {
        
        *pActualEnd = actualEnd;
    }
    
    // Compute page numbers
    EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0);
    EFC_TranslateAddress(0, actualEnd, &endPage, 0);
    
    // Unlock all pages
    while (startPage < endPage) {
        
        error = EFC_PerformCommand(pEfc, AT91C_EFC_FCMD_CLB, startPage);
        if (error) {
            
            return error;
        }
        startPage += numPagesInRegion;
    }
    
    return 0;
}
//------------------------------------------------------------------------------
/// Returns the number of locked regions inside the given address range.
/// \param start  Start address of range.
/// \param end  End address of range.
//------------------------------------------------------------------------------
unsigned char FLASHD_IsLocked(unsigned int start, unsigned int end)
{
    unsigned short startPage, endPage;
    unsigned char startRegion, endRegion;
    unsigned int numPagesInRegion;
    unsigned int status;
    unsigned char error;
    unsigned int numLockedRegions = 0;

    // Compute page numbers
    EFC_TranslateAddress(start, &startPage, 0);
    EFC_TranslateAddress(end, &endPage, 0);

    // Compute region numbers
    numPagesInRegion = AT91C_IFLASH_LOCK_REGION_SIZE / AT91C_IFLASH_PAGE_SIZE;
    startRegion = startPage / numPagesInRegion;
    endRegion = endPage / numPagesInRegion;
    if ((endPage % numPagesInRegion) != 0) {

        endRegion++;
    }

    // Retrieve lock status
    error = EFC_PerformCommand(AT91C_EFC_FCMD_GLB, 0);
    ASSERT(!error, "-F- Error while trying to fetch lock bits status (0x%02X)\n\r", error);
    status = EFC_GetResult();

    // Check status of each involved region
    while (startRegion < endRegion) {

        if ((status & (1 << startRegion)) != 0) {

            numLockedRegions++;
        }
        startRegion++;
    }

    return numLockedRegions;
}
Beispiel #21
0
/**
 * \brief Check if the given GPNVM bit is set or not.
 *
 * \param gpnvm  GPNVM bit index.
 * \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
 */
extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM )
{
	__attribute__((unused)) uint32_t dwError ;
    uint32_t dwStatus ;

    assert( ucGPNVM < 2 ) ;

    /* Get GPNVMs status */
    dwError = EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ;
    assert( !dwError ) ;
    dwStatus = EFC_GetResult( EFC ) ;

    /* Check if GPNVM is set */
    if ( (dwStatus & (1 << ucGPNVM)) != 0 )
    {
        return 1 ;
    }
    else
    {
        return 0 ;
    }
}
//------------------------------------------------------------------------------
/// Returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
/// \param gpnvm  GPNVM bit index.
//------------------------------------------------------------------------------
unsigned char FLASHD_IsGPNVMSet(unsigned char gpnvm)
{
    unsigned char error;
    unsigned int status;

    SANITY_CHECK(gpnvm < EFC_NUM_GPNVMS);

    // Get GPNVMs status
    error = EFC_PerformCommand(AT91C_EFC_FCMD_GFB, 0);
    ASSERT(!error, "-F- Error while trying to fetch GPNVMs status (0x%02X)\n\r", error);
    status = EFC_GetResult();

    // Check if GPNVM is set
    if ((status & (1 << gpnvm)) != 0) {

        return 1;
    }
    else {

        return 0;
    }
}
Beispiel #23
0
unsigned char FLASHD_ReadUniqueID (unsigned long * uniqueID)
{
    unsigned char error;
    
    SANITY_CHECK(uniqueID != NULL);
    
    uniqueID[0] = 0;
    uniqueID[1] = 0;
    uniqueID[2] = 0;
    uniqueID[3] = 0;
    
    EFC_StartCommand(AT91C_BASE_EFC, AT91C_EFC_FCMD_STUI, 0);
    
    uniqueID[0] = *(unsigned int *)AT91C_IFLASH;
    uniqueID[1] = *(unsigned int *)(AT91C_IFLASH + 4);
    uniqueID[2] = *(unsigned int *)(AT91C_IFLASH + 8);
    uniqueID[3] = *(unsigned int *)(AT91C_IFLASH + 12);
    
    error = EFC_PerformCommand(AT91C_BASE_EFC, AT91C_EFC_FCMD_SPUI, 0);
    if (error) return error;
    
    return 0;
}
Beispiel #24
0
//------------------------------------------------------------------------------
/// Clears the selected GPNVM bit.
/// Returns 0 if successful; otherwise returns an error code.
/// \param gpnvm  GPNVM index.
//------------------------------------------------------------------------------
unsigned char FLASHD_ClearGPNVM(unsigned char gpnvm)
{
    AT91S_EFC *pEfc = AT91C_BASE_EFC0;

    //SANITY_CHECK(gpnvm < EFC_NUM_GPNVMS);

    if (FLASHD_IsGPNVMSet(gpnvm)) {

#ifdef AT91C_BASE_EFC1
        // GPNVM in EFC1
        if (gpnvm >= 8) {

            pEfc = AT91C_BASE_EFC1;
            gpnvm -= 8;
        }
#endif

        return EFC_PerformCommand(pEfc, AT91C_MC_FCMD_CLR_GP_NVM, gpnvm);
    }
    else {

        return 0;
    }
}
Beispiel #25
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 ;
}
Beispiel #26
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;
}
Beispiel #27
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 ;
}
//------------------------------------------------------------------------------
/// 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;
}