#include "stm32f4xx.h" #include #include #include #include #include void reset_AHB1() { RCC->AHB1RSTR = -1; RCC->AHB1RSTR = 0; } void reset_AHB2() { RCC->AHB2RSTR = -1; RCC->AHB2RSTR = 0; } void reset_APB1() { RCC->APB1RSTR = -1; RCC->APB1RSTR = 0; } void reset_APB2() { RCC->APB2RSTR = -1; RCC->APB2RSTR = 0; } uint32_t getCpuFreq() { extern uint32_t OSC0; extern uint32_t INTOSC; uint32_t cpufreq = OSC0; uint32_t PLLN,PLLM,PLLP; if((RCC->CFGR & 0xC) == 8) //PLL used as sys clk { uint32_t pllinput=INTOSC; if((RCC->PLLCFGR & (1<<22)) == (1<<22)) { pllinput=OSC0; } PLLN = (RCC->PLLCFGR>>6) & 0x1FF; PLLM = RCC->PLLCFGR & 0x3F; PLLP = 1<<(((RCC->PLLCFGR>>16) & 3 )+1); cpufreq = (pllinput * PLLN )/(PLLM*PLLP); } else if((RCC->CFGR & 0xC) == 0) //HSI used as sys clk { cpufreq=INTOSC; } if((RCC->CFGR & (1<<7))==1<<7) { return cpufreq>>((RCC->CFGR & (7<<4))>>4); } return cpufreq; } /* | 2.7->3.6V ------------------------- 0WS | 062) && ((*PLLN)<433) && ((Fplli * (*PLLN)) < 433000000)) { f_errornw = abs((int32_t)((int32_t)((Fplli*(*PLLN))/((*PLLP)*AHBPR))-freq)); if( ( (f_error)>(f_errornw) ) || ( (*AHBPRindx==0)&&(*PLLP==2)&&(*PLLN==63) ) ) { f_error=f_errornw; PLLN_r = *PLLN; PLLP_r = *PLLP; AHBPR_r=*AHBPRindx; if(f_error==0) { *PLLN = PLLN_r; *PLLP = PLLP_r; *AHBPRindx = AHBPR_r; return 1; } } } } } *PLLN = PLLN_r; *PLLP = PLLP_r; *AHBPRindx = AHBPR_r; return 1; } int setPll(uint32_t freq) { extern uint32_t OSC0; extern uint32_t INTOSC; uint32_t srcfreq = INTOSC; uint8_t AHBPRindx; uint32_t AHBPRtbl[9]={1,2,4,8,16,64,128,256,512}; uint32_t PLLN=0,PLLM=0,PLLP=0,AHBPR=0; uint32_t Fplli=0; if((RCC->PLLCFGR & (1<<22))==(1<<22)) { srcfreq = OSC0; } PLLM = srcfreq / 1500000; // [3] Fplli = srcfreq / PLLM; optimizePLLcfg(freq,srcfreq,PLLM,&PLLP,&PLLN,&AHBPRindx); srcfreq = (Fplli*PLLN)/(PLLP*AHBPRtbl[AHBPRindx]); //Put real clk freq in srcfreq for return value //now switch to HSIs if((RCC->CR & 1)==0)RCC->CR |= 1; //turn ON HSI while((RCC->CR & 2)!=2); //wait for HSI Ready RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= RCC_CFGR_SW_HSI; //set HSI as main clk while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_HSI); RCC->CR &= ~(1<<24); //Turn OFF PLL RCC->PLLCFGR &= ~0x37FFF; //clear PLLP PLLM PLLN RCC->PLLCFGR |= PLLM + (PLLN<<6) + (((PLLP>>1) -1)<<16); RCC->CR |= RCC_CR_PLLON; //Turn ON PLL while((RCC->CR & (1<<25))!=(1<<25)); //wait for PLL Ready if(AHBPRindx!=0)AHBPRindx|=0x8; RCC->CFGR &= ~(0xF<<4); RCC->CFGR |= (uint32_t)(AHBPRindx<<4); AHBPR=0; while((srcfreq>>AHBPR)>42000000)AHBPR++; //[5] //Thune APB1 prescaler to keep APB1 CLK below 42MHz if(AHBPR!=0) { AHBPR-=1; AHBPR|=0x4; } RCC->CFGR &= ~(0x7<<10); RCC->CFGR |= (uint32_t)(AHBPR<<10); AHBPR=0; while((srcfreq>>AHBPR)>84000000)AHBPR++; //[5] //Thune APB2 prescaler to keep APB2 CLK below 42MHz if(AHBPR!=0) { AHBPR-=1; AHBPR|=0x4; } RCC->CFGR &= ~(0x7<<13); RCC->CFGR |= (uint32_t)(AHBPR<<13); FLASH->ACR |= FLASH_ACR_LATENCY_7WS; RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));//Switch to PLL as main clk source RCC->CFGR |= RCC_CFGR_SW_PLL; /* Wait till the main PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); if(srcfreq>150000000) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_5WS; } if((srcfreq<150000000) && (srcfreq>=120000000)) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_4WS; } if((srcfreq<120000000) && (srcfreq>=90000000)) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_3WS; } if((srcfreq<90000000) && (srcfreq>=60000000)) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_2WS; } if((srcfreq<60000000) && (srcfreq>=30000000)) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_1WS; } if(srcfreq<30000000) { FLASH->ACR &= (~7)|FLASH_ACR_LATENCY_0WS; } return srcfreq; } int setCpuFreq(uint32_t freq) { extern uint32_t OSC0; extern uint32_t INTOSC; uint8_t i=0; uint32_t curentFeq = getCpuFreq(); if(curentFeq==freq)return curentFeq; if((freq>2000000) && (freq<=250000000)) //be carefull with 250MHz!!! { if((RCC->CFGR & 0xC) == 8) //PLL used as sys clk { return setPll(freq); } else if((RCC->CFGR & 0xC) == 0) //HSI used as sys clk { if((INTOSC%freq)==0) //now check if we can directly divide HSI { if(freq==INTOSC) { RCC->CFGR &= ~(0xF<<4); return freq; } for(i=1;i<8;i++) { if((freq<CFGR &= ~(0xF<<4); RCC->CFGR |= ((0x8|i)<<4); return freq; } } } else return setPll(freq); } else //HSE used as sys clk { if((OSC0%freq)==0) //now check if we can directly divide HSI { if(freq==OSC0) { RCC->CFGR &= ~(0xF<<4); return freq; } for(i=1;i<8;i++) { if((freq<CFGR &= ~(0xF<<4); RCC->CFGR |= ((0x8|i)<<4); return freq; } } } else return setPll(freq); } } return 0; } #include extern int main(); inline void enable_FPU() { SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ __asm__("dsb"); __asm__("isb"); } void cpu_init() { extern uint32_t currentCpuFreq; currentCpuFreq = 80000000; enable_FPU(); RCC->CR |= (uint32_t)0x00000001; FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; reset_AHB1(); reset_AHB2(); reset_APB1(); reset_APB2(); RCC->CR |= (uint32_t)0x00000001; FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; RCC->CFGR = 0x00000000; RCC->CIR = 0x00000000; SCB->VTOR = FLASH_BASE; RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_PMODE; bsp_init(); printf("Configure PLL to reach %uHz\n\r",(unsigned int)currentCpuFreq); currentCpuFreq=setCpuFreq(currentCpuFreq); bsp_uart_init(); RCC_ClocksTypeDef RCC_ClocksStatus; RCC_GetClocksFreq(&RCC_ClocksStatus); printf("PLL Configured got:\n\r SYS=%uHz\n\r CPU=%uHz\n\r APB1=%uHz\n\r APB2=%uHz\n\r",(unsigned int)RCC_ClocksStatus.SYSCLK_Frequency,(unsigned int)RCC_ClocksStatus.HCLK_Frequency,(unsigned int)RCC_ClocksStatus.PCLK1_Frequency,(unsigned int)RCC_ClocksStatus.PCLK2_Frequency); printf("Enter Main\n\r"); int res=main(); printf("\n\rprogram exited with code "); printf("%u",res); printf("\n\r"); while(1) { for(volatile int i=0;i<1024*64;i++); gpioset(PD14); for(volatile int i=0;i<1024*64;i++); gpioclr(PD14); } }