extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) { if ( dwUseIAP != 0 ) { /* Pointer on IAP function in ROM */ static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ; IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ; IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ; return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ; } else { uint32_t dwStatus ; efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; do { dwStatus = efc->EEFC_FSR ; } while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ; return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ; } }
void Reset_Handler(void) { uint32_t *src; uint32_t *dest; //System initialization SystemInit(); //Initialize the relocate segment src = &_etext; dest = &_srelocate; if(src != dest) { while(dest < &_erelocate) { *dest++ = *src++; } } //Clear the zero segment for(dest = &_szero; dest < &_ezero;) { *dest++ = 0; } //Set the vector table base address src = (uint32_t *) & _sfixed; SCB->VTOR = ((uint32_t) src & SCB_VTOR_TBLOFF_Msk); #ifdef ENABLE_TCM //32KB EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(8)); EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(7)); TCM_Enable(); #else EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(8)); EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(7)); TCM_Disable(); #endif //C library initialization __libc_init_array(); //Branch to main function main(); //Endless loop while(1); }
/** * \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 < IFLASH_NB_OF_PAGES ) ; 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) ; }
void banzai() { // Disable all interrupts __disable_irq(); // Set bootflag to run SAM-BA bootloader at restart const int EEFC_FCMD_CGPB = 0x0C; const int EEFC_KEY = 0x5A; while (EFC0->EEFC_FSR & EEFC_FSR_FRDY == 0); EFC0->EEFC_FCR = EEFC_FCR_FCMD(EEFC_FCMD_CGPB) | EEFC_FCR_FARG(1) | EEFC_FCR_FKEY(EEFC_KEY); while (EFC0->EEFC_FSR & EEFC_FSR_FRDY == 0); // From here flash memory is no more available. // Memory swap needs some time to stabilize for (uint32_t i=0; i<1000000; i++) // force compiler to not optimize this __asm__ __volatile__(""); // BANZAIIIIIII!!! const int RSTC_KEY = 0xA5; RSTC->RSTC_CR = RSTC_CR_KEY(RSTC_KEY) | RSTC_CR_PROCRST | RSTC_CR_PERRST; while (true); }
void banzai() { // Disable all interrupts __disable_irq(); // Set bootflag to run SAM-BA bootloader at restart const int EEFC_FCMD_CGPB = 0x0C; const int EEFC_KEY = 0x5A; while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0); EFC0->EEFC_FCR = EEFC_FCR_FCMD(EEFC_FCMD_CGPB) | EEFC_FCR_FARG(1) | EEFC_FCR_FKEY(EEFC_KEY); while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0); // From here flash memory is no more available. // BANZAIIIIIII!!! const int RSTC_KEY = 0xA5; RSTC->RSTC_CR = RSTC_CR_KEY(RSTC_KEY) | RSTC_CR_PROCRST | RSTC_CR_PERRST; while (true); }
/** * \brief Perform the given command and wait until its completion (or an error). * * \note Unique ID commands are not supported, use efc_read_unique_id. * * \param p_efc Pointer to an EFC instance. * \param ul_command Command to perform. * \param ul_argument Optional command argument. * * \note This function will automatically choose to use IAP function. * * \return 0 if successful, otherwise returns an error code. */ uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command, uint32_t ul_argument) { // Unique ID commands are not supported. if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) { return EFC_RC_NOT_SUPPORT; } #if (SAM3XA_SERIES || SAM3U4) // Use IAP function with 2 parameters in ROM. static uint32_t(*iap_perform_command) (uint32_t, uint32_t); uint32_t ul_efc_nb = (p_efc == EFC0) ? 0 : 1; iap_perform_command = (uint32_t(*)(uint32_t, uint32_t)) *((uint32_t *) CHIP_FLASH_IAP_ADDRESS); iap_perform_command(ul_efc_nb, EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); return (p_efc->EEFC_FSR & EEFC_ERROR_FLAGS); #elif (SAM3N_SERIES || SAM3S_SERIES || SAM4S_SERIES || SAM3U_SERIES) // Use IAP function with 2 parameter in ROM. static uint32_t(*iap_perform_command) (uint32_t, uint32_t); iap_perform_command = (uint32_t(*)(uint32_t, uint32_t)) *((uint32_t *) CHIP_FLASH_IAP_ADDRESS); #if SAM4S_SERIES uint32_t ul_efc_nb = (p_efc == EFC0) ? 0 : 1; iap_perform_command(ul_efc_nb, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); #else iap_perform_command(0, EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); #endif return (p_efc->EEFC_FSR & EEFC_ERROR_FLAGS); #else // Use RAM Function. return efc_perform_fcr(p_efc, EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); #endif }
/** * \brief Perform the given command and wait until its completion (or an error). * * \note Unique ID commands are not supported, use efc_perform_read_sequence. * * \param p_efc Pointer to an EFC instance. * \param ul_command Command to perform. * \param ul_argument Optional command argument. * * \note This function will automatically choose to use IAP function. * * \return 0 if successful, otherwise returns an error code. */ uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command, uint32_t ul_argument) { /* Unique ID commands are not supported. */ if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) { return EFC_RC_NOT_SUPPORT; } /* Use RAM Function. */ return efc_perform_fcr(p_efc, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); }
usb_request_bootloader(void) { irq_disable(); // Request boot from ROM (instead of boot from flash) while ((EFC_HW->EEFC_FSR & EEFC_FSR_FRDY) == 0) ; EFC_HW->EEFC_FCR = (EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(1) | EEFC_FCR_FKEY_PASSWD); while ((EFC_HW->EEFC_FSR & EEFC_FSR_FRDY) == 0) ; // Reboot RSTC->RSTC_CR = ((0xA5 << RSTC_CR_KEY_Pos) | RSTC_CR_PROCRST | RSTC_CR_PERRST); for (;;) ; }
/** * \brief Perform the given command and wait until its completion (or an error). * * \note Unique ID commands are not supported, use efc_perform_read_sequence. * * \param p_efc Pointer to an EFC instance. * \param ul_command Command to perform. * \param ul_argument Optional command argument. * * \note This function will automatically choose to use IAP function. * * \return 0 if successful, otherwise returns an error code. */ uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command, uint32_t ul_argument) { uint32_t result; irqflags_t flags; /* Unique ID commands are not supported. */ if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) { return EFC_RC_NOT_SUPPORT; } flags = cpu_irq_save(); /* Use RAM Function. */ result = efc_perform_fcr(p_efc, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(ul_argument) | EEFC_FCR_FCMD(ul_command)); cpu_irq_restore(flags); return result; }
uint32_t efc_perform_read_sequence(Efc *p_efc, uint32_t ul_cmd_st, uint32_t ul_cmd_sp, uint32_t *p_ul_buf, uint32_t ul_size) { volatile uint32_t ul_status; uint32_t ul_cnt; #if (SAM3U4 || SAM3XA_SERIES /*|| SAM4SD16 || SAM4SD32*/) uint32_t *p_ul_data = (uint32_t *) ((p_efc == EFC0) ? READ_BUFF_ADDR0 : READ_BUFF_ADDR1); #elif (SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3U_SERIES) uint32_t *p_ul_data = (uint32_t *) READ_BUFF_ADDR; #else return EFC_RC_NOT_SUPPORT; #endif if (p_ul_buf == NULL) { return EFC_RC_INVALID; } p_efc->EEFC_FMR |= (0x1u << 16); /* Send the Start Read command */ #if SAM4S_SERIES p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) | EEFC_FCR_FCMD(ul_cmd_st); #else p_efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0) | EEFC_FCR_FCMD(ul_cmd_st); #endif /* Wait for the FRDY bit in the Flash Programming Status Register * (EEFC_FSR) falls. */ do { ul_status = p_efc->EEFC_FSR; } while ((ul_status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY); /* The data is located in the first address of the Flash * memory mapping. */ for (ul_cnt = 0; ul_cnt < ul_size; ul_cnt++) { p_ul_buf[ul_cnt] = p_ul_data[ul_cnt]; } /* To stop the read mode */ p_efc->EEFC_FCR = #if SAM4S_SERIES EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) | EEFC_FCR_FCMD(ul_cmd_sp); #else EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0) | EEFC_FCR_FCMD(ul_cmd_sp); #endif /* Wait for the FRDY bit in the Flash Programming Status Register (EEFC_FSR) * rises. */ do { ul_status = p_efc->EEFC_FSR; } while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); p_efc->EEFC_FMR &= ~(0x1u << 16); return EFC_RC_OK; }
// ============================================================================= // 功能:系统时钟初始化,主时钟配置为300MHz,外设时钟为150M // 参数:无 // 返回:无 // ============================================================================= void SysClk_Init(void) { uint32_t read_MOR; EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(8)); EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(7)); TCM_Disable(); /* Set FWS according to SYS_BOARD_MCKR configuration */ EFC->EEFC_FMR = EEFC_FMR_FWS(5); /* Before switching MAIN OSC on external crystal : enable it and don't * disable at the same time RC OSC in case of if MAIN OSC is still using RC * OSC */ read_MOR = PMC->CKGR_MOR; /* enable external crystal - enable RC OSC */ read_MOR |= (CKGR_MOR_KEY_PASSWD |CKGR_MOR_XT32KFME); PMC->CKGR_MOR = read_MOR; /* Select XTAL 32k instead of internal slow RC 32k for slow clock */ if ( (SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST ) { SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL; while( !(SUPC->SUPC_SR & SUPC_SR_OSCSEL) ); } /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) ) { } } /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; while ( !(PMC->PMC_SR & PMC_SR_MOSCSELS) ) { } PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } /* Initialize PLLA */ PMC->CKGR_PLLAR = SYS_BOARD_PLLAR; while ( !(PMC->PMC_SR & PMC_SR_LOCKA) ) { } /* Switch to main clock */ PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } /* Switch to PLLA */ PMC->PMC_MCKR = SYS_BOARD_MCKR; while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) ) { } // SystemCoreClock = CHIP_FREQ_CPU_MAX; }