mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 10:03:50 +01:00
Merge pull request #6110 from lebrush/stm32f1-no-pll
cpu/stm32f1: implement lpm + run without PLL
This commit is contained in:
commit
0d628b6dc3
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2013 INRIA
|
||||
* 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
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
@ -19,6 +20,7 @@
|
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
||||
* @author Víctor Ariño <victor.arino@zii.aero>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -26,9 +28,19 @@
|
||||
#include "cpu.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)
|
||||
#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
|
||||
#define CLOCK_CR_SOURCE RCC_CR_HSION
|
||||
#define CLOCK_CR_SOURCE_RDY RCC_CR_HSIRDY
|
||||
@ -36,8 +48,11 @@
|
||||
#define CLOCK_PLL_SOURCE 0
|
||||
#define CLOCK_DISABLE_HSI 0
|
||||
|
||||
#if (CLOCK_PLL_DIV != 1)
|
||||
#error "HSI clock cannot be divided"
|
||||
#if (CLOCK_USE_PLL == 0)
|
||||
#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
|
||||
|
||||
#elif CLOCK_HSE
|
||||
@ -46,11 +61,14 @@
|
||||
#define CLOCK_PLL_SOURCE RCC_CFGR_PLLSRC
|
||||
#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
|
||||
#elif (CLOCK_PLL_DIV == 1)
|
||||
#define CLOCK_PLL_DIVMSK 0
|
||||
#else
|
||||
#elif defined(CLOCK_PLL_DIV)
|
||||
#error "HSE divider must be 1 or 2"
|
||||
#endif
|
||||
|
||||
@ -58,11 +76,15 @@
|
||||
#error "Please provide CLOCK_HSI or CLOCK_HSE in boards/NAME/includes/perhip_cpu.h"
|
||||
#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
|
||||
#error "PLL multiplier cannot exceed 16 times"
|
||||
#elif CLOCK_PLL_MUL < 2
|
||||
#error "PLL multiplier cannot be set to 1 or lower"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void clk_init(void);
|
||||
|
||||
@ -110,18 +132,21 @@ static void clk_init(void)
|
||||
RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV;
|
||||
|
||||
#if (CLOCK_USE_PLL == 1)
|
||||
/* 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));
|
||||
/* 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 */
|
||||
#endif
|
||||
|
||||
/* Select the system clock source */
|
||||
RCC->CFGR &= ~((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) != RCC_CFGR_SWS_PLL) {}
|
||||
RCC->CFGR |= (uint32_t)CLOCK_CFGR_SW;
|
||||
/* Wait till selected system clock source is ready */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != CLOCK_CFGR_SW_RDY) {}
|
||||
|
||||
#if CLOCK_DISABLE_HSI
|
||||
RCC->CR &= ~(RCC_CR_HSION);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 INRIA
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
* Copyright (C) 2015 Engineering-Spirit
|
||||
*
|
||||
* 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
|
||||
@ -12,45 +11,88 @@
|
||||
* @{
|
||||
*
|
||||
* @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 Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Nick v. IJzendoorn <nijzndoorn@engineering-spirit.nl>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "arch/lpm_arch.h"
|
||||
|
||||
static enum lpm_mode current_mode = LPM_UNKNOWN;
|
||||
|
||||
void lpm_arch_init(void)
|
||||
{
|
||||
/* TODO */
|
||||
current_mode = LPM_ON;
|
||||
}
|
||||
|
||||
enum lpm_mode lpm_arch_set(enum lpm_mode target)
|
||||
{
|
||||
(void) target;
|
||||
/* TODO */
|
||||
return 0;
|
||||
enum lpm_mode last_mode = current_mode;
|
||||
|
||||
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)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
return current_mode;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
/** Not provided */
|
||||
inline void lpm_arch_begin_awake(void) { }
|
||||
|
||||
void lpm_arch_end_awake(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
/** Not provided */
|
||||
inline void lpm_arch_end_awake(void) { }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user