current_v/MF-config/Src/mf_config.c
2025-12-31 08:21:43 +08:00

501 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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*************************/