416 lines
13 KiB
C
416 lines
13 KiB
C
/**
|
|
******************************************************************************
|
|
* @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;
|
|
}
|