Merge pull request #235 from bcostm/master

[NUCLEO_L152RE/F103RB] Add automatic HSE/HSI clock configuration.
pull/237/head
Bogdan Marinescu 2014-03-27 09:41:25 +00:00
commit c81f9207c4
10 changed files with 550 additions and 793 deletions

View File

@ -35,7 +35,23 @@
* When HSE is used as system clock source, directly or through PLL, and you
* are using different crystal you have to adapt the HSE value to your own
* configuration.
*
* 5. This file configures the system clock as follows:
*-----------------------------------------------------------------------------
* System clock source | 1- PLL_HSE_EXTC | 3- PLL_HSI
* | (external 8 MHz clock) | (internal 8 MHz)
* | 2- PLL_HSE_XTAL |
* | (external 8 MHz xtal) |
*-----------------------------------------------------------------------------
* SYSCLK(MHz) | 72 | 64
*-----------------------------------------------------------------------------
* AHBCLK (MHz) | 72 | 64
*-----------------------------------------------------------------------------
* APB1CLK (MHz) | 36 | 32
*-----------------------------------------------------------------------------
* APB2CLK (MHz) | 72 | 64
*-----------------------------------------------------------------------------
* USB capable (48 MHz precise clock) | YES | NO
*-----------------------------------------------------------------------------
*******************************************************************************
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
@ -95,55 +111,11 @@
* @{
*/
/*!< Uncomment the line corresponding to the desired System clock (SYSCLK)
frequency (after reset the HSI is used as SYSCLK source)
IMPORTANT NOTE:
==============
1. After each device reset the HSI is used as System clock source.
2. Please make sure that the selected System clock doesn't exceed your device's
maximum frequency.
3. If none of the define below is enabled, the HSI is used as System clock
source.
4. The System clock configuration functions provided within this file assume that:
- For Low, Medium and High density Value line devices an external 8MHz
crystal is used to drive the System clock.
- For Low, Medium and High density devices an external 8MHz crystal is
used to drive the System clock.
- For Connectivity line devices an external 25MHz crystal is used to drive
the System clock.
If you are using different crystal you have to adapt those functions accordingly.
*/
#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
/*!< Uncomment the following line if you need to use external SRAM mounted
on STM3210E-EVAL board (STM32 High density and XL-density devices) or on
STM32100E-EVAL board (STM32 High-density value line devices) as data memory */
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
/* #define DATA_IN_ExtSRAM */
#endif
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/**
* @}
*/
@ -152,6 +124,10 @@
* @{
*/
/* Select the clock sources (other than HSI) to start with (0=OFF, 1=ON) */
#define USE_PLL_HSE_EXTC (1) /* Use external clock */
#define USE_PLL_HSE_XTAL (1) /* Use external xtal */
/**
* @}
*/
@ -160,24 +136,7 @@
* @{
*/
/*******************************************************************************
* Clock Definitions
*******************************************************************************/
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */
uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */
#endif
uint32_t SystemCoreClock = 64000000; /* Default with HSI. Will be updated if HSE is used */
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/**
@ -188,22 +147,14 @@ __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}
* @{
*/
static void SetSysClock(void);
void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#if (USE_PLL_HSE_XTAL != 0) || (USE_PLL_HSE_EXTC != 0)
uint8_t SetSysClock_PLL_HSE(uint8_t bypass);
#endif
uint8_t SetSysClock_PLL_HSI(void);
#ifdef DATA_IN_ExtSRAM
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM */
@ -431,24 +382,41 @@ void SystemCoreClockUpdate (void)
* @param None
* @retval None
*/
static void SetSysClock(void)
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();
/* 1- Try to start with HSE and external clock */
#if USE_PLL_HSE_EXTC != 0
if (SetSysClock_PLL_HSE(1) == 0)
#endif
/* If none of the define above is enabled, the HSI is used as System clock
source (default after reset) */
{
/* 2- If fail try to start with HSE and external xtal */
#if USE_PLL_HSE_XTAL != 0
if (SetSysClock_PLL_HSE(0) == 0)
#endif
{
/* 3- If fail start with HSI clock */
if (SetSysClock_PLL_HSI() == 0)
{
while(1)
{
// [TODO] Put something here to tell the user that a problem occured...
}
}
}
}
/* Output SYSCLK on MCO pin(PA8) for debugging purpose */
/*
// Enable GPIOA clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Select the clock to output
RCC_MCOConfig(RCC_MCO_SYSCLK);
*/
}
/**
@ -504,572 +472,57 @@ void SystemInit_ExtMemCtl(void)
}
#endif /* DATA_IN_ExtSRAM */
#ifdef SYSCLK_FREQ_HSE
/**
* @brief Selects HSE as System clock source and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockToHSE(void)
#if (USE_PLL_HSE_XTAL != 0) || (USE_PLL_HSE_EXTC != 0)
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
__IO uint32_t StartUpCounter = 0;
__IO uint32_t HSEStatus = 0;
/* Bypass HSE: can be done only if HSE is OFF */
RCC->CR &= ((uint32_t)~RCC_CR_HSEON); /* To be sure HSE is OFF */
if (bypass != 0)
{
RCC->CR |= ((uint32_t)RCC_CR_HSEBYP);
}
else
{
RCC->CR &= ((uint32_t)~RCC_CR_HSEBYP);
}
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
/* Wait till HSE is ready */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
/* Check if HSE has started correctly */
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
/* Flash wait states
0WS for 0 < SYSCLK <= 24 MHz
1WS for 24 < SYSCLK <= 48 MHz
2WS for 48 < SYSCLK <= 72 MHz */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
#ifndef STM32F10X_CL
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#else
if (HSE_VALUE <= 24000000)
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
}
else
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
}
#endif /* STM32F10X_CL */
#endif
/* 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;
/* Select HSE as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04)
{
}
}
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 */
}
}
#elif defined SYSCLK_FREQ_24MHz
/**
* @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo24(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)
{
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#endif
/* 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;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 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_PLLMULL6);
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 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_DIV10);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/* PLL configuration: = (HSE / 2) * 6 = 24 MHz */
/* PLL configuration */
/* SYSCLK = 72 MHz (8 MHz * 9) */
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);
#else
/* 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_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6);
#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 */
}
}
#elif defined SYSCLK_FREQ_36MHz
/**
* @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo36(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 1 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
/* 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;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 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);
/*!< PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 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_DIV10);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
#else
/* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 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_PLLXTPRE_HSE_Div2 | 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 */
}
}
#elif defined SYSCLK_FREQ_48MHz
/**
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo48(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 1 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
/* 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 * 6 = 48 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_PLLMULL6);
#else
/* PLL configuration: PLLCLK = HSE * 6 = 48 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_PLLMULL6);
#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 */
}
}
#elif defined SYSCLK_FREQ_56MHz
/**
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo56(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 * 7 = 56 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_PLLMULL7);
#else
/* PLL configuration: PLLCLK = HSE * 7 = 56 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_PLLMULL7);
#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 */
}
}
#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 */
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9
| RCC_CFGR_HPRE_DIV1 /* HCLK = 72 MHz */
| RCC_CFGR_PPRE2_DIV1 /* PCLK2 = 72 MHz */
| RCC_CFGR_PPRE1_DIV2); /* PCLK1 = 36 MHz */
/* USBCLK = 48 MHz (72 MHz / 1.5) --> USB OK */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
@ -1081,20 +534,68 @@ static void SetSysClockTo72(void)
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
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)
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
return 1; // OK
}
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 */
{
return 0; // FAIL
}
}
#endif
/******************************************************************************/
/* PLL (clocked by HSI) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSI(void)
{
__IO uint32_t StartUpCounter = 0;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash wait states
0WS for 0 < SYSCLK <= 24 MHz
1WS for 24 < SYSCLK <= 48 MHz
2WS for 48 < SYSCLK <= 72 MHz */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* PLL configuration
PLLCLK = 64 MHz (HSI/2 * 16) */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL16
| RCC_CFGR_HPRE_DIV1 /* HCLK = 64 MHz */
| RCC_CFGR_PPRE2_DIV1 /* PCLK2 = 64 MHz */
| RCC_CFGR_PPRE1_DIV2); /* PCLK1 = 32 MHz */
/* USBCLK = 42.667 MHz (64 MHz / 1.5) --> USB NOT POSSIBLE */
/* 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)RCC_CFGR_SWS_PLL)
{
}
return 1; // OK
}
/**
* @}
*/
@ -1102,8 +603,9 @@ static void SetSysClockTo72(void)
/**
* @}
*/
/**
* @}
*/
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -27,7 +27,8 @@
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LR_IROM1 0x08000000 0x80000 { ; load region size_region (512 KB)
; STM32L152RE: 512KB FLASH + 80KB SRAM
LR_IROM1 0x08000000 0x80000 { ; load region size_region
ER_IROM1 0x08000000 0x80000 { ; load address = execution address
*.o (RESET, +First)

View File

@ -27,7 +27,8 @@
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LR_IROM1 0x08000000 0x80000 { ; load region size_region (512 KB)
; STM32L152RE: 512KB FLASH + 80KB SRAM
LR_IROM1 0x08000000 0x80000 { ; load region size_region
ER_IROM1 0x08000000 0x80000 { ; load address = execution address
*.o (RESET, +First)

View File

@ -38,38 +38,25 @@
* in "stm32l1xx.h" file. When HSE is used as system clock source, directly or
* through PLL, and you are using different crystal you have to adapt the HSE
* value to your own configuration.
*
* 5. This file configures the system clock as follows:
*=============================================================================
* System Clock Configuration
*=============================================================================
* System Clock source | PLL(HSI)
*-----------------------------------------------------------------------------
* SYSCLK | 32000000 Hz
*-----------------------------------------------------------------------------
* HCLK | 32000000 Hz
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB1 Prescaler | 1
*-----------------------------------------------------------------------------
* APB2 Prescaler | 1
*-----------------------------------------------------------------------------
* HSE Frequency | Not used
*-----------------------------------------------------------------------------
* PLL DIV | 2
*-----------------------------------------------------------------------------
* PLL MUL | 4
*-----------------------------------------------------------------------------
* VDD | 3.3 V
*-----------------------------------------------------------------------------
* Vcore | 1.8 V (Range 1)
*-----------------------------------------------------------------------------
* Flash Latency | 1 WS
*-----------------------------------------------------------------------------
* Require 48MHz for USB clock | Disabled
*-----------------------------------------------------------------------------
*=============================================================================
*
* 5. This file configures the system clock as follows:
*-----------------------------------------------------------------------------
* System clock source | 1- PLL_HSE_EXTC | 3- PLL_HSI
* | (external 8 MHz clock) | (internal 16 MHz)
* | 2- PLL_HSE_XTAL |
* | (external 8 MHz xtal) |
*-----------------------------------------------------------------------------
* SYSCLK(MHz) | 24 | 32
*-----------------------------------------------------------------------------
* AHBCLK (MHz) | 24 | 32
*-----------------------------------------------------------------------------
* APB1CLK (MHz) | 24 | 32
*-----------------------------------------------------------------------------
* APB2CLK (MHz) | 24 | 32
*-----------------------------------------------------------------------------
* USB capable (48 MHz precise clock) | YES | NO
*-----------------------------------------------------------------------------
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
@ -142,6 +129,10 @@
* @{
*/
/* Select the clock sources (other than HSI) to start with (0=OFF, 1=ON) */
#define USE_PLL_HSE_EXTC (1) /* Use external clock */
#define USE_PLL_HSE_XTAL (1) /* Use external xtal */
/**
* @}
*/
@ -149,7 +140,9 @@
/** @addtogroup STM32L1xx_System_Private_Variables
* @{
*/
uint32_t SystemCoreClock = 32000000;
uint32_t SystemCoreClock = 32000000; /* Default with HSI. Will be updated if HSE is used */
__I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
@ -163,6 +156,12 @@ __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}
void SetSysClock(void);
#if (USE_PLL_HSE_XTAL != 0) || (USE_PLL_HSE_EXTC != 0)
uint8_t SetSysClock_PLL_HSE(uint8_t bypass);
#endif
uint8_t SetSysClock_PLL_HSI(void);
/**
* @}
*/
@ -198,35 +197,20 @@ void SystemInit (void)
/*!< Disable all interrupts */
RCC->CIR = 0x00000000;
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings */
SetSysClock();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal 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. */
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
/* ADDED FOR MBED DEBUG PURPOSE */
/*
// Enable the GPIOA peripheral
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// Output the system clock on MCO pin (PA.08)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Select the clock to output on MCO pin (PA.08)
RCC_MCOConfig(RCC_MCOSource_SYSCLK, RCC_MCODiv_1);
//RCC_MCOConfig(RCC_MCOSource_HSI, RCC_MCODiv_1);
*/
}
/**
* @brief Update SystemCoreClock according to Clock Register Values
* @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.
@ -315,8 +299,8 @@ void SystemCoreClockUpdate (void)
}
/**
* @brief Configures the System clock frequency, AHB/APBx prescalers and Flash
* settings.
* @brief Configures the System clock source, PLL Multiplier and Divider factors,
* AHB/APBx prescalers and Flash settings
* @note This function should be called only once the RCC clock configuration
* is reset to the default reset state (done in SystemInit() function).
* @param None
@ -324,41 +308,89 @@ void SystemCoreClockUpdate (void)
*/
void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSIStatus = 0;
/* 1- Try to start with HSE and external clock */
#if USE_PLL_HSE_EXTC != 0
if (SetSysClock_PLL_HSE(1) == 0)
#endif
{
/* 2- If fail try to start with HSE and external xtal */
#if USE_PLL_HSE_XTAL != 0
if (SetSysClock_PLL_HSE(0) == 0)
#endif
{
/* 3- If fail start with HSI clock */
if (SetSysClock_PLL_HSI() == 0)
{
while(1)
{
// [TODO] Put something here to tell the user that a problem occured...
}
}
}
}
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSI */
RCC->CR |= ((uint32_t)RCC_CR_HSION);
/* Wait till HSI is ready and if Time out is reached exit */
do
{
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
} while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
/* Output SYSCLK on MCO pin(PA8) for debugging purpose */
/*
// Enable GPIOA clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// Configure MCO pin (PA8)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Select the clock to output
RCC_MCOConfig(RCC_MCOSource_SYSCLK, RCC_MCODiv_1);
*/
}
if ((RCC->CR & RCC_CR_HSIRDY) != RESET)
#if (USE_PLL_HSE_XTAL != 0) || (USE_PLL_HSE_EXTC != 0)
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
__IO uint32_t StartUpCounter = 0;
__IO uint32_t HSEStatus = 0;
/* Bypass HSE: can be done only if HSE is OFF */
RCC->CR &= ((uint32_t)~RCC_CR_HSEON); /* To be sure HSE is OFF */
if (bypass != 0)
{
HSIStatus = (uint32_t)0x01;
RCC->CR |= ((uint32_t)RCC_CR_HSEBYP);
}
else
{
HSIStatus = (uint32_t)0x00;
RCC->CR &= ((uint32_t)~RCC_CR_HSEBYP);
}
if (HSIStatus == (uint32_t)0x01)
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
/* Check if HSE has started correctly */
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
/* Enable 64-bit access */
FLASH->ACR |= FLASH_ACR_ACC64;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Flash 1 wait state (latency) */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Power enable */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Select the Voltage Range 1 (1.8 V) */
PWR->CR = PWR_CR_VOS_0;
@ -368,18 +400,13 @@ void SetSysClock(void)
}
/* PLL configuration */
/* SYSCLK = (HSI 16 MHz * 4) / 2 = 32 MHz */
/* SYSCLK = 24 MHz ((8 MHz * 6) / 2) */
/* USBCLK = 48 MHz (8 MHz * 6) --> USB OK */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2);
/* HCLK = 32 MHz */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = 32 MHz */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = 32 MHz */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV2
| RCC_CFGR_HPRE_DIV1 /* HCLK = 24 MHz */
| RCC_CFGR_PPRE2_DIV1 /* PCLK2 = 24 MHz */
| RCC_CFGR_PPRE1_DIV1); /* PCLK1 = 24 MHz */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
@ -388,7 +415,7 @@ void SetSysClock(void)
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;
@ -397,11 +424,87 @@ void SetSysClock(void)
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
return 1; // OK
}
else
{
/* If HSI fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
return 0; // FAIL
}
}
#endif
/******************************************************************************/
/* PLL (clocked by HSI) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSI(void)
{
__IO uint32_t StartUpCounter = 0;
__IO uint32_t HSIStatus = 0;
/* Enable HSI */
RCC->CR |= ((uint32_t)RCC_CR_HSION);
/* Wait till HSI is ready */
do
{
HSIStatus = RCC->CR & RCC_CR_HSIRDY;
StartUpCounter++;
} while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSIRDY) != RESET)
{
/* Enable 64-bit access */
FLASH->ACR |= FLASH_ACR_ACC64;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Flash 1 wait state (latency) */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Power enable */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Select the Voltage Range 1 (1.8 V) */
PWR->CR = PWR_CR_VOS_0;
/* Wait Until the Voltage Regulator is ready */
while((PWR->CSR & PWR_CSR_VOSF) != RESET)
{
}
/* PLL configuration */
/* SYSCLK = 32 MHz ((16 MHz * 4) / 2) */
/* USBCLK = 64 MHz (16 MHz * 4) --> USB not possible */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2
| RCC_CFGR_HPRE_DIV1 /* HCLK = 32 MHz */
| RCC_CFGR_PPRE2_DIV1 /* PCLK2 = 32 MHz */
| RCC_CFGR_PPRE1_DIV1); /* PCLK1 = 32 MHz */
/* 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)RCC_CFGR_SWS_PLL)
{
}
return 1; // OK
}
else
{
return 0; // FAIL
}
}

View File

@ -0,0 +1,35 @@
/* mbed Microcontroller Library
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern void SystemCoreClockUpdate(void);
// This function is called after RAM initialization and before main.
void mbed_sdk_init() {
// Update the SystemCoreClock variable.
SystemCoreClockUpdate();
}

View File

@ -30,6 +30,9 @@
#include "sleep_api.h"
#include "cmsis.h"
// This function is in the system_stm32f10x.c file
extern void SetSysClock(void);
void sleep(void)
{
// Disable us_ticker update interrupt
@ -53,6 +56,9 @@ void deepsleep(void)
// Request to enter STOP mode with regulator in low power mode
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// After wake-up from STOP reconfigure the PLL
SetSysClock();
// Re-enable us_ticker update interrupt
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
}

View File

@ -38,25 +38,29 @@
static const PinMap PinMap_SPI_MOSI[] = {
{PA_7, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{PB_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
{PB_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // GPIO_Remap_SPI1
{PB_15, SPI_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{NC, NC, 0}
};
static const PinMap PinMap_SPI_MISO[] = {
{PA_6, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{PB_4, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
{PB_4, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // GPIO_Remap_SPI1
{PB_14, SPI_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{NC, NC, 0}
};
static const PinMap PinMap_SPI_SCLK[] = {
{PA_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{PB_3, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
{PB_3, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // GPIO_Remap_SPI1
{PB_13, SPI_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{NC, NC, 0}
};
// Only used in Slave mode
static const PinMap PinMap_SPI_SSEL[] = {
{PB_6, SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)}, // Generic IO, not real H/W NSS pin
{PA_4, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{PA_15, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // GPIO_Remap_SPI1
{PB_12, SPI_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
{NC, NC, 0}
};
@ -66,15 +70,15 @@ static void init_spi(spi_t *obj) {
SPI_Cmd(spi, DISABLE);
SPI_InitStructure.SPI_Mode = obj->mode;
SPI_InitStructure.SPI_NSS = obj->nss;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = obj->bits;
SPI_InitStructure.SPI_CPOL = obj->cpol;
SPI_InitStructure.SPI_CPHA = obj->cpha;
SPI_InitStructure.SPI_Mode = obj->mode;
SPI_InitStructure.SPI_NSS = obj->nss;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = obj->bits;
SPI_InitStructure.SPI_CPOL = obj->cpol;
SPI_InitStructure.SPI_CPHA = obj->cpha;
SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(spi, &SPI_InitStructure);
SPI_Cmd(spi, ENABLE);
@ -100,7 +104,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
if (obj->spi == SPI_1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
}
if (obj->spi == SPI_2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
}
// Configure the SPI pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
@ -110,7 +117,7 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
obj->bits = SPI_DataSize_8b;
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_1Edge;
obj->br_presc = SPI_BaudRatePrescaler_256; // 1MHz
obj->br_presc = SPI_BaudRatePrescaler_256;
if (ssel == NC) { // Master
obj->mode = SPI_Mode_Master;
@ -171,23 +178,62 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
}
void spi_frequency(spi_t *obj, int hz) {
// Choose the baud rate divisor (between 2 and 256)
uint32_t divisor = SystemCoreClock / hz;
// Find the nearest power-of-2
divisor = (divisor > 0 ? divisor-1 : 0);
divisor |= divisor >> 1;
divisor |= divisor >> 2;
divisor |= divisor >> 4;
divisor |= divisor >> 8;
divisor |= divisor >> 16;
divisor++;
uint32_t baud_rate = __builtin_ffs(divisor) - 2;
if (obj->spi == SPI_1) {
// Values depend of PCLK2: 64 MHz if HSI is used, 72 MHz if HSE is used
if (hz < 500000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 250 kHz - 281 kHz
}
else if ((hz >= 500000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 500 kHz - 563 kHz
}
else if ((hz >= 1000000) && (hz < 2000000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 1 MHz - 1.13 MHz
}
else if ((hz >= 2000000) && (hz < 4000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 2 MHz - 2.25 MHz
}
else if ((hz >= 4000000) && (hz < 8000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 4 MHz - 4.5 MHz
}
else if ((hz >= 8000000) && (hz < 16000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 8 MHz - 9 MHz
}
else if ((hz >= 16000000) && (hz < 32000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 16 MHz - 18 MHz
}
else { // >= 32000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 32 MHz - 36 MHz
}
}
// Save new value
obj->br_presc = ((baud_rate > 7) ? (7 << 3) : (baud_rate << 3));
if (obj->spi == SPI_2) {
// Values depend of PCLK1: 32 MHz if HSI is used, 36 MHz if HSE is used
if (hz < 250000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 125 kHz - 141 kHz
}
else if ((hz >= 250000) && (hz < 500000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 250 kHz - 281 kHz
}
else if ((hz >= 500000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 500 kHz - 563 kHz
}
else if ((hz >= 1000000) && (hz < 2000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 1 MHz - 1.13 MHz
}
else if ((hz >= 2000000) && (hz < 4000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 2 MHz - 2.25 MHz
}
else if ((hz >= 4000000) && (hz < 8000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 4 MHz - 4.5 MHz
}
else if ((hz >= 8000000) && (hz < 16000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 8 MHz - 9 MHz
}
else { // >= 16000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 16 MHz - 18 MHz
}
}
init_spi(obj);
}

View File

@ -153,7 +153,7 @@ typedef enum {
SPI_MISO = PB_14,
SPI_SCK = PB_13,
SPI_CS = PB_6,
PWM_OUT = PB_3,
PWM_OUT = PB_4,
// Not connected
NC = (int)0xFFFFFFFF

View File

@ -0,0 +1,35 @@
/* mbed Microcontroller Library
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern void SystemCoreClockUpdate(void);
// This function is called after RAM initialization and before main.
void mbed_sdk_init() {
// Update the SystemCoreClock variable.
SystemCoreClockUpdate();
}

View File

@ -191,30 +191,58 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
}
void spi_frequency(spi_t *obj, int hz) {
// Note: The frequencies are obtained with SPI clock = 32 MHz (APB1 & APB2 clocks)
if (hz < 250000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 125 kHz
// Values depend of PCLK1 and PCLK2: 32 MHz if HSI is used, 24 MHz if HSE is used
if (SystemCoreClock == 32000000) { // HSI
if (hz < 250000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 125 kHz
}
else if ((hz >= 250000) && (hz < 500000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 250 kHz
}
else if ((hz >= 500000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 500 kHz
}
else if ((hz >= 1000000) && (hz < 2000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 1 MHz
}
else if ((hz >= 2000000) && (hz < 4000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 2 MHz
}
else if ((hz >= 4000000) && (hz < 8000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 4 MHz
}
else if ((hz >= 8000000) && (hz < 16000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 8 MHz
}
else { // >= 16000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 16 MHz
}
}
else if ((hz >= 250000) && (hz < 500000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 250 kHz
}
else if ((hz >= 500000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 500 kHz
}
else if ((hz >= 1000000) && (hz < 2000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 1 MHz
}
else if ((hz >= 2000000) && (hz < 4000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 2 MHz
}
else if ((hz >= 4000000) && (hz < 8000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 4 MHz
}
else if ((hz >= 8000000) && (hz < 16000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 8 MHz
}
else { // >= 16000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 16 MHz
else { // 24 MHz - HSE
if (hz < 180000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 94 kHz
}
else if ((hz >= 180000) && (hz < 350000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 188 kHz
}
else if ((hz >= 350000) && (hz < 750000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 375 kHz
}
else if ((hz >= 750000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 750 kHz
}
else if ((hz >= 1000000) && (hz < 3000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 1.5 MHz
}
else if ((hz >= 3000000) && (hz < 6000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 3 MHz
}
else if ((hz >= 6000000) && (hz < 12000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 6 MHz
}
else { // >= 12000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 12 MHz
}
}
init_spi(obj);
}