#include "sys.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32F7开发板 //系统时钟初始化 //正点原子@ALIENTEK //技术论坛:www.openedv.com //创建日期:2015/6/10 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2014-2024 //All rights reserved //******************************************************************************** //修改说明 //无 ////////////////////////////////////////////////////////////////////////////////// //使能CPU的L1-Cache void Cache_Enable(void) { SCB_EnableICache();//使能I-Cache SCB_EnableDCache();//使能D-Cache SCB->CACR|=1<<2; //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题 } //时钟设置函数 //Fvco=Fs*(plln/pllm); //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp)); //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq)); //Fvco:VCO频率 //Fsys:系统时钟频率 //Fusb:USB,SDIO,RNG等的时钟频率 //Fs:PLL输入时钟频率,可以是HSI,HSE等. //plln:主PLL倍频系数(PLL倍频),取值范围:64~432. //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63. //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!) //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15. //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9. //得到:Fvco=25*(432/25)=432Mhz // Fsys=432/2=216Mhz // Fusb=432/9=48Mhz //返回值:0,成功;1,失败 void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq) { HAL_StatusTypeDef ret = HAL_OK; RCC_OscInitTypeDef RCC_OscInitStructure; RCC_ClkInitTypeDef RCC_ClkInitStructure; __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别,以便在器件未以最大频率工作 RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE; //时钟源为HSE RCC_OscInitStructure.HSEState=RCC_HSE_ON; //打开HSE RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON; //打开PLL RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE; //PLL时钟源选择HSE RCC_OscInitStructure.PLL.PLLM=pllm; //主PLL和音频PLL分频系数(PLL之前的分频) RCC_OscInitStructure.PLL.PLLN=plln; //主PLL倍频系数(PLL倍频) RCC_OscInitStructure.PLL.PLLP=pllp; //系统时钟的主PLL分频系数(PLL之后的分频) RCC_OscInitStructure.PLL.PLLQ=pllq; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频) ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化 if(ret!=HAL_OK) while(1); ret=HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能 if(ret!=HAL_OK) while(1); //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2 RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;//设置系统时钟时钟源为PLL RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1;//AHB分频系数为1 RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV4;//APB1分频系数为4 RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV2;//APB2分频系数为2 ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_7);//同时设置FLASH延时周期为7WS,也就是8个CPU周期。 if(ret!=HAL_OK) while(1); } #ifdef USE_FULL_ASSERT //当编译提示出错的时候此函数用来报告错误的文件和所在行 //file:指向源文件 //line:指向在文件中的行数 void assert_failed(uint8_t* file, uint32_t line) { while (1) { } } #endif //判断I_Cache是否打开 //返回值:0 关闭,1 打开 u8 Get_ICahceSta(void) { u8 sta; sta=((SCB->CCR)>>17)&0X01; return sta; } //判断I_Dache是否打开 //返回值:0 关闭,1 打开 u8 Get_DCahceSta(void) { u8 sta; sta=((SCB->CCR)>>16)&0X01; return sta; } //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI void WFI_SET(void) { asm("WFI"); } //关闭所有中断(但是不包括fault和NMI中断) void INTX_DISABLE(void) { asm("CPSID I"); asm("BX LR"); } //开启所有中断 void INTX_ENABLE(void) { asm("CPSIE I"); asm("BX LR"); } //设置栈顶地址 //addr:栈顶地址 void MSR_MSP(u32 addr) { asm("MSR MSP, r0"); //set Main Stack value asm("BX r14"); }