mbed library sources
Fork of mbed-src by
Diff: targets/cmsis/TARGET_STM/TARGET_NUCLEO_L152RE/system_stm32l1xx.c
- Revision:
- 139:e3413eddde57
- Parent:
- 129:0182c99221bc
- Child:
- 354:e67efb2aab0e
--- a/targets/cmsis/TARGET_STM/TARGET_NUCLEO_L152RE/system_stm32l1xx.c Tue Mar 25 17:45:07 2014 +0000 +++ b/targets/cmsis/TARGET_STM/TARGET_NUCLEO_L152RE/system_stm32l1xx.c Thu Mar 27 09:45:07 2014 +0000 @@ -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>© 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 @@ 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 @@ /*!< 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 @@ } /** - * @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 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 + /* 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 (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 = RCC->CR & RCC_CR_HSIRDY; - } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); - - if ((RCC->CR & RCC_CR_HSIRDY) != RESET) - { - 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 @@ } /* 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 @@ 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 @@ 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 } }