dc31-addon-addon-badge-firm.../badge_firmware/driver/CMSIS/HK32F030M/Source/system_hk32f030m.c

416 lines
13 KiB
C
Raw Permalink Normal View History

/**
******************************************************************************
* @file system_hk32f030m.c
* @author laura.C
* @version V1.0
* @brief API file of system clk config
* @changelist
******************************************************************************
*/
/*
This file configures the system clock as follows:
*=============================================================================
* Supported hk32f030m device
*-----------------------------------------------------------------------------
* System Clock source | HSI32M
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 32000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 32000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB1 Prescaler | 1
*-----------------------------------------------------------------------------
*=============================================================================
******************************************************************************
*/
#include "hk32f030m.h"
/* system clock source */
#define SYSCLK_SRC_HSI8M 0x2
#define SYSCLK_SRC_HSI16M 0x3
#define SYSCLK_SRC_HSI32M 0x4
#define SYSCLK_SRC_LSI 0x5
#define SYSCLK_SCR_EXTCLK_IO 0x6
#define SYSCLK_SOURCE SYSCLK_SRC_HSI32M
/* vector table location */
// #define VECT_TAB_SRAM
#ifndef VECT_TAB_OFFSET
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
#endif
uint32_t System_SysClk; // SYSCLK which feeds AHB, ADC, USART, etc. System clock.
uint32_t System_HClk; // HCLK which feeds core, AHB bus, memory. CPU clock.
#if(SYSCLK_SOURCE==SYSCLK_SRC_HSI8M)
#define SYSCLK_FREQ_HSI 32000000
#define HCLK_FREQ 8000000
#define SET_FLASH_LATENCY FLASH_Latency_0
#define SET_HPRE_DIV RCC_CFGR_HPRE_DIV4
static void SetSysClockToHSI(void);
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI16M)
#define SYSCLK_FREQ_HSI 32000000
#define HCLK_FREQ 16000000
#define SET_FLASH_LATENCY FLASH_Latency_0
#define SET_HPRE_DIV RCC_CFGR_HPRE_DIV2
static void SetSysClockToHSI(void);
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI32M)
#define SYSCLK_FREQ_HSI 32000000
#define HCLK_FREQ 32000000
#define SET_FLASH_LATENCY FLASH_Latency_1
#define SET_HPRE_DIV RCC_CFGR_HPRE_DIV1
static void SetSysClockToHSI(void);
#elif(SYSCLK_SOURCE == SYSCLK_SRC_LSI)
#define SYSCLK_FREQ_LSI LSI_VALUE
uint32_t SystemCoreClock = SYSCLK_FREQ_LSI;
static void SetSysClockToLSI(void);
#elif(SYSCLK_SOURCE == SYSCLK_SCR_EXTCLK_IO)
#define SYSCLK_FREQ_EXTCLK EXTCLK_VALUE
uint32_t SystemCoreClock = SYSCLK_FREQ_EXTCLK;
static void SetSysClockToEXTCLK(void);
#endif
static void SetSysClock(void);
/**
* @brief Setup the microcontroller system.
* Initialize the default HSI clock source, vector table location and the PLL configuration is reset.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW[1:0], HPRE[3:0], PPRE[2:0] and MCOSEL[2:0] bits */
RCC->CFGR &= (uint32_t)0xF8FFB81C;
/* Reset USARTSW[1:0], I2CSW bits */
RCC->CFGR3 &= (uint32_t)0xFFFFFFEC;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
SetSysClock();
#ifdef VECT_TAB_SRAM
SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE; /* Vector Table Relocation in Internal SRAM. */
#else
// FLASH->INT_VEC_OFFSET = VECT_TAB_OFFSET ; /* Vector Table Relocation in Internal FLASH. */
#endif
}
/**
* @brief Configures the System clock frequency, HCLK, PCLK prescalers.
* @param None
* @retval None
*/
static void SetSysClock(void)
{
/*reload the hsi trimming value to the bit3~bit13 of RCC_CR register */
uint32_t u32HSIFLASH = 0;
uint32_t u32RCC_CR = 0;
uint32_t u32HSITemp = 0;
uint16_t u16HSITempH = 0;
uint16_t u16HSITempL = 0;
u32HSIFLASH = *(uint32_t *) 0x1FFFF820;
u16HSITempH = (uint16_t)(u32HSIFLASH>>16);
u16HSITempL = (uint16_t)(u32HSIFLASH);
if(!(u16HSITempH & u16HSITempL))
{
u32HSITemp = RCC->CR;
u32HSITemp &= (uint32_t)((uint32_t)~(RCC_CR_HSITRIM|RCC_CR_HSICAL));
u32RCC_CR = (uint32_t)(((u16HSITempL & 0x001F) <<3) | (((u16HSITempL>>5) & 0x003F)<<8));
RCC->CR |= u32RCC_CR;
}
/*end*/
#if(SYSCLK_SOURCE==SYSCLK_SRC_HSI8M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI16M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI32M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_LSI)
SetSysClockToLSI();
#elif(SYSCLK_SOURCE == SYSCLK_SCR_EXTCLK_IO)
SetSysClockToEXTCLK();
#endif
/* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */
}
#ifdef SYSCLK_FREQ_HSI
static void SetSysClockToHSI(void)
{
__IO uint32_t StartUpCounter = 0, HSIStatus = 0;
__IO uint32_t ACRreg = 0;
__IO uint32_t RCCHCLKReg = 0;
__IO uint32_t RCCPCLKReg = 0;
/* Enable HSI */
RCC->CR |= RCC_CR_HSION;
/* Set flash programming clock to 2MHz using HSI32M directly
* Datasheet and RM was updated in 2023 which derated flash programming from 4MHz
* 0x07 = 4MHz, 0x08 = 2MHz. change as you see fit */
RCC->CFGR4 &= ~(RCC_RCC_CFGR4_FLITFCLK_PRE | RCC_RCC_CFGR4_FLITFCLK_SE);
RCC->CFGR4 |= (((uint32_t)0x08) << RCC_RCC_CFGR4_FLITFCLK_PRE_Pos);
/* Wait until HSI is ready; if timeout is reached, then exit */
do {
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
StartUpCounter++;
} while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSIRDY) != RESET) {
HSIStatus = (uint32_t)0x01;
} else {
HSIStatus = (uint32_t)0x00;
}
if (HSIStatus == (uint32_t)0x01) {
/* Flash wait state */
ACRreg = FLASH->ACR;
ACRreg &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR = (uint32_t)(SET_FLASH_LATENCY | ACRreg);
/* HCLK = configured divided value from SYSCLK (which will later be set to HSI32M) */
RCCHCLKReg = RCC->CFGR;
RCCHCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_HPRE_Msk);
RCC->CFGR = (uint32_t)(SET_HPRE_DIV | RCCHCLKReg);
/* PCLK = HCLK */
RCCPCLKReg = RCC->CFGR;
RCCPCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_PPRE_Msk);
RCC->CFGR = (uint32_t)(RCC_CFGR_PPRE_DIV1|RCCPCLKReg);
/* Select HSI32M as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSI;
/* Wait until HSI is active as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);
} else {
/* If clock fails to start, the application will have wrong clock configuration.
* User can add some code here to deal with this error
*/
}
}
#elif (SYSCLK_SOURCE == SYSCLK_SRC_LSI)
static void SetSysClockToLSI(void)
{
__IO uint32_t StartUpCounter = 0, LSIStatus = 0;
/* Enable LSI */
RCC->CSR |= RCC_CSR_LSION;
/* Wait till LSI is ready and if Time out is reached exit */
do{
LSIStatus = RCC->CSR & RCC_CSR_LSIRDY;
StartUpCounter++;
} while((LSIStatus == 0) && (StartUpCounter != STARTUP_TIMEOUT));
if ((RCC->CSR & RCC_CSR_LSIRDY) != RESET)
{
LSIStatus = (uint32_t)0x01;
}
else
{
LSIStatus = (uint32_t)0x00;
}
if (LSIStatus == (uint32_t)0x01)
{
/* Flash wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_Latency_0;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
/* Select HSI as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_LSI;
/* Wait till LSI is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_LSI)
{
}
}
else
{ /* If fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */
}
};
#elif (SYSCLK_SOURCE == SYSCLK_SCR_EXTCLK_IO)
static void SetSysClockToEXTCLK(void)
{
__IO uint32_t StartUpCounter = 0, EXTCLKStatus = 0;
__IO uint32_t ACRreg = 0;
__IO uint32_t RCCHCLKReg = 0;
__IO uint32_t RCCPCLKReg = 0;
//enable EXTIO PA1/PD7/PB5/PC5
/* Configure PA1 as CLOCK input */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// GPIO_Init(GPIOD, &GPIO_InitStructure);
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// GPIO_Init(GPIOB, &GPIO_InitStructure);
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// GPIO_Init(GPIOC, &GPIO_InitStructure);
/*CLOCK select */
RCC->CFGR4 &= (uint32_t)~(RCC_RCC_CFGR4_EXTCLK_SEL);
RCC->CFGR4 |= (uint32_t)RCC_CFGR4_EXTCLK_SEL_PA1;
// RCC->CFGR4 |= (uint32_t)RCC_CFGR4_EXTCLK_SEL_PB5;
// RCC->CFGR4 |= (uint32_t)RCC_CFGR4_EXTCLK_SEL_PC5;
// RCC->CFGR4 |= (uint32_t)RCC_CFGR4_EXTCLK_SEL_PD7;
/* Enable EXTCLK */
RCC->CR |= RCC_CR_EXTCLKON;
/* Wait till LSI is ready and if Time out is reached exit */
do{
EXTCLKStatus = RCC->CR & RCC_CR_EXTCLKRDY;
StartUpCounter++;
} while((EXTCLKStatus == 0) && (StartUpCounter != STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_EXTCLKRDY) != RESET)
{
EXTCLKStatus = (uint32_t)0x01;
}
else
{
EXTCLKStatus = (uint32_t)0x00;
}
if (EXTCLKStatus == (uint32_t)0x01)
{
/* Flash wait state */
ACRreg= FLASH->ACR;
ACRreg &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
if (SystemCoreClock <= 16000000)
FLASH->ACR = (uint32_t)(FLASH_Latency_0|ACRreg);
else if(SystemCoreClock <= 32000000)
FLASH->ACR = (uint32_t)(FLASH_Latency_1|ACRreg);
else
FLASH->ACR = (uint32_t)(FLASH_Latency_2|ACRreg);
RCCHCLKReg = RCC->CFGR;
RCCHCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_HPRE_Msk);
/* HCLK = SYSCLK */
RCC->CFGR = (uint32_t)(RCC_CFGR_HPRE_DIV1|RCCHCLKReg);
RCCPCLKReg = RCC->CFGR;
RCCPCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_PPRE_Msk);
/* PCLK = HCLK */
RCC->CFGR = (uint32_t)(RCC_CFGR_PPRE_DIV1|RCCPCLKReg);
/* Select EXTCLK as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_EXTCLK;
/* Wait till EXTCLK is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_EXTCLK)
{
}
}
else
{ /* If fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */
}
};
#endif
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, presc = 0;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp) {
case RCC_CFGR_SWS_EXTCLK: // EXTCLK used as system clock
SystemCoreClock = EXTCLK_VALUE;
break;
case RCC_CFGR_SWS_LSI: // LSI used as system clock
SystemCoreClock = LSI_VALUE;
break;
case RCC_CFGR_SWS_HSI: // HSI used as system clock
default:
SystemCoreClock = HCLK_FREQ;
break;
}
/* Compute HCLK clock frequency ----------------*/
/* Get HCLK prescaler */
tmp = RCC->CFGR & RCC_CFGR_HPRE;
tmp = tmp >> 4;
presc = AHBPrescTable[tmp];
/* HCLK clock frequency */
SystemCoreClock = SystemCoreClock/presc;
}