diff --git a/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.defconfig.series b/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.defconfig.series index ae00b03a66a..e1294f038f4 100644 --- a/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.defconfig.series +++ b/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.defconfig.series @@ -26,6 +26,9 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC int default 32768 +config SYS_POWER_MANAGEMENT + default y + config SRAM_BASE_ADDRESS default 0x20000000 diff --git a/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.series b/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.series index c05594f2d67..c601c434ea6 100644 --- a/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.series +++ b/arch/arm/soc/nordic_nrf5/nrf51/Kconfig.series @@ -24,6 +24,5 @@ config SOC_SERIES_NRF51X select XIP select HAS_CMSIS select HAS_NORDIC_MDK - select CPU_HAS_SYSTICK help Enable support for NRF51 MCU series diff --git a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52832 b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52832 index 2c18a1c7c2c..90e7a193d84 100644 --- a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52832 +++ b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52832 @@ -22,19 +22,11 @@ config SOC string default nRF52832 -config SYS_CLOCK_HW_CYCLES_PER_SEC - int - default 64000000 - config SRAM_SIZE default 64 config FLASH_SIZE default 512 -config NUM_IRQS - int - default 39 - endif # SOC_NRF52832 diff --git a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.series b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.series index bc1eae6f4b7..b5e458d770d 100644 --- a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.series +++ b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.series @@ -22,12 +22,23 @@ source "arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52*" config SOC_SERIES default nrf52 +config SYS_CLOCK_HW_CYCLES_PER_SEC + int + default 32768 + +config SYS_POWER_MANAGEMENT + default y + config SRAM_BASE_ADDRESS default 0x20000000 config FLASH_BASE_ADDRESS default 0x00000000 +config NUM_IRQS + int + default 39 + config NUM_IRQ_PRIO_BITS int default 3 diff --git a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.series b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.series index 54b0aa82a73..a024bd914d1 100644 --- a/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.series +++ b/arch/arm/soc/nordic_nrf5/nrf52/Kconfig.series @@ -24,6 +24,5 @@ config SOC_SERIES_NRF52X select XIP select HAS_CMSIS select HAS_NORDIC_MDK - select CPU_HAS_SYSTICK help Enable support for NRF52 MCU series diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 0bb279fd474..b99e35948e5 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -149,6 +149,16 @@ config ALTERA_AVALON_TIMER with Nios II and possibly other Altera soft CPUs. It provides the standard "system clock driver" interfaces. +config NRF_RTC_TIMER + bool "nRF Real Time Counter (NRF_RTC1) Timer" + default y + depends on SOC_FAMILY_NRF5 + select NANOKERNEL_TICKLESS_IDLE_SUPPORTED + help + This module implements a kernel device driver for the nRF Real Time + Counter NRF_RTC1 and provides the standard "system clock driver" + interfaces. + config SYSTEM_CLOCK_DISABLE bool "API to disable system clock" default n diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 205407c572f..6ffe5c7bd8b 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_LOAPIC_TIMER) += loapic_timer.o obj-$(CONFIG_ARCV2_TIMER) += arcv2_timer0.o obj-$(CONFIG_ALTERA_AVALON_TIMER) += altera_avalon_timer.o +obj-$(CONFIG_NRF_RTC_TIMER) += nrf_rtc_timer.o _CORTEX_M_SYSTICK_AND_GDB_INFO_yy = y obj-$(CONFIG_CORTEX_M_SYSTICK) += cortex_m_systick.o diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c new file mode 100644 index 00000000000..9557cad5ffd --- /dev/null +++ b/drivers/timer/nrf_rtc_timer.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#define RTC_TICKS ((uint32_t)(((((uint64_t)1000000UL / \ + CONFIG_SYS_CLOCK_TICKS_PER_SEC) * \ + 1000000000UL) / 30517578125UL)) & 0x00FFFFFF) + +extern int64_t _sys_clock_tick_count; + +#ifdef CONFIG_TICKLESS_IDLE +extern int32_t _sys_idle_elapsed_ticks; + +void _timer_idle_enter(int32_t ticks) +{ + /* restrict ticks to max supported by RTC */ + if ((ticks < 0) || (ticks > (0x00FFFFFF / RTC_TICKS))) { + ticks = 0x00FFFFFF / RTC_TICKS; + } + + /* setup next RTC compare event by ticks amount */ + NRF_RTC1->CC[0] = ((_sys_clock_tick_count + ticks) * RTC_TICKS) & + 0x00FFFFFF; + + /* TODO: check if CC is set to stale value */ +} + +void _timer_idle_exit(void) +{ + uint32_t elapsed_ticks; + + /* update with elapsed ticks from h/w */ + elapsed_ticks = ((NRF_RTC1->COUNTER - + (_sys_clock_tick_count * RTC_TICKS)) / + RTC_TICKS) & 0x00FFFFFF; + + /* setup next RTC compare event by 1 tick */ + NRF_RTC1->CC[0] = ((_sys_clock_tick_count + elapsed_ticks + 1) * + RTC_TICKS) & 0x00FFFFFF; + + /* TODO: check if CC is set to stale value */ +} +#endif /* CONFIG_TICKLESS_IDLE */ + +static void rtc1_nrf5_isr(void *arg) +{ + ARG_UNUSED(arg); + + if (NRF_RTC1->EVENTS_COMPARE[0]) { + NRF_RTC1->EVENTS_COMPARE[0] = 0; + +#ifdef CONFIG_TICKLESS_IDLE + /* update with elapsed ticks from h/w */ + _sys_idle_elapsed_ticks = ((NRF_RTC1->COUNTER - + (_sys_clock_tick_count * + RTC_TICKS)) / RTC_TICKS) & + 0x00FFFFFF; +#endif + + /* setup next RTC compare event */ + NRF_RTC1->CC[0] = ((_sys_clock_tick_count + + _sys_idle_elapsed_ticks + 1) * RTC_TICKS) + & 0x00FFFFFF; + + /* TODO: check if CC is set to stale value */ + + _sys_clock_tick_announce(); + } +} + +int _sys_clock_driver_init(struct device *device) +{ + struct device *clock; + int retval; + + ARG_UNUSED(device); + + clock = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME); + if (!clock) { + return -1; + } + + clock_control_on(clock, (void *)CLOCK_CONTROL_NRF5_K32SRC); + + /* TODO: replace with counter driver to access RTC */ + NRF_RTC1->PRESCALER = 0; + NRF_RTC1->CC[0] = RTC_TICKS; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; + + IRQ_CONNECT(NRF5_IRQ_RTC1_IRQn, 1, rtc1_nrf5_isr, 0, 0); + irq_enable(NRF5_IRQ_RTC1_IRQn); + + NRF_RTC1->TASKS_START = 1; + + return retval; +} + +uint32_t sys_cycle_get_32(void) +{ + uint32_t elapsed_cycles; + + elapsed_cycles = (NRF_RTC1->COUNTER - + (_sys_clock_tick_count * RTC_TICKS)) & 0x00FFFFFF; + + return (_sys_clock_tick_count * sys_clock_hw_cycles_per_tick) + + elapsed_cycles; +}