/* * Copyright (C) 2014-2017 Freie Universität Berlin * 2015 Jan Wagner * * 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_nrf5x_common * @ingroup drivers_periph_rtt * @{ * * @file * @brief RTT implementation for NRF5x CPUs * * @author Hauke Petersen * @author Jan Wagner * * @} */ #include "cpu.h" #include "nrf_clock.h" #include "periph/rtt.h" /* get the IRQ configuration */ #if (RTT_DEV == 1) #define DEV NRF_RTC1 #define ISR isr_rtc1 #define IRQn RTC1_IRQn #elif (RTT_DEV == 2) #define DEV NRF_RTC2 #define ISR isr_rtc2 #define IRQn RTC2_IRQn #else #error "RTT configuration: invalid or no RTC device specified (RTT_DEV)" #endif #define LFCLK_FREQ (32768U) /* allocate memory for callbacks and their args */ 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 the low-frequency clock */ clock_start_lf(); /* make sure device is powered */ #ifdef CPU_FAM_NRF51 DEV->POWER = 1; #endif /* stop the RTT during configuration */ DEV->TASKS_STOP = 1; /* configure interrupt */ NVIC_EnableIRQ(IRQn); /* set prescaler */ DEV->PRESCALER = (LFCLK_FREQ / RTT_FREQUENCY) - 1; /* start the actual RTT thing */ DEV->TASKS_START = 1; } void rtt_set_overflow_cb(rtt_cb_t cb, void *arg) { overflow_cb = cb; overflow_arg = arg; DEV->INTENSET = RTC_INTENSET_OVRFLW_Msk; } void rtt_clear_overflow_cb(void) { DEV->INTENCLR = RTC_INTENCLR_OVRFLW_Msk; } uint32_t rtt_get_counter(void) { return DEV->COUNTER; } void rtt_set_counter(uint32_t counter) { (void) counter; /* not supported by the nRF5x */ } void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg) { alarm_cb = cb; alarm_arg = arg; DEV->CC[0] = (alarm & RTT_MAX_VALUE); DEV->INTENSET = RTC_INTENSET_COMPARE0_Msk; } uint32_t rtt_get_alarm(void) { return DEV->CC[0]; } void rtt_clear_alarm(void) { DEV->INTENCLR = RTC_INTENSET_COMPARE0_Msk; } void rtt_poweron(void) { #ifdef CPU_FAM_NRF51 DEV->POWER = 1; #endif DEV->TASKS_START = 1; } void rtt_poweroff(void) { DEV->TASKS_STOP = 1; #ifdef CPU_FAM_NRF51 DEV->POWER = 0; #endif } void ISR(void) { if (DEV->EVENTS_COMPARE[0] == 1) { DEV->EVENTS_COMPARE[0] = 0; DEV->INTENCLR = RTC_INTENSET_COMPARE0_Msk; alarm_cb(alarm_arg); } if (DEV->EVENTS_OVRFLW == 1) { DEV->EVENTS_OVRFLW = 0; overflow_cb(overflow_arg); } cortexm_isr_end(); }