From e3e89fe51321a74a5e3b8732fd26e6c31922b158 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 30 Nov 2020 17:26:02 +0100 Subject: [PATCH] cpu/nrf5x: implement periph_timer_periodic --- cpu/nrf5x_common/Kconfig | 1 + cpu/nrf5x_common/Makefile.features | 1 + cpu/nrf5x_common/periph/timer.c | 33 ++++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/cpu/nrf5x_common/Kconfig b/cpu/nrf5x_common/Kconfig index e77265eae6..5f0812254e 100644 --- a/cpu/nrf5x_common/Kconfig +++ b/cpu/nrf5x_common/Kconfig @@ -13,6 +13,7 @@ config CPU_COMMON_NRF5X select HAS_PERIPH_GPIO_IRQ select HAS_PERIPH_HWRNG select HAS_PERIPH_TEMPERATURE + select HAS_PERIPH_TIMER_PERIODIC select HAS_PERIPH_UART_MODECFG select HAS_PERIPH_WDT select HAS_PERIPH_WDT_CB diff --git a/cpu/nrf5x_common/Makefile.features b/cpu/nrf5x_common/Makefile.features index 5bcd257807..30f8cf3aa7 100644 --- a/cpu/nrf5x_common/Makefile.features +++ b/cpu/nrf5x_common/Makefile.features @@ -5,6 +5,7 @@ FEATURES_PROVIDED += periph_flashpage_pagewise FEATURES_PROVIDED += periph_gpio periph_gpio_irq FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += periph_temperature +FEATURES_PROVIDED += periph_timer_periodic FEATURES_PROVIDED += periph_uart_modecfg FEATURES_PROVIDED += periph_wdt periph_wdt_cb diff --git a/cpu/nrf5x_common/periph/timer.c b/cpu/nrf5x_common/periph/timer.c index 26499fc4ee..b0ca580a0c 100644 --- a/cpu/nrf5x_common/periph/timer.c +++ b/cpu/nrf5x_common/periph/timer.c @@ -31,6 +31,7 @@ typedef struct { timer_cb_t cb; void *arg; uint8_t flags; + uint8_t is_periodic; } tim_ctx_t; /** @@ -106,6 +107,29 @@ int timer_set_absolute(tim_t tim, int chan, unsigned int value) return 0; } +int timer_set_periodic(tim_t tim, int chan, unsigned int value, uint8_t flags) +{ + /* see if channel is valid */ + if (chan >= timer_config[tim].channels) { + return -1; + } + + ctx[tim].flags |= (1 << chan); + ctx[tim].is_periodic |= (1 << chan); + dev(tim)->CC[chan] = value; + if (flags & TIM_FLAG_RESET_ON_MATCH) { + dev(tim)->SHORTS |= (1 << chan); + } + if (flags & TIM_FLAG_RESET_ON_SET) { + dev(tim)->TASKS_CLEAR = 1; + } + dev(tim)->INTENSET = (TIMER_INTENSET_COMPARE0_Msk << chan); + + dev(tim)->TASKS_START = 1; + + return 0; +} + int timer_clear(tim_t tim, int chan) { /* see if channel is valid */ @@ -114,7 +138,10 @@ int timer_clear(tim_t tim, int chan) } dev(tim)->INTENCLR = (TIMER_INTENSET_COMPARE0_Msk << chan); + /* Clear out the Compare->Clear flag of this channel */ + dev(tim)->SHORTS &= ~(1 << chan); ctx[tim].flags &= ~(1 << chan); + ctx[tim].is_periodic &= ~(1 << chan); return 0; } @@ -141,8 +168,10 @@ static inline void irq_handler(int num) if (dev(num)->EVENTS_COMPARE[i] == 1) { dev(num)->EVENTS_COMPARE[i] = 0; if (ctx[num].flags & (1 << i)) { - ctx[num].flags &= ~(1 << i); - dev(num)->INTENCLR = (TIMER_INTENSET_COMPARE0_Msk << i); + if ((ctx[num].is_periodic & (1 << i)) == 0) { + ctx[num].flags &= ~(1 << i); + dev(num)->INTENCLR = (TIMER_INTENSET_COMPARE0_Msk << i); + } ctx[num].cb(ctx[num].arg, i); } }