/** ****************************************************************************** * @file : mf_config.c * @brief : MCU FUNCTION CONFIG ****************************************************************************** * @attention * * Copyright (c) [2021] [Fudan Microelectronics] * THIS SOFTWARE is licensed under Mulan PSL v2. * can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "mf_config.h" /* Private function prototypes -----------------------------------------------*/ /** * @brief CMU_XTLF Initialization function * @param void * @retval None */ void MF_CMU_XTLF_Init(void) { FL_VAO_XTLF_InitTypeDef XTLF_InitStruct; XTLF_InitStruct.driveMode = FL_VAO_XTLF_DRIVE_LEVEL_1; XTLF_InitStruct.workingCurrentMode = FL_VAO_XTLF_WORK_CURRENT_450NA; FL_VAO_XTLF_Init(VAO, &XTLF_InitStruct); } /** * @brief I2C_MASTER Initialization function * @param void * @retval None */ void MF_I2C_MASTER_Init(void) { FL_GPIO_InitTypeDef GPIO_InitStruct; FL_I2C_MasterMode_InitTypeDef I2C_InitStruct; /* PA11 I2C_SCL */ GPIO_InitStruct.pin = FL_GPIO_PIN_11; GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.pull = FL_DISABLE; GPIO_InitStruct.remapPin = FL_DISABLE; GPIO_InitStruct.analogSwitch = FL_DISABLE; FL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* PA12 I2C_SDA */ GPIO_InitStruct.pin = FL_GPIO_PIN_12; GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.pull = FL_DISABLE; GPIO_InitStruct.remapPin = FL_DISABLE; GPIO_InitStruct.analogSwitch = FL_DISABLE; FL_GPIO_Init(GPIOA, &GPIO_InitStruct); I2C_InitStruct.clockSource = FL_CMU_I2C_CLK_SOURCE_APBCLK; I2C_InitStruct.baudRate = 100000; FL_I2C_MasterMode_Init(I2C, &I2C_InitStruct); } /** * @brief SWD_IO Initialization function * @param void * @retval None */ void MF_SWD_IO_Init(void) { FL_GPIO_InitTypeDef GPIO_InitStruct; /* PD7 SWD_SWCLK */ GPIO_InitStruct.pin = FL_GPIO_PIN_7; GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.pull = FL_DISABLE; GPIO_InitStruct.remapPin = FL_DISABLE; GPIO_InitStruct.analogSwitch = FL_DISABLE; FL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* PD8 SWD_SWDIO */ GPIO_InitStruct.pin = FL_GPIO_PIN_8; GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.pull = FL_DISABLE; GPIO_InitStruct.remapPin = FL_DISABLE; GPIO_InitStruct.analogSwitch = FL_DISABLE; FL_GPIO_Init(GPIOD, &GPIO_InitStruct); } /** * @brief Clock Initialization. * @retval None */ void MF_Clock_Init(void) { /* Initial CDIF */ FL_CDIF_EnableCPUToVAO(CDIF); FL_CDIF_EnableVAOToCPU(CDIF); /* Initial RTCA Adjust Value */ FL_CMU_EnableGroup1BusClock(FL_CMU_GROUP1_BUSCLK_RTCA); FL_RTCA_WriteAdjustValue(RTCA, 0); FL_CMU_DisableGroup1BusClock(FL_CMU_GROUP1_BUSCLK_RTCA); /* Initial RTCB Adjust Value */ FL_RTCB_WriteAdjustValue(RTCB, 0); /* Initial XTLF */ MF_CMU_XTLF_Init(); FL_VAO_XTLF_Enable(VAO); FL_DelayMs(1000); /* Initial Low Speed Clock */ FL_CMU_SetLSCLKClockSource(FL_CMU_LSCLK_CLK_SOURCE_RCLP); /* Initial RCHF */ FL_CMU_RCHF_WriteTrimValue(RCHF8M_TRIM); FL_CMU_RCHF_SetFrequency(FL_CMU_RCHF_FREQUENCY_8MHZ); FL_CMU_RCHF_Enable(); /* Initial System Clock */ FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_0CYCLE); /* 设置FLASH读等待为 0 个周期 */ FL_CMU_SetSystemClockSource(FL_CMU_SYSTEM_CLK_SOURCE_RCHF); /* 设置系统主时钟为 RCHF */ FL_CMU_SetAHBPrescaler(FL_CMU_AHBCLK_PSC_DIV1); FL_CMU_SetAPBPrescaler(FL_CMU_APBCLK_PSC_DIV1); /* Initial CDIF Clock Prescaler */ FL_CDIF_SetPrescaler(CDIF, FL_CDIF_PSC_DIV1); SystemCoreClockUpdate(); } void MF_Config_Init(void) { /* 配置普通GPIO工作模式 */ FL_GPIO_InitTypeDef GPIO_InitStruct; FL_BSTIM32_InitTypeDef TimerBase_InitStruct; FL_NVIC_ConfigTypeDef InterruptConfigStruct; GPIO_InitStruct.pin = FL_GPIO_PIN_0; GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.pull = FL_ENABLE; GPIO_InitStruct.remapPin = FL_DISABLE; GPIO_InitStruct.analogSwitch = FL_DISABLE; /* 初始化LED状态灯 */ FL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* 断电、报警功能GPIO */ GPIO_InitStruct.pin = FL_GPIO_PIN_10|FL_GPIO_PIN_11; FL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* 调试模式输入GPIO */ GPIO_InitStruct.mode = FL_GPIO_MODE_INPUT; GPIO_InitStruct.pin = FL_GPIO_PIN_8|FL_GPIO_PIN_9|FL_GPIO_PIN_10|FL_GPIO_PIN_11; FL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* 使用BSTIM32作为时基产生20ms一次中断 */ TimerBase_InitStruct.prescaler = 127; TimerBase_InitStruct.autoReload = 9999; TimerBase_InitStruct.autoReloadState = FL_ENABLE; TimerBase_InitStruct.clockSource = FL_CMU_BSTIM32_CLK_SOURCE_APBCLK; FL_BSTIM32_Init(BSTIM32, &TimerBase_InitStruct); FL_BSTIM32_ClearFlag_Update(BSTIM32); FL_BSTIM32_EnableIT_Update(BSTIM32); InterruptConfigStruct.preemptPriority = 0x03; FL_NVIC_Init(&InterruptConfigStruct, BSTIM_IRQn); FL_BSTIM32_Enable(BSTIM32); } /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { } #define PLL_TIMEOUT 0xFFFFFFFFU uint32_t SYSCLKSELErrorState = 0; void FDET_IRQHandler(void) { //时钟选择中断处理 if((FL_CMU_IsEnabledIT_SYSCLKSELError() == 0x01UL) && (FL_CMU_IsActiveFlag_SYSCLKSELError() == 0x01UL)) { FL_CMU_ClearFlag_SYSCLKSELError(); //清除标志 SYSCLKSELErrorState = 1; } if((FL_CMU_IsEnabledIT_XTHFFail() == 0x01UL) && (FL_CMU_IsActiveFlag_XTHFFail() == 0x01UL)) { FL_CMU_DisableIT_XTHFFail(); FL_CMU_ClearFlag_XTHFFail(); //清除标志 /*应用处理逻辑*/ } } /** * @brief * @param Source 锁相环输入参考时钟选择 This parameter can be one of the following values: * @arg @ref FL_CMU_PLL_CLK_SOURCE_RCHF * @arg @ref FL_CMU_PLL_CLK_SOURCE_XTHF * @param PLL_REFPSC 参考时钟分频,目标分频值1M This parameter can be one of the following values: * @arg @ref FL_CMU_PLL_PSC_DIV1 * @arg @ref FL_CMU_PLL_PSC_DIV2 * @arg @ref FL_CMU_PLL_PSC_DIV4 * @arg @ref FL_CMU_PLL_PSC_DIV8 * @arg @ref FL_CMU_PLL_PSC_DIV12 * @arg @ref FL_CMU_PLL_PSC_DIV16 * @arg @ref FL_CMU_PLL_PSC_DIV24 * @arg @ref FL_CMU_PLL_PSC_DIV32 * @param PLL_DB PLL倍频比,输出时钟频率为1M*(clock+1) This parameter can be Between parameters of the following values: * @arg @ref * @param PLL_OSEL PLL输出选择 This parameter can be one of the following values: * @arg @ref FL_CMU_PLL_OUTPUT_X1 * @arg @ref FL_CMU_PLL_OUTPUT_X2 * @retval None */ void CMU_PLL_ConfigDomain_SYSTEM(uint32_t Source, uint32_t PLL_REFPSC, uint32_t PLL_DB, uint32_t PLL_OSEL) { MODIFY_REG(CMU->PLLCR, CMU_PLLCR_DB_Msk | CMU_PLLCR_REFPRSC_Msk | CMU_PLLCR_OSEL_Msk | CMU_PLLCR_INSEL_Msk, (PLL_DB << CMU_PLLCR_DB_Pos) | PLL_REFPSC | PLL_OSEL | Source); } void RCHFInit(uint32_t clock) { switch(clock) { case FL_CMU_RCHF_FREQUENCY_8MHZ: FL_CMU_RCHF_WriteTrimValue(RCHF8M_TRIM); break; case FL_CMU_RCHF_FREQUENCY_16MHZ: FL_CMU_RCHF_WriteTrimValue(RCHF16M_TRIM); break; case FL_CMU_RCHF_FREQUENCY_24MHZ: FL_CMU_RCHF_WriteTrimValue(RCHF24M_TRIM); break; case FL_CMU_RCHF_FREQUENCY_32MHZ: FL_CMU_RCHF_WriteTrimValue(RCHF32M_TRIM); break; default: FL_CMU_RCHF_WriteTrimValue(RCHF8M_TRIM); break; } FL_CMU_RCHF_SetFrequency(clock); } /** * @brief 选择内部RCHF作为锁相环的参考时钟 * * @note 锁相环的参考时钟需要预分频至1M,再进行PLL倍频 * @param rchf RCHF参考时钟选择 This parameter can be one of the following values: * @arg @ref FL_CMU_RCHF_FREQUENCY_8MHZ * @arg @ref FL_CMU_RCHF_FREQUENCY_16MHZ * @arg @ref FL_CMU_RCHF_FREQUENCY_24MHZ * @arg @ref FL_CMU_RCHF_FREQUENCY_32MHZ * @param clock PLL倍频输出频率 * @note 输出时钟频率为1M*(clock+1),最高输出频率可达64M * @retval none */ void SelRCHFToPLL(uint32_t rchf, uint32_t clock) { FL_NVIC_ConfigTypeDef InterruptConfigStruct; uint32_t counter = 0; uint32_t readystatus = 0; uint32_t div = FL_CMU_PLL_PSC_DIV8; if(clock > 63) { return; } /*RCHF初始化配置*/ RCHFInit(rchf); /*清除时钟选择错误标志*/ FL_CMU_ClearFlag_SYSCLKSELError(); /*使能时钟选择错误中断*/ FL_CMU_EnableIT_SYSCLKSELError(); InterruptConfigStruct.preemptPriority = 0x00; FL_NVIC_Init(&InterruptConfigStruct, FDET_IRQn); switch(rchf) { case FL_CMU_RCHF_FREQUENCY_16MHZ: div = FL_CMU_PLL_PSC_DIV16; break; case FL_CMU_RCHF_FREQUENCY_24MHZ: div = FL_CMU_PLL_PSC_DIV24; break; case FL_CMU_RCHF_FREQUENCY_32MHZ: div = FL_CMU_PLL_PSC_DIV32; break; default: break; } /*FLASH读等待周期配置*/ FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_2CYCLE); /*CDIF接口分频设置,访问的最高频率不超过8M*/ FL_CDIF_SetPrescaler(CDIF, FL_CDIF_PSC_DIV8); /*PLL配置*/ CMU_PLL_ConfigDomain_SYSTEM(FL_CMU_PLL_CLK_SOURCE_RCHF, div, clock, FL_CMU_PLL_OUTPUT_X1); /*使能PLL*/ FL_CMU_PLL_Enable(); /*等待PLL建立稳定*/ do { readystatus = FL_CMU_IsActiveFlag_PLLReady(); counter++; } while((readystatus != 0x1U) && (counter != PLL_TIMEOUT)); /*系统时钟源选择PLL*/ FL_CMU_SetSystemClockSource(FL_CMU_SYSTEM_CLK_SOURCE_PLL); /*FLASH读等待周期配置*/ if(clock <= 23) { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_0CYCLE); FL_CDIF_SetPrescaler(CDIF, FL_CDIF_PSC_DIV4); } else if((clock > 23) && (clock <= 47)) { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_1CYCLE); } else { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_2CYCLE); } /*AHB时钟分频配置*/ FL_CMU_SetAHBPrescaler(FL_CMU_AHBCLK_PSC_DIV1); /*APB时钟分频配置*/ FL_CMU_SetAPBPrescaler(FL_CMU_APBCLK_PSC_DIV1); /*系统内核时钟更新*/ SystemCoreClockUpdate(); } void XTHFInit(void) { FL_GPIO_InitTypeDef GPIO_InitStruct = {0}; FL_NVIC_ConfigTypeDef InterruptConfigStruct; /*PC2.3配置成模拟功能,外接XTHF*/ GPIO_InitStruct.pin = FL_GPIO_PIN_2 | FL_GPIO_PIN_3; GPIO_InitStruct.mode = FL_GPIO_MODE_ANALOG; GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.pull = FL_DISABLE; GPIO_InitStruct.remapPin = FL_DISABLE; (void)FL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*XTHF振荡强度配置*/ FL_CMU_XTHF_WriteDriverStrength(0x0A); /*使能XTHF*/ FL_CMU_XTHF_Enable(); /*硬延时等待XTHF建立稳定*/ FL_DelayMs(2); FL_CMU_ClearFlag_XTHFFail(); /*开启XTHF停振检测中断*/ FL_CMU_EnableIT_XTHFFail(); InterruptConfigStruct.preemptPriority = 0x00; FL_NVIC_Init(&InterruptConfigStruct, FDET_IRQn); /*系统内核时钟更新*/ SystemCoreClockUpdate(); } /** * @brief 选择外部XTHF作为锁相环的参考时钟 * * @note 锁相环的参考时钟需要预分频至1M,再进行PLL倍频 * @param div 对XTHF参考时钟的分频,目标分频到1M * * @param clock PLL倍频输出频率 * @note 输出时钟频率为1M*(clock+1),最高输出频率可达64M * @retval none */ void SelXTHFToPLL(uint32_t div, uint32_t clock) { FL_NVIC_ConfigTypeDef InterruptConfigStruct; uint32_t counter = 0; uint32_t readystatus = 0; if(clock > 63) { return; } /*外部高频晶体使能配置*/ XTHFInit(); FL_CMU_ClearFlag_SYSCLKSELError(); //清除时钟选择错误标志 FL_CMU_EnableIT_SYSCLKSELError(); //使能时钟选择错误中断 InterruptConfigStruct.preemptPriority = 0x00; FL_NVIC_Init(&InterruptConfigStruct, FDET_IRQn); //系统时钟选择错误中断 /*FLASH读等待周期配置*/ FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_2CYCLE); /*CDIF接口分频设置,访问的最高频率不超过8M*/ FL_CDIF_SetPrescaler(CDIF, FL_CDIF_PSC_DIV8); /*PLL配置*/ CMU_PLL_ConfigDomain_SYSTEM(FL_CMU_PLL_CLK_SOURCE_XTHF, div, clock, FL_CMU_PLL_OUTPUT_X1); /*使能PLL*/ FL_CMU_PLL_Enable(); /*等待PLL建立稳定*/ do { readystatus = FL_CMU_IsActiveFlag_PLLReady(); counter++; } while((readystatus != 0x1U) && (counter != PLL_TIMEOUT)); /*系统时钟源选择PLL*/ FL_CMU_SetSystemClockSource(FL_CMU_SYSTEM_CLK_SOURCE_PLL); if(clock <= 23) { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_0CYCLE); FL_CDIF_SetPrescaler(CDIF, FL_CDIF_PSC_DIV4); } else if((clock > 23) && (clock <= 47)) { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_1CYCLE); } else { FL_FLASH_SetReadWait(FLASH, FL_FLASH_READ_WAIT_2CYCLE); } /*AHB时钟分频配置*/ FL_CMU_SetAHBPrescaler(FL_CMU_AHBCLK_PSC_DIV1); /*APB时钟分频配置*/ FL_CMU_SetAPBPrescaler(FL_CMU_APBCLK_PSC_DIV1); /*系统内核时钟更新*/ SystemCoreClockUpdate(); } #endif /* USE_FULL_ASSERT */ /*************************(C) COPYRIGHT Fudan Microelectronics **** END OF FILE*************************/