Skip to content
Snippets Groups Projects
Commit 0d628b6d authored by Ludwig Knüpfer's avatar Ludwig Knüpfer Committed by GitHub
Browse files

Merge pull request #6110 from lebrush/stm32f1-no-pll

cpu/stm32f1: implement lpm + run without PLL
parents 537b725a 419dcfdf
No related branches found
No related tags found
No related merge requests found
/* /*
* Copyright (C) 2013 INRIA * Copyright (C) 2013 INRIA
* Copyright (C) 2014 Freie Universität Berlin * Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2016 TriaGnoSys GmbH
* *
* This file is subject to the terms and conditions of the GNU Lesser General * This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more * Public License v2.1. See the file LICENSE in the top level directory for more
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl> * @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Víctor Ariño <victor.arino@zii.aero>
* *
* @} * @}
*/ */
...@@ -26,9 +28,19 @@ ...@@ -26,9 +28,19 @@
#include "cpu.h" #include "cpu.h"
#include "periph_conf.h" #include "periph_conf.h"
/* Check the source to be used for the PLL */ /* See if we want to use the PLL */
#if defined(CLOCK_PLL_DIV) || defined(CLOCK_PLL_MUL)
#define CLOCK_USE_PLL 1
#else
#define CLOCK_USE_PLL 0
#endif
/* Check the source to be used and parameters */
#if defined(CLOCK_HSI) && defined(CLOCK_HSE) #if defined(CLOCK_HSI) && defined(CLOCK_HSE)
#error "Only provide one of two CLOCK_HSI/CLOCK_HSE" #error "Only provide one of two CLOCK_HSI/CLOCK_HSE"
#elif (CLOCK_USE_PLL == 1) && (!defined(CLOCK_PLL_MUL) || !defined(CLOCK_PLL_DIV))
#error "When using PLL both CLOCK_PLL_DIV and CLOCK_PLL_MUL must be provided"
#elif CLOCK_HSI #elif CLOCK_HSI
#define CLOCK_CR_SOURCE RCC_CR_HSION #define CLOCK_CR_SOURCE RCC_CR_HSION
#define CLOCK_CR_SOURCE_RDY RCC_CR_HSIRDY #define CLOCK_CR_SOURCE_RDY RCC_CR_HSIRDY
...@@ -36,8 +48,11 @@ ...@@ -36,8 +48,11 @@
#define CLOCK_PLL_SOURCE 0 #define CLOCK_PLL_SOURCE 0
#define CLOCK_DISABLE_HSI 0 #define CLOCK_DISABLE_HSI 0
#if (CLOCK_PLL_DIV != 1) #if (CLOCK_USE_PLL == 0)
#error "HSI clock cannot be divided" #define CLOCK_CFGR_SW RCC_CFGR_SW_HSI
#define CLOCK_CFGR_SW_RDY RCC_CFGR_SWS_HSI
#elif (CLOCK_PLL_DIV != 2)
#error "CLOCK_PLL_DIV can only be 2 for the HSI"
#endif #endif
#elif CLOCK_HSE #elif CLOCK_HSE
...@@ -46,11 +61,14 @@ ...@@ -46,11 +61,14 @@
#define CLOCK_PLL_SOURCE RCC_CFGR_PLLSRC #define CLOCK_PLL_SOURCE RCC_CFGR_PLLSRC
#define CLOCK_DISABLE_HSI 1 #define CLOCK_DISABLE_HSI 1
#if (CLOCK_PLL_DIV == 2) #if (CLOCK_USE_PLL == 0)
#define CLOCK_CFGR_SW RCC_CFGR_SW_HSE
#define CLOCK_CFGR_SW_RDY RCC_CFGR_SWS_HSE
#elif (CLOCK_PLL_DIV == 2)
#define CLOCK_PLL_DIVMSK RCC_CFGR_PLLXTPRE #define CLOCK_PLL_DIVMSK RCC_CFGR_PLLXTPRE
#elif (CLOCK_PLL_DIV == 1) #elif (CLOCK_PLL_DIV == 1)
#define CLOCK_PLL_DIVMSK 0 #define CLOCK_PLL_DIVMSK 0
#else #elif defined(CLOCK_PLL_DIV)
#error "HSE divider must be 1 or 2" #error "HSE divider must be 1 or 2"
#endif #endif
...@@ -58,11 +76,15 @@ ...@@ -58,11 +76,15 @@
#error "Please provide CLOCK_HSI or CLOCK_HSE in boards/NAME/includes/perhip_cpu.h" #error "Please provide CLOCK_HSI or CLOCK_HSE in boards/NAME/includes/perhip_cpu.h"
#endif #endif
#if (CLOCK_USE_PLL == 1)
#define CLOCK_CFGR_SW RCC_CFGR_SW_PLL
#define CLOCK_CFGR_SW_RDY RCC_CFGR_SWS_PLL
#if CLOCK_PLL_MUL > 16 #if CLOCK_PLL_MUL > 16
#error "PLL multiplier cannot exceed 16 times" #error "PLL multiplier cannot exceed 16 times"
#elif CLOCK_PLL_MUL < 2 #elif CLOCK_PLL_MUL < 2
#error "PLL multiplier cannot be set to 1 or lower" #error "PLL multiplier cannot be set to 1 or lower"
#endif #endif
#endif
static void clk_init(void); static void clk_init(void);
...@@ -110,18 +132,21 @@ static void clk_init(void) ...@@ -110,18 +132,21 @@ static void clk_init(void)
RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV; RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV;
/* PCLK1 = HCLK */ /* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV; RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV;
#if (CLOCK_USE_PLL == 1)
/* PLL configuration: PLLCLK = CLOCK_SOURCE / PLL_DIV * PLL_MUL */ /* PLL configuration: PLLCLK = CLOCK_SOURCE / PLL_DIV * PLL_MUL */
RCC->CFGR &= ~((uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(CLOCK_PLL_SOURCE | CLOCK_PLL_DIVMSK | ((CLOCK_PLL_MUL - 2) << 18)); RCC->CFGR |= (uint32_t)(CLOCK_PLL_SOURCE | CLOCK_PLL_DIVMSK | ((CLOCK_PLL_MUL - 2) << 18));
/* Enable PLL */ /* Enable PLL */
RCC->CR |= RCC_CR_PLLON; RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */ /* Wait till PLL is ready */
while ((RCC->CR & RCC_CR_PLLRDY) == 0) {} while ((RCC->CR & RCC_CR_PLLRDY) == 0) {}
/* Select PLL as system clock source */ #endif
/* Select the system clock source */
RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW)); RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; RCC->CFGR |= (uint32_t)CLOCK_CFGR_SW;
/* Wait till PLL is used as system clock source */ /* Wait till selected system clock source is ready */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != CLOCK_CFGR_SW_RDY) {}
#if CLOCK_DISABLE_HSI #if CLOCK_DISABLE_HSI
RCC->CR &= ~(RCC_CR_HSION); RCC->CR &= ~(RCC_CR_HSION);
......
/* /*
* Copyright (C) 2013 INRIA * Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2014 Freie Universität Berlin
* *
* This file is subject to the terms and conditions of the GNU Lesser General * This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more * Public License v2.1. See the file LICENSE in the top level directory for more
...@@ -12,45 +11,88 @@ ...@@ -12,45 +11,88 @@
* @{ * @{
* *
* @file * @file
* @brief Implementation of the kernel's lpm interface * @brief Implementation of the kernels power management interface
* *
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr> * @author Nick v. IJzendoorn <nijzndoorn@engineering-spirit.nl>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* *
* @} * @}
*/ */
#include "cpu.h"
#include "arch/lpm_arch.h" #include "arch/lpm_arch.h"
static enum lpm_mode current_mode = LPM_UNKNOWN;
void lpm_arch_init(void) void lpm_arch_init(void)
{ {
/* TODO */ current_mode = LPM_ON;
} }
enum lpm_mode lpm_arch_set(enum lpm_mode target) enum lpm_mode lpm_arch_set(enum lpm_mode target)
{ {
(void) target; enum lpm_mode last_mode = current_mode;
/* TODO */
return 0; switch (target) {
case LPM_ON: /* STM Run mode */
current_mode = LPM_ON;
break;
case LPM_IDLE: /* STM Sleep mode */
current_mode = LPM_IDLE;
/* Reset SLEEPDEEP bit of system control block */
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
/* Enter sleep mode */
__WFI();
break;
case LPM_SLEEP: /* STM Stop mode */
current_mode = LPM_SLEEP;
/* Clear PDDS and LPDS bits to enter stop mode on */
/* deepsleep with voltage regulator on */
PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* Enter stop mode */
__WFI();
break;
case LPM_POWERDOWN: /* STM Standby mode */
/* Fall-through */
case LPM_OFF: /* STM Standby mode */
current_mode = LPM_POWERDOWN;
/* Set PDDS to enter standby mode on deepsleep and clear flags */
PWR->CR |= (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF);
/* Enable WKUP pin to use for wakeup from standby mode */
PWR->CSR |= PWR_CSR_EWUP;
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
#if defined ( __CC_ARM )
/* Ensure that store operations are completed */
__force_stores();
#endif
/* Enter standby mode */
__WFI();
break;
default:
break;
}
return last_mode;
} }
enum lpm_mode lpm_arch_get(void) enum lpm_mode lpm_arch_get(void)
{ {
/* TODO */ return current_mode;
return 0;
} }
void lpm_arch_awake(void) void lpm_arch_awake(void)
{ {
/* TODO */ if (current_mode == LPM_SLEEP) {
/* After stop mode, the clock system needs to be reconfigured */
cpu_init();
}
current_mode = LPM_ON;
} }
void lpm_arch_begin_awake(void) /** Not provided */
{ inline void lpm_arch_begin_awake(void) { }
/* TODO */
}
void lpm_arch_end_awake(void) /** Not provided */
{ inline void lpm_arch_end_awake(void) { }
/* TODO */
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment