몇일이 지났는데 아직도 main에 초입을 보고 있다. 분발~~
이번에 볼 소스는 RCC_GetClocksFreq 다 .
이 함수는 rcc_clocks 라는 스트럭쳐를 상수값으로 전달해서
내부 선언된 클럭을 읽어오는 함수다.
---------------------------------------------------------------------------------
int main(void)
{
uint8_t ch;
/* System Clocks Configuration */
RCC_Configuration(); //시스템 클럭을 살리고 주변 프리페럴럴 를 살린다.
RCC_GetClocksFreq(&rcc_clocks); //현재 설정된 클럭을 rcc_clocks 스트럭쳐로 가져 온다.
---------------------------------------------------------------------------------
스트력처를 보면 클러벌 변수로 선언이 되어 있다.
---------------------------------------------------------------------------------
RCC_ClocksTypeDef rcc_clocks;
---------------------------------------------------------------------------------
스트럭처 내용을 보면 typedef 로 선언되어 있고 stm32f10x_rcc.h 에 있다.
특별한기능은 없고 값을 기억하고 있는용으로 사용된다.
---------------------------------------------------------------------------------
typedef struct
{
uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz */
uint32_t HCLK_Frequency; /*!< returns HCLK clock frequency expressed in Hz */
uint32_t PCLK1_Frequency; /*!< returns PCLK1 clock frequency expressed in Hz */
uint32_t PCLK2_Frequency; /*!< returns PCLK2 clock frequency expressed in Hz */
uint32_t ADCCLK_Frequency; /*!< returns ADCCLK clock frequency expressed in Hz */
}RCC_ClocksTypeDef;
---------------------------------------------------------------------------------
RCC_GetClocksFreq 소스는 stm32f10x_rcc.c 에 있다. 내용을 보면 아래와 같다.
---------------------------------------------------------------------------------
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;
#ifdef STM32F10X_CL //105,107은 레지스터가 추가되어 있어 계산식이 복잡하다.
uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & CFGR_SWS_Mask;
/* SWS 정보 : system 클럭의 소스는 누구?
00: HSI oscillator used as system clock
01: HSE oscillator used as system clock
10: PLL used as system clock
11: not applicable
*/
switch (tmp)
{
case 0x00: /* HSI used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSI_Value; //define 된 값을 가져 온다.
break;
case 0x04: /* HSE used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSE_Value; //define 된 값을 가져 온다.
break;
case 0x08: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & CFGR_PLLMull_Mask; //pll 입력 주파수 * 몇배할값
pllsource = RCC->CFGR & CFGR_PLLSRC_Mask; //pll 입력: 외부클럭 (1값)이 바로 들어오는지 내부클럭/2 (0값)되서 들어오는지
#ifndef STM32F10X_CL
//pllmull 이 0 이면 pll은 *2로 동작
//pllmull 이 1 이면 pll은 *3로 동작 .....
pllmull = ( pllmull >> 18) + 2;
if (pllsource == 0x00) //내부클럭/2 * pll배수
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_Value >> 1) * pllmull;
}
else //외부 클럭 * pll 배수 또는 외부 클럭/2 * pll
{/* HSE selected as PLL clock entry */
if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
{/* HSE oscillator clock divided by 2 */
RCC_Clocks->SYSCLK_Frequency = (HSE_Value >> 1) * pllmull;
}
else
{
RCC_Clocks->SYSCLK_Frequency = HSE_Value * pllmull;
}
}
#else //성능 좋은 놈들 105,107
pllmull = pllmull >> 18;
if (pllmull != 0x0D)
{
//pllmull 이 0 이면 pll은 *2로 동작
//pllmull 이 1 이면 pll은 *3로 동작
pllmull += 2;
}
else
{ /* PLL multiplication factor = PLL input clock * 6.5 */
pllmull = 13 / 2;
}
if (pllsource == 0x00) //내부클럭/2 * pll배수
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_Value >> 1) * pllmull;
}
else //외부 클럭 * pll 배수
{/* PREDIV1 selected as PLL clock entry */
/* Get PREDIV1 clock source and division factor */
prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
if (prediv1source == 0)
{ /* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_Value / prediv1factor) * pllmull;
}
else
{/* PLL2 clock selected as PREDIV1 clock entry */
/* Get PREDIV2 division factor and PLL2 multiplication factor */
prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;
pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2;
RCC_Clocks->SYSCLK_Frequency = (((HSE_Value / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
}
}
#endif /* STM32F10X_CL */
break;
default:
RCC_Clocks->SYSCLK_Frequency = HSI_Value;
break;
}
/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
/* Get HCLK prescaler */
tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
tmp = tmp >> 4;
presc = APBAHBPrescTable[tmp];
/* HCLK clock frequency */ //core,AHB,menory,DMA 용
RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
/* Get PCLK1 prescaler */
tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
tmp = tmp >> 8;
presc = APBAHBPrescTable[tmp];
/* PCLK1 clock frequency */ //APB1 용 peripherals
//USART2,USART3,UART4,SPI/I2S2,SPI/I2S3,I2C1,I2C2,TIM2,TIM3,TIM4,TIM5,TIM6,TIM7가 사용
RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get PCLK2 prescaler */
tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
tmp = tmp >> 11;
presc = APBAHBPrescTable[tmp];
/* PCLK2 clock frequency */ //APB2용 peripherals
//USART1,SPI1,ADC1,ADC3,TIM1,TIM8 가 사용
RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get ADCCLK prescaler */
tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
tmp = tmp >> 14;
presc = ADCPrescTable[tmp];
/* ADCCLK clock frequency */ //ADC용 클럭
//타이머에 의한 ADC 동작을 만들수도 있고 ADC클럭으로 이벤트 동작을 할수도 있다.
RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
}
---------------------------------------------------------------------------------
* STM32F10X_CL define 문을 잘 보면서 소스를 봐야지 자꾸 잘못 본다.