하여간 스타트 업이 되면
main.c 의 int main(void) 로 점프를 한다.
main에서 최초에 만나는 문장은 RCC_Configuration 이다.
------------------------------------------------------
int main(void)
{
/* System Clocks Configuration */
RCC_Configuration();
------------------------------------------------------
RCC_Configuration 은 hw_config.c 파일에 들어 있다.
H/W 를 초기화 하는 곳인가 보다.
여기서 최초 문장은 SystemInit(); 다
------------------------------------------------------
void RCC_Configuration(void)
{
SystemInit();
/* Enable GPIOA clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Enable GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Enable GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable GPIOD clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
/* Enable USART1 clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
------------------------------------------------------
SystemInit 를 찾아보니 system_stm32f10x.c다.(너무 source를 쪼개둔거 아니야 짜증나)
내용을 살펴봐야 겠다.
------------------------------------------------------
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
//일단 클럭쪽 레지스터를 초기화 해서 사용 못하게 한다.
RCC->CR |= (uint32_t)0x00000001; //디버깅을 지원하기위해 HSI ON
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL //고사양 프로세서 STM32F105,STM32F107 용
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000; //RCC->CFGR 레지스터를 clr
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits -> clr*/
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit -> clr */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits -> clr*/
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifndef STM32F10X_CL
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#else
/* Reset PLL2ON and PLL3ON bits */ //클럭쪽 인터럽트 레지스터 사용 불가
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#endif /* STM32F10X_CL */
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock(); //클럭을 살린다.
}
------------------------------------------------------
내용인 즉은 SetSysClock을 실행하기 전에 기존에 사용중인 클럭 모드를 초기화 하는
것이다. SetSysClock은 클럭을 다시 살리는듯 하다. SetSysClock을 보면
사용하고자하는 클럭 쪽으로 설정하도록 모드가 여러가지다.
------------------------------------------------------
static void SetSysClock(void) // 클럭을 다시 설정 한다.
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz //다른쪽에 이것을 사용하도록 설정되어 있다.
SetSysClockTo72();
#endif
}
------------------------------------------------------
지금 보고 있는 장비는 외부 클럭이 12M 이고 내부 시스템 클럭을 pll로 72M 로 만들어서 사용할것이다. 그래서 SetSysClockTo72(); 이 실행된다.
그래서 SetSysClockTo72() 를 살펴보면 아래와 같다.
------------------------------------------------------
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON); //HSEON 외부 크리스탈 동작
//주의 STOP 이다. STANBY 모드시 HSE ON 0이됨 -> 다시 설정 해야겠지..
/* Wait till HSE is ready and if Time out is reached exit */
do //HSERDY가 SET 되면 사용가능 또는 time out 되면 빠저나감
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ((RCC->CR & RCC_CR_HSERDY) != RESET) //타임 아웃 되어서 나왔는지 확인 한다.
{
HSEStatus = (uint32_t)0x01; //1이면 안정
}
else
{
HSEStatus = (uint32_t)0x00; //0이면 불안정
}
if (HSEStatus == (uint32_t)0x01) //정상 클럭
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); //flash access 속도를 0으로 초기화
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; //flsdh access 속도를 2로 -> 40M < SYSCLK < 72M 일때
/* HCLK = SYSCLK */ // AHB,core,memory,DMA
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK/2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL //STM32F105,STM32F107 인경우
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
//PLL을 동작 시킨다.
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
#ifdef EXT_CLOCK_SOURCE_12M //외부 입력 크리스탈 소스 가 12M으로 사용됨 -> 필요시 수정되어야함
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); // 12M*6 => 72M
#else
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); //8M*9 => 72M
#endif
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else //비정상 클럭 무한 loop
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
/* Go to infinite loop */
while (1)
{
}
}
}
------------------------------------------------------
외부 크리스탈 살리고 이상이 없으면 PLL을 살리고 이상이 있으면 무한루프를 돌린다.
여기서 주의할것은 외부 크리스탈이 바뀌면 이부분의 다시보고 PLL등을 맞추어 주어야한다.