Browse Source

Merge pull request #6834 from haukepetersen/add_stm32l_rtt

cpu/stm32_common: added LPTIM based rtt implementation
pr/rotary
Alexandre Abadie 6 years ago committed by GitHub
parent
commit
6529abd687
  1. 1
      boards/nucleo-l476/Makefile.features
  2. 11
      boards/nucleo-l476/include/periph_conf.h
  3. 158
      cpu/stm32_common/periph/rtt_lptim.c
  4. 2
      cpu/stm32l4/include/cpu_conf.h

1
boards/nucleo-l476/Makefile.features

@ -5,6 +5,7 @@ FEATURES_PROVIDED += periph_hwrng
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_rtt
FEATURES_PROVIDED += periph_uart
# load the common Makefile.features for Nucleo boards

11
boards/nucleo-l476/include/periph_conf.h

@ -234,6 +234,17 @@ static const spi_conf_t spi_config[] = {
#define DAC_NUMOF (0)
/** @} */
/**
* @name RTT configuration
*
* On the STM32Lx platforms, we always utilize the LPTIM1.
* @{
*/
#define RTT_NUMOF (1)
#define RTT_FREQUENCY (1024U) /* 32768 / 2^n */
#define RTT_MAX_VALUE (0x0000ffff) /* 16-bit timer */
/** @} */
#ifdef __cplusplus
}
#endif

158
cpu/stm32_common/periph/rtt_lptim.c

@ -0,0 +1,158 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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 details.
*/
/**
* @ingroup cpu_stm32_common
* @{
*
* @file
* @brief RTT implementation using LPTIM1
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "cpu.h"
#include "irq.h"
#include "periph/rtt.h"
/* this driver is only valid for STM CPUs that provide LPTIMERs */
#if (defined(LPTIM1) && RTT_NUMOF)
/* figure out the used pre-scaler */
#if (RTT_FREQUENCY == 32768)
#define PRE (0)
#elif (RTT_FREQUENCY == 16384)
#define PRE (LPTIM_CFGR_PRESC_0)
#elif (RTT_FREQUENCY == 8192)
#define PRE (LPTIM_CFGR_PRESC_1)
#elif (RTT_FREQUENCY == 4096)
#define PRE (LPTIM_CFGR_PRESC_1 | LPTIM_CFGR_PRESC_0)
#elif (RTT_FREQUENCY == 2048)
#define PRE (LPTIM_CFGR_PRESC_2)
#elif (RTT_FREQUENCY == 1024)
#define PRE (LPTIM_CFGR_PRESC_2 | LPTIM_CFGR_PRESC_0)
#elif (RTT_FREQUENCY == 512)
#define PRE (LPTIM_CFGR_PRESC_2 | LPTIM_CFGR_PRESC_1)
#elif (RTT_FREQUENCY == 256)
#define PRE (LPTIM_CFGR_PRESC)
#else
#error "RTT config: RTT_FREQUENCY not configured or invalid for your board"
#endif
/* allocate memory for overflow and alarm callbacks + args */
static rtt_cb_t ovf_cb = NULL;
static void *ovf_arg;
static rtt_cb_t to_cb = NULL;
static void *to_arg;
void rtt_init(void)
{
/* power on the selected LPTIMER */
rtt_poweron();
/* stop the timer and reset configuration */
LPTIM1->CR = 0;
/* select low speed clock (LSI or LSE) */
RCC->CCIPR &= ~(RCC_CCIPR_LPTIM1SEL);
#if CLOCK_LSE
RCC->CCIPR |= (RCC_CCIPR_LPTIM1SEL_1 | RCC_CCIPR_LPTIM1SEL_0);
#else
RCC->CCIPR |= (RCC_CCIPR_LPTIM1SEL_0);
#endif
/* set configuration: prescale factor and external clock (LSI or LSE) */
LPTIM1->CFGR = PRE;
/* enable overflow and compare interrupts */
LPTIM1->IER = (LPTIM_IER_ARRMIE | LPTIM_IER_CMPMIE);
NVIC_EnableIRQ(LPTIM1_IRQn);
/* enable timer */
LPTIM1->CR = LPTIM_CR_ENABLE;
/* set auto-reload value (timer needs to be enabled for this) */
LPTIM1->ARR = RTT_MAX_VALUE;
/* start the timer */
LPTIM1->CR |= LPTIM_CR_CNTSTRT;
}
uint32_t rtt_get_counter(void)
{
return (uint32_t)LPTIM1->CNT;
}
void rtt_set_overflow_cb(rtt_cb_t cb, void *arg)
{
assert(cb);
unsigned is = irq_disable();
ovf_cb = cb;
ovf_arg = arg;
irq_restore(is);
}
void rtt_clear_overflow_cb(void)
{
ovf_cb = NULL;
}
void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
{
assert(cb && !(alarm & ~RTT_MAX_VALUE));
unsigned is = irq_disable();
to_cb = cb;
to_arg = arg;
LPTIM1->CMP = (uint16_t)alarm;
irq_restore(is);
}
void rtt_clear_alarm(void)
{
to_cb = NULL;
}
void rtt_poweron(void)
{
#ifdef RCC_APB1ENR1_LPTIM1EN
periph_clk_en(APB1, RCC_APB1ENR1_LPTIM1EN);
#else
periph_clk_en(APB1, RCC_APB1ENR_LPTIM1EN);
#endif
}
void rtt_poweroff(void)
{
#ifdef RCC_APB1ENR1_LPTIM1EN
periph_clk_dis(APB1, RCC_APB1ENR1_LPTIM1EN);
#else
periph_clk_dis(APB1, RCC_APB1ENR_LPTIM1EN);
#endif
}
void isr_lptim1(void)
{
if (LPTIM1->ISR & LPTIM_ISR_CMPM) {
if (to_cb) {
/* 'consume' the callback (as it might be set again in the cb) */
rtt_cb_t tmp = to_cb;
to_cb = NULL;
tmp(to_arg);
}
}
if (LPTIM1->ISR & LPTIM_ISR_ARRM) {
if (ovf_cb) {
ovf_cb(ovf_arg);
}
}
LPTIM1->ICR = (LPTIM_ICR_ARRMCF | LPTIM_ICR_CMPMCF);
cortexm_isr_end();
}
#endif /* LPTIM1 */

2
cpu/stm32l4/include/cpu_conf.h

@ -36,7 +36,7 @@ extern "C" {
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
#define CPU_IRQ_NUMOF (82U)
#define CPU_IRQ_NUMOF (81U)
/** @} */
#ifdef __cplusplus

Loading…
Cancel
Save