注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BA5AG的博客

业余电台 Arduino RaspberryPi

 
 
 

日志

 
 

100C8的SystemInit  

2014-04-25 20:34:28|  分类: STM32F100 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c

这是startup.s里调用的第一个函数SystemInit所在的地方。我们这样来编译它:

CC = $(GNUARM)/bin/arm-none-eabi-gcc

DEFS = -DSTM32F10X_MD_VL

FLAG = -mcpu=cortex-m3 -mthumb -Wall

system_stm32f10x.o: $(STM)/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c

        $(CC) $(INC) $(DEFS) $(FLAG) -c $<

我们来看看这个.c里面有什么。

#include "stm32f10x.h"

暂时还不清楚它具体为什么要用到这个头文件,先看下去。

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000

既然我们-D了STM32F10X_MD_VL,那么这个宏SYSCLK_FREQ_24MHz就会被定义,显然后面会有用。

#define VECT_TAB_OFFSET 0x0

中断向量表起始地址。这个宏在我们这块芯片的代码中没有用到。

#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz;

看出来了吧,因为我们-D了STM32F10X_MD_VL,那么就有了宏SYSCLK_FREQ_24MHz,于是SystemCoreClock这个全局变量就有了24000000的值。这个全局变量是开放的,所以在你的应用程序里是可以使用的,以此可以知道当前的芯片的时钟频率。

__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};

这是AHB外设总线上的预分频器的分频表。这是用在下面一个叫做SystemCoreClockUpdate的函数里的。这个SystemCoreClockUpdate函数是用来根据时钟类寄存器的值重新刷新SystemCoreClock这个全局变量的。

接下来就是这个SystemInit函数了,这个反而很好懂,我把不相关的条件编译的部分去掉,整理如下:

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 */
RCC->CFGR &= (uint32_t)0xF0FF0000;

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

/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;

/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;

/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();

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

它调用了SetSysClock(),这个函数就在它下面(中间隔了另一个函数),这个函数由一堆的条件编译,最后走去调用具体和芯片相关的一个时钟配置函数,我们的F100C8是SetSysClockTo24:

__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)
{
/* 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_DIV1;

/* PLL configuration: = (HSE / 2) * 6 = 24 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);

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

这两个函数都是通过读写RCC组的寄存器来做基础的时钟配置的,具体要读懂每一次读写,需要去看详细的芯片数据手册了。我们先暂且放过,但是,这里的RCC是什么?
stm32f10x.h里(这就是为什么它要include这个头文件),我们找到了:

#define RCC ((RCC_TypeDef *) RCC_BASE)

而这个RCC_BASE:

#define RCC_BASE (AHBPERIPH_BASE + 0x1000)

而这个AHBPERIPH_BASE:

#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)

而这个PERIPH_BASE:

#define PERIPH_BASE ((uint32_t)0x40000000)

好嘛,绕了一大圈,RCC是RCC组寄存器的第一个寄存器的地址0x40021000,那么RCC_TypeDef是什么?

typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;

uint32_t RESERVED0;
__IO uint32_t CFGR2;
} RCC_TypeDef;

看到了吧,就是这一组寄存器,所以,SystemInit的第一句:

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

就是CR寄存器或上了1。


  评论这张
 
阅读(138)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018