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 )
{
	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 #2
0
/**
 * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
 *
 * \note It does NOT set the FMCN field automatically.
 * \param efc  Pointer to a Efc instance
 * \param command  Command to execute.
 * \param argument  Command argument (should be 0 if not used).
 */
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{
    /* Check command & argument */
    switch ( dwCommand )
    {
        case EFC_FCMD_WP:
        case EFC_FCMD_WPL:
        case EFC_FCMD_EWP:
        case EFC_FCMD_EWPL:
        case EFC_FCMD_SLB:
        case EFC_FCMD_CLB:
            assert( dwArgument < (IS_SAM3() ? IFLASH_NB_OF_PAGES_SAM3 : IFLASH_NB_OF_PAGES_SAM4) ) ;
        break ;

        case EFC_FCMD_SFB:
        case EFC_FCMD_CFB:
            assert( dwArgument < 2 ) ;
        break;

        case EFC_FCMD_GETD:
        case EFC_FCMD_EA:
        case EFC_FCMD_GLB:
        case EFC_FCMD_GFB:
        case EFC_FCMD_STUI:
            assert( dwArgument == 0 ) ;
        break;

        default: assert( 0 ) ;
    }

    /* Start command Embedded flash */
    assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
    efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
}
Exemple #3
0
/**
 * \brief Translates the given address page and offset values.
 * \note The resulting values are stored in the provided variables if they are not null.
 *
 * \param efc  Pointer to a Efc instance
 * \param address  Address to translate.
 * \param pPage  First page accessed.
 * \param pOffset  Byte offset in first page.
 */
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{
	const uint32_t IFLASH_PAGE_SIZE = IS_SAM3() ? IFLASH_PAGE_SIZE_SAM3 : IFLASH_PAGE_SIZE_SAM4;

    Efc *pEfc ;
    uint16_t wPage ;
    uint16_t wOffset ;

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

    pEfc = EFC ;
    wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
    wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;

    TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
    /* Store values */
    if ( pEfc )
    {
        *ppEfc = pEfc ;
    }

    if ( pwPage )
    {
        *pwPage = wPage ;
    }

    if ( pwOffset )
    {
        *pwOffset = wOffset ;
    }
}
Exemple #4
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 ;
}
Exemple #5
0
/**
 * \brief Computes the address of a flash access given the page and offset.
 *
 * \param efc  Pointer to a Efc instance
 * \param page  Page number.
 * \param offset  Byte offset inside page.
 * \param pAddress  Computed address (optional).
 */
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{
	const uint32_t IFLASH_PAGE_SIZE = IS_SAM3() ? IFLASH_PAGE_SIZE_SAM3 : IFLASH_PAGE_SIZE_SAM4;
    uint32_t dwAddress ;
	
    assert( efc ) ;
    assert( wPage <= (IS_SAM3() ? IFLASH_NB_OF_PAGES_SAM3 : IFLASH_NB_OF_PAGES_SAM4) ) ;
    assert( wOffset < IFLASH_PAGE_SIZE ) ;
	
    /* Compute address */
    dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
	
    /* Store result */
    if ( pdwAddress != NULL )
	{
        *pdwAddress = dwAddress ;
    }
}
Exemple #6
0
/**
 * \brief Locks all the regions in the given address range. The actual lock range is
 * reported through two output parameters.
 *
 * \param start  Start address of lock range.
 * \param end    End address of lock range.
 * \param pActualStart  Start address of the actual lock range (optional).
 * \param pActualEnd  End address of the actual lock range (optional).
 * \return 0 if successful, otherwise returns an error code.
 */
extern uint32_t FLASHD_Lock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
	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 ;
    uint32_t actualStart, actualEnd ;
    uint16_t startPage, endPage ;
    uint32_t dwError ;
    uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;

    /* Compute actual lock 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 ) ;

    /* Lock all pages */
    while ( startPage < endPage )
    {
        dwError = EFC_PerformCommand( pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP ) ;
        if ( dwError )
        {
            return dwError ;
        }
        startPage += numPagesInRegion;
    }

    return 0 ;
}
Exemple #7
0
void brick_init(void) {
	// Wait 5ms so everything can power up
	SLEEP_MS(5);
	logging_init();

	logsi("Booting %d\n\r", BRICK_DEVICE_IDENTIFIER);
	logsi("Compiled on %s %s\n\r", __DATE__, __TIME__);
	logsi("Processor family %s\n\r", IS_SAM3() ? "SAM3S" : "SAM4S");

    led_init();
	led_on(LED_STD_BLUE);
#ifdef LED_STD_RED
#if LOGGING_LEVEL == LOGGING_NONE
	led_off(LED_STD_RED);
#else
	led_on(LED_STD_RED);
#endif
#endif
	logsi("LEDs initialized\n\r");

	com_info.uid = uid_get_uid32();

	// Add 0 at end for printing
    char sn[MAX_BASE58_STR_SIZE] = {'\0'};
    uid_to_serial_number(com_info.uid, sn);
    set_serial_number_descriptor(sn, MAX_BASE58_STR_SIZE);
    logsi("Unique ID %s (%lu)\n\r\n\r", sn, com_info.uid);

    wdt_start();
    logsi("Watchdog disabled\n\r");

    mutex_init();
    logsi("Mutexes initialized\n\r");

	// Disable JTAG (Pins are needed for i2c)
#ifdef DISABLE_JTAG_ON_STARTUP
	MATRIX->CCFG_SYSIO |= (CCFG_SYSIO_SYSIO12 |
	                       CCFG_SYSIO_SYSIO4  |
	                       CCFG_SYSIO_SYSIO5  |
	                       CCFG_SYSIO_SYSIO6  |
	                       CCFG_SYSIO_SYSIO7);
	logsi("JTAG disabled\n\r");
#endif

	com_info.current = COM_NONE;
    PIO_InitializeInterrupts(15);

    bricklet_clear_eeproms();
    i2c_eeprom_master_init(TWI_BRICKLET);
    logsi("I2C for Bricklets initialized\n\r");

	usb_detect_configure();

	adc_init();
	adc_enable_temperature_sensor();
#ifndef NO_PERIODIC_ADC_CONVERISION
	adc_start_periodic_conversion();
#endif
    logsi("A/D converter initialized\n\r");

	bricklet_init();
}
Exemple #8
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 ;
}