您的位置:首页 > 其它

STM32启动后系统初始化SystemInit()

2016-04-07 14:55 281 查看
启动文件中复位异常相应函数如下:

; Reset handler
Reset_Handler   PROC
EXPORT  Reset_Handler             [WEAK]
IMPORT  __main
IMPORT  SystemInit
LDR     R0, =SystemInit
BLX     R0
LDR     R0, =__main
BX      R0
ENDP


SystemInit()这个函数出现在main()函数的第一行,可以看出它的重要性。以前关于SystemInit()这个函数从来没有关心过,只知道这是进行STM32系统初始化的一个函数。今天决定仔细看看,重新开始STM32的学习。这个函数在system_stm32f10x.c中,此C文件主要就是干具体硬件配置相关的工作。

[cpp] view
plain copy

print?

/** @addtogroup STM32F10x_System_Private_Functions

* @{

*/

/**

* @brief Setup the microcontroller system

* Initialize the Embedded Flash Interface, the PLL and update the

* SystemCoreClock variable.

* @note This function should be used only after reset.

* @param None

* @retval None

*/

void SystemInit (void)

{

/* Reset the RCC clock configuration to the default reset state(for debug purpose) */

/* Set HSION bit */

RCC->CR |= (uint32_t)0x00000001;

/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

#ifndef STM32F10X_CL

RCC->CFGR &= (uint32_t)0xF8FF0000;

#else

RCC->CFGR &= (uint32_t)0xF0FF0000;

#endif /* STM32F10X_CL */

/* Reset HSEON, CSSON and PLLON bits */

RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset HSEBYP bit */

RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL

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

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* Disable all interrupts and clear pending bits */

RCC->CIR = 0x009F0000;

/* Reset CFGR2 register */

RCC->CFGR2 = 0x00000000;

#else

/* Disable all interrupts and clear pending bits */

RCC->CIR = 0x009F0000;

#endif /* STM32F10X_CL */

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

#ifdef DATA_IN_ExtSRAM

SystemInit_ExtMemCtl();

#endif /* DATA_IN_ExtSRAM */

#endif

/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

/* Configure the Flash Latency cycles and enable prefetch buffer */

SetSysClock();

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */

#endif

}

从函数说明来看,此函数功能就是初始化内部FALSH,PLL并且更新系统时钟。此函数需在复位启动后调用。

[cpp] view
plain copy

print?

RCC->CR |= (uint32_t)0x00000001;

第一行代码操作时钟控制寄存器,将内部8M高速时钟使能,从这里可以看出系统启动后是首先依靠内部时钟源而工作的。

[cpp] view
plain copy

print?

#ifndef STM32F10X_CL

RCC->CFGR &= (uint32_t)0xF8FF0000;

#else

RCC->CFGR &= (uint32_t)0xF0FF0000;

这两行代码则是操作时钟配置寄存器。其主要设置了MCO(微控制器时钟输出)PLL相关(PLL倍频系数,PLL输入时钟源),ADCPRE(ADC时钟),PPRE2(高速APB分频系数),PPRE1(低速APB分频系数),HPRE(AHB预分频系数),SW(系统时钟切换),开始时,系统时钟切换到HSI,由它作为系统初始时钟。宏STM32F10X_CL是跟具体STM32芯片相关的一个宏。

[cpp] view
plain copy

print?

/* Reset HSEON, CSSON and PLLON bits */

RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset HSEBYP bit */

RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

RCC->CFGR &= (uint32_t)0xFF80FFFF;

这几句话则是先在关闭HSE,CSS,,PLL等的情况下配置好与之相关参数然后开启,达到生效的目的。

[cpp] view
plain copy

print?

#ifdef STM32F10X_CL

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

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* Disable all interrupts and clear pending bits */

RCC->CIR = 0x009F0000;

/* Reset CFGR2 register */

RCC->CFGR2 = 0x00000000;

#else

/* Disable all interrupts and clear pending bits */

RCC->CIR = 0x009F0000;

#endif /* STM32F10X_CL */

这一段主要是跟中断设置有关。开始时,我们需要禁止所有中断并且清除所有中断标志位。不同硬件有不同之处。

[cpp] view
plain copy

print?

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

#ifdef DATA_IN_ExtSRAM

SystemInit_ExtMemCtl();

#endif /* DATA_IN_ExtSRAM */

#endif

这段跟设置外部RAM有关吧,我用到的STM32F103RBT与此无关。

[cpp] view
plain copy

print?

SetSysClock();

此又是一个函数,主要是配置系统时钟频率。HCLK,PCLK2,PCLK1的分频值,分别代表AHB,APB2,和APB1。当然还干了其它的事情,配置FLASH延时周期和使能预取缓冲期。后面的这个配置具体还不了解。

[cpp] view
plain copy

print?

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */

#endif

这段代码主要是实现向量表的重定位。依据你想要将向量表定位在内部SRAM中还是内部FLASH中。这个SCB开始没在STM32参考手册中发现,原来它是跟Cortex-M3内核相关的东西。所以ST公司就没有把它包含进来吧。内核的东西后面再了解,这里给自己提个醒。

然后再看看SystemInit()中的那个函数SetClock()又做了什么吧。

[cpp] view
plain copy

print?

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

/* If none of the define above is enabled, the HSI is used as System clock

source (default after reset) */

}

从中可以看出就是根据不同的宏来设置不同的系统时钟,这些宏就在跟此函数在同一个源文件里。官方很是考虑周到,我们只需要选择相应宏就能达到快速配置系统时钟的目的。

[cpp] view
plain copy

print?

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

#else

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz 24000000 */

/* #define SYSCLK_FREQ_36MHz 36000000 */

/* #define SYSCLK_FREQ_48MHz 48000000 */

/* #define SYSCLK_FREQ_56MHz 56000000 */

#define SYSCLK_FREQ_72MHz 72000000

#endif

比如这里我需要配置系统时钟为72MHZ,则只需要将#define SYSCLK_FREQ_72MHz 72000000两边的注释符去掉。

这个函数里面又有SetSysClockTo72()函数,这个函数就是具体操作寄存器进行配置了。

[cpp] view
plain copy

print?

#elif defined SYSCLK_FREQ_72MHz

/**

* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2

* and PCLK1 prescalers.

* @note This function should be used only after reset.

* @param None

* @retval None

*/

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);

/* Wait till HSE is ready and if Time out is reached exit */

do

{

HSEStatus = RCC->CR & RCC_CR_HSERDY;

StartUpCounter++;

} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)

{

HSEStatus = (uint32_t)0x01;

}

else

{

HSEStatus = (uint32_t)0x00;

}

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->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;

/* HCLK = SYSCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

/* PCLK2 = HCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

/* PCLK1 = HCLK */

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL

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

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |

RCC_CFGR_PLLMULL));

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

#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

{ /* If HSE fails to start-up, the application will have wrong clock

configuration. User can add here some code to deal with this error */

}

}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: