mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
Merge #19202
19202: cpu/gd32v: add periph_rtt support r=benpicco a=gschorcht ### Contribution description This PR provides the `periph_rtt` support and is one of a bunch of PRs that complete the peripheral drivers for GD32VF103. ### Testing procedure `tests/periph_rtt` should work and give the following results: ``` Help: Press s to start test, r to print it is ready START main(): This is RIOT! (Version: 2023.04-devel-199-g2d429-cpu/gd32v/periph_rtt) RIOT RTT low-level driver test RTT configuration: RTT_MAX_VALUE: 0xffffffff RTT_FREQUENCY: 32768 Testing the tick conversion Trying to convert 1 to seconds and back Trying to convert 256 to seconds and back Trying to convert 65536 to seconds and back Trying to convert 16777216 to seconds and back Trying to convert 2147483648 to seconds and back All ok Initializing the RTT driver This test will now display 'Hello' every 5 seconds RTT now: 148 Setting initial alarm to now + 5 s (163988) rtt_get_alarm() PASSED Done setting up the RTT, wait for many Hellos { "threads": [{ "name": "idle", "stack_size": 256, "stack_used": 216 }]} { "threads": [{ "name": "main", "stack_size": 1280, "stack_used": 480 }]} Hello Hello Hello Hello ``` ### Issues/PRs references Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
31fe47c82c
@ -19,11 +19,7 @@
|
||||
#ifndef PERIPH_CONF_H
|
||||
#define PERIPH_CONF_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "periph_common_conf.h"
|
||||
|
||||
#include "cfg_timer_default.h"
|
||||
#include "cfg_uart_default.h"
|
||||
#include "macros/units.h"
|
||||
|
||||
#ifndef CONFIG_BOARD_HAS_HXTAL
|
||||
#define CONFIG_BOARD_HAS_HXTAL 1 /**< The board provides a high frequency oscillator. */
|
||||
@ -37,6 +33,12 @@
|
||||
#define CONFIG_CLOCK_HXTAL MHZ(8) /**< HXTAL frequency */
|
||||
#endif
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "periph_common_conf.h"
|
||||
|
||||
#include "cfg_timer_default.h"
|
||||
#include "cfg_uart_default.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -19,11 +19,7 @@
|
||||
#ifndef PERIPH_CONF_H
|
||||
#define PERIPH_CONF_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "periph_common_conf.h"
|
||||
|
||||
#include "cfg_timer_default.h"
|
||||
#include "cfg_uart_default.h"
|
||||
#include "macros/units.h"
|
||||
|
||||
#ifndef CONFIG_BOARD_HAS_HXTAL
|
||||
#define CONFIG_BOARD_HAS_HXTAL 1 /**< The board provides a high frequency oscillator. */
|
||||
@ -37,6 +33,12 @@
|
||||
#define CONFIG_CLOCK_HXTAL MHZ(8) /**< HXTAL frequency */
|
||||
#endif
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "periph_common_conf.h"
|
||||
|
||||
#include "cfg_timer_default.h"
|
||||
#include "cfg_uart_default.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@ config CPU_FAM_GD32V
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_PM
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_RTT
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_TIMER_PERIODIC
|
||||
select HAS_PERIPH_WDT
|
||||
|
@ -5,6 +5,7 @@ FEATURES_PROVIDED += periph_clic
|
||||
FEATURES_PROVIDED += periph_gpio
|
||||
FEATURES_PROVIDED += periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_timer_periodic
|
||||
FEATURES_PROVIDED += periph_wdt
|
||||
|
@ -276,12 +276,20 @@ typedef struct {
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define RTT_INTR_PRIORITY (2)
|
||||
#define RTT_DEV RTC /**< RTC is used as RTT device */
|
||||
|
||||
#define RTT_IRQ RTC_ALARM_IRQn /**< RTC_ALARM_IRQn is used as IRQ number */
|
||||
#define RTT_IRQ_PRIORITY (2) /**< RTT interrupt priority */
|
||||
|
||||
#if CONFIG_BOARD_HAS_LXTAL
|
||||
#define RTT_CLOCK_FREQUENCY (32768U) /**< Low frequency XTAL is used as clock source */
|
||||
#else
|
||||
#define RTT_CLOCK_FREQUENCY (40000U) /**< IRC40K is used as clock source */
|
||||
#endif
|
||||
|
||||
#define RTT_MAX_VALUE (0xffffffff)
|
||||
#define RTT_CLOCK_FREQUENCY (32768U) /* in Hz */
|
||||
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
||||
#define RTT_MIN_FREQUENCY (1U) /* in Hz */
|
||||
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
||||
#define RTT_MAX_VALUE (0xffffffff)
|
||||
|
||||
#ifndef RTT_FREQUENCY
|
||||
#define RTT_FREQUENCY (RTT_MAX_FREQUENCY) /* in Hz */
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32
|
||||
* @ingroup cpu_gd32v
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
|
267
cpu/gd32v/periph/rtt.c
Normal file
267
cpu/gd32v/periph/rtt.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
* 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_gd32v
|
||||
* @ingroup drivers_periph_rtt
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level RTT driver implementation for STM32F1
|
||||
*
|
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph/rtt.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define EXTI_RTC_BIT (1UL << 17)
|
||||
|
||||
#define RTT_PRESCALER ((RTT_CLOCK_FREQUENCY / RTT_FREQUENCY) - 1 )
|
||||
|
||||
static inline void _rtt_enter_config_mode(void);
|
||||
static inline void _rtt_leave_config_mode(void);
|
||||
static void isr_rtc(unsigned irqn);
|
||||
|
||||
static rtt_cb_t alarm_cb;
|
||||
static void *alarm_arg;
|
||||
|
||||
static rtt_cb_t overflow_cb;
|
||||
static void *overflow_arg;
|
||||
|
||||
void rtt_init(void)
|
||||
{
|
||||
/* enable backup domain clock */
|
||||
periph_clk_en(APB1, RCU_APB1EN_BKPIEN_Msk);
|
||||
|
||||
/* enable write access to backup domain registers */
|
||||
PMU->CTL |= PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
/* reset the entire backup domain */
|
||||
RCU->BDCTL |= RCU_BDCTL_BKPRST_Msk;
|
||||
RCU->BDCTL &= ~RCU_BDCTL_BKPRST_Msk;
|
||||
|
||||
rtt_poweron();
|
||||
|
||||
/* clear RSYN flag */
|
||||
RTT_DEV->CTL &= ~(RTC_CTL_RSYNF_Msk);
|
||||
while ((RTC->CTL & RTC_CTL_RSYNF_Msk) != RTC_CTL_RSYNF_Msk) { }
|
||||
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* reset RTC counter */
|
||||
RTT_DEV->CNTH = 0x0000;
|
||||
RTT_DEV->CNTL = 0x0000;
|
||||
|
||||
/* set prescaler */
|
||||
RTT_DEV->PSCH = (RTT_PRESCALER >> 16) & 0x000f;
|
||||
RTT_DEV->PSCL = RTT_PRESCALER & 0xffff;
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
|
||||
/* configure the EXTI channel, as RTC interrupts are routed through it.
|
||||
* Needs to be configured to trigger on rising edges. */
|
||||
EXTI->FTEN &= ~(EXTI_RTC_BIT);
|
||||
EXTI->RTEN |= EXTI_RTC_BIT;
|
||||
EXTI->INTEN |= EXTI_RTC_BIT;
|
||||
EXTI->PD |= EXTI_RTC_BIT;
|
||||
|
||||
/* enable global RTC interrupt */
|
||||
clic_set_handler(RTT_IRQ, isr_rtc);
|
||||
clic_enable_interrupt(RTT_IRQ, RTT_IRQ_PRIORITY);
|
||||
}
|
||||
|
||||
void rtt_set_overflow_cb(rtt_cb_t cb, void *arg)
|
||||
{
|
||||
overflow_cb = cb;
|
||||
overflow_arg = arg;
|
||||
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* Enable overflow interrupt */
|
||||
RTT_DEV->INTEN |= RTC_INTEN_OVIE_Msk;
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
}
|
||||
|
||||
void rtt_clear_overflow_cb(void)
|
||||
{
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* Clear overflow interrupt */
|
||||
RTT_DEV->INTEN &= ~(RTC_INTEN_OVIE_Msk);
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
|
||||
overflow_cb = NULL;
|
||||
overflow_arg = NULL;
|
||||
}
|
||||
|
||||
uint32_t rtt_get_counter(void)
|
||||
{
|
||||
/* wait for synchronization */
|
||||
while (!(RTT_DEV->CTL & RTC_CTL_RSYNF_Msk)) { }
|
||||
|
||||
return ((uint32_t)RTT_DEV->CNTH << 16 ) | (uint32_t)(RTT_DEV->CNTL);
|
||||
}
|
||||
|
||||
void rtt_set_counter(uint32_t counter)
|
||||
{
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* Set RTC counter MSB word */
|
||||
RTT_DEV->CNTH = counter >> 16;
|
||||
/* Set RTC counter LSB word */
|
||||
RTT_DEV->CNTL = counter & 0xffff;
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
}
|
||||
|
||||
/* RTC->ALRMH and RTC->ALRML are writable only. Therefore the current alarm
|
||||
* time must be stored separately in a variable for rtt_get_alarm. */
|
||||
static uint32_t _rtt_alarm = 0;
|
||||
|
||||
uint32_t rtt_get_alarm(void)
|
||||
{
|
||||
/* wait for synchronization */
|
||||
while (!(RTT_DEV->CTL & RTC_CTL_RSYNF_Msk)) { }
|
||||
|
||||
return _rtt_alarm;
|
||||
}
|
||||
|
||||
void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
|
||||
{
|
||||
/* save the current alarm time */
|
||||
_rtt_alarm = alarm;
|
||||
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* Disable alarm*/
|
||||
RTT_DEV->INTEN &= ~RTC_INTEN_ALRMIE_Msk;
|
||||
/* Save new cb and argument */
|
||||
alarm_cb = cb;
|
||||
alarm_arg = arg;
|
||||
|
||||
/* Set the alarm MSB word */
|
||||
RTT_DEV->ALRMH = alarm >> 16;
|
||||
/* Set the alarm LSB word */
|
||||
RTT_DEV->ALRML = (alarm & 0xffff);
|
||||
|
||||
/* Enable alarm interrupt */
|
||||
RTT_DEV->INTEN |= RTC_INTEN_ALRMIE_Msk;
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
}
|
||||
|
||||
void rtt_clear_alarm(void)
|
||||
{
|
||||
_rtt_enter_config_mode();
|
||||
|
||||
/* Disable alarm interrupt */
|
||||
RTT_DEV->INTEN &= ~RTC_INTEN_ALRMIE_Msk;
|
||||
/* Set the ALARM MSB word to reset value */
|
||||
RTT_DEV->ALRMH = 0xffff;
|
||||
/* Set the ALARM LSB word to reset value */
|
||||
RTT_DEV->ALRML = 0xffff;
|
||||
|
||||
_rtt_leave_config_mode();
|
||||
}
|
||||
|
||||
#define RCU_BDCTL_RTCSRC_CK_LXTAL 1
|
||||
#define RCU_BDCTL_RTCSRC_CK_IRC40K 2
|
||||
|
||||
void rtt_poweron(void)
|
||||
{
|
||||
/* enable backup domain clock */
|
||||
periph_clk_en(APB1, RCU_APB1EN_BKPIEN_Msk);
|
||||
|
||||
/* enable write access to backup domain registers */
|
||||
PMU->CTL |= PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
#if CONFIG_BOARD_HAS_LXTAL
|
||||
/* oscillator clock used as RTC clock */
|
||||
RCU->BDCTL |= RCU_BDCTL_RTCSRC_CK_LXTAL << RCU_BDCTL_RTCSRC_Pos;
|
||||
RCU->BDCTL |= RCU_BDCTL_LXTALEN_Msk;
|
||||
while ((RCU->BDCTL & RCU_BDCTL_LXTALSTB_Msk) != RCU_BDCTL_LXTALSTB_Msk) { }
|
||||
#else
|
||||
RCU->BDCTL |= RCU_BDCTL_RTCSRC_CK_IRC40K << RCU_BDCTL_RTCSRC_Pos;
|
||||
#endif
|
||||
|
||||
/* enable RTC clock */
|
||||
RCU->BDCTL |= RCU_BDCTL_RTCEN_Msk;
|
||||
|
||||
/* disable write access to backup domain registers */
|
||||
PMU->CTL &= ~PMU_CTL_BKPWEN_Msk;
|
||||
}
|
||||
|
||||
void rtt_poweroff(void)
|
||||
{
|
||||
/* enable write access to backup domain registers */
|
||||
PMU->CTL |= PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
/* enable RTC clock */
|
||||
RCU->BDCTL &= ~RCU_BDCTL_RTCEN_Msk;
|
||||
|
||||
/* disable write access to backup domain registers */
|
||||
PMU->CTL &= ~PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
/* disable backup domain clock */
|
||||
periph_clk_dis(APB1, RCU_APB1EN_BKPIEN_Msk);
|
||||
}
|
||||
|
||||
static inline void _rtt_enter_config_mode(void)
|
||||
{
|
||||
/* enable write access to backup domain registers */
|
||||
PMU->CTL |= PMU_CTL_BKPWEN_Msk;
|
||||
|
||||
/* wait until the LWOFF bit is 1 (Last write operation finished). */
|
||||
while ((RTC->CTL & RTC_CTL_LWOFF_Msk) == 0) { }
|
||||
|
||||
/* enter configuration mode. */
|
||||
RTC->CTL |= RTC_CTL_CMF_Msk;
|
||||
}
|
||||
|
||||
static inline void _rtt_leave_config_mode(void)
|
||||
{
|
||||
/* exit configuration mode. */
|
||||
RTC->CTL &= ~RTC_CTL_CMF_Msk;
|
||||
|
||||
/* wait until the LWOFF bit is 1 (Last write operation finished). */
|
||||
while ((RTC->CTL & RTC_CTL_LWOFF_Msk) == 0) { }
|
||||
|
||||
/* disable write access to backup domain registers */
|
||||
PMU->CTL &= ~PMU_CTL_BKPWEN_Msk;
|
||||
}
|
||||
|
||||
static void isr_rtc(unsigned irqn)
|
||||
{
|
||||
(void)irqn;
|
||||
|
||||
if (RTT_DEV->CTL & RTC_CTL_ALRMIF_Msk) {
|
||||
RTT_DEV->CTL &= ~(RTC_CTL_ALRMIF_Msk);
|
||||
if (alarm_cb) {
|
||||
alarm_cb(alarm_arg);
|
||||
}
|
||||
}
|
||||
if (RTT_DEV->CTL & RTC_CTL_OVIF_Msk) {
|
||||
RTT_DEV->CTL &= ~(RTC_CTL_OVIF_Msk);
|
||||
if (overflow_cb) {
|
||||
overflow_cb(overflow_arg);
|
||||
}
|
||||
}
|
||||
|
||||
EXTI->PD |= EXTI_RTC_BIT;
|
||||
}
|
Loading…
Reference in New Issue
Block a user