drivers: timer: nRF SoC Series RTC system clock implementation

The nRF5x series SoCs do not implement systick, hence we disable
CORTEX_M_SYSTICK.
Instead, use nRF SoC Series NRF_RTC1 for system clock interfaces.
The kernel system clock interface is implemented using the low
power real time counter NRF_RTC1. NRF_RTC0 is used by the BLE
controller.

In addition, cleanup nRF5x series defconfig to be consistent.

Jira: ZEP-742
Jira: ZEP-1308
Jira: ZEP-1315

Change-id: I0f6cc1836fe0820a65f2cbb02cf5ae7e9eb92e1d
Signed-off-by: Vinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no>
Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Vinayak Chettimada 2016-11-22 17:03:32 +01:00 committed by Anas Nashif
commit a100ada866
8 changed files with 150 additions and 10 deletions

View file

@ -26,6 +26,9 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC
int int
default 32768 default 32768
config SYS_POWER_MANAGEMENT
default y
config SRAM_BASE_ADDRESS config SRAM_BASE_ADDRESS
default 0x20000000 default 0x20000000

View file

@ -24,6 +24,5 @@ config SOC_SERIES_NRF51X
select XIP select XIP
select HAS_CMSIS select HAS_CMSIS
select HAS_NORDIC_MDK select HAS_NORDIC_MDK
select CPU_HAS_SYSTICK
help help
Enable support for NRF51 MCU series Enable support for NRF51 MCU series

View file

@ -22,19 +22,11 @@ config SOC
string string
default nRF52832 default nRF52832
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 64000000
config SRAM_SIZE config SRAM_SIZE
default 64 default 64
config FLASH_SIZE config FLASH_SIZE
default 512 default 512
config NUM_IRQS
int
default 39
endif # SOC_NRF52832 endif # SOC_NRF52832

View file

@ -22,12 +22,23 @@ source "arch/arm/soc/nordic_nrf5/nrf52/Kconfig.defconfig.nrf52*"
config SOC_SERIES config SOC_SERIES
default nrf52 default nrf52
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 32768
config SYS_POWER_MANAGEMENT
default y
config SRAM_BASE_ADDRESS config SRAM_BASE_ADDRESS
default 0x20000000 default 0x20000000
config FLASH_BASE_ADDRESS config FLASH_BASE_ADDRESS
default 0x00000000 default 0x00000000
config NUM_IRQS
int
default 39
config NUM_IRQ_PRIO_BITS config NUM_IRQ_PRIO_BITS
int int
default 3 default 3

View file

@ -24,6 +24,5 @@ config SOC_SERIES_NRF52X
select XIP select XIP
select HAS_CMSIS select HAS_CMSIS
select HAS_NORDIC_MDK select HAS_NORDIC_MDK
select CPU_HAS_SYSTICK
help help
Enable support for NRF52 MCU series Enable support for NRF52 MCU series

View file

@ -149,6 +149,16 @@ config ALTERA_AVALON_TIMER
with Nios II and possibly other Altera soft CPUs. It provides the with Nios II and possibly other Altera soft CPUs. It provides the
standard "system clock driver" interfaces. 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 config SYSTEM_CLOCK_DISABLE
bool "API to disable system clock" bool "API to disable system clock"
default n default n

View file

@ -4,6 +4,7 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_LOAPIC_TIMER) += loapic_timer.o obj-$(CONFIG_LOAPIC_TIMER) += loapic_timer.o
obj-$(CONFIG_ARCV2_TIMER) += arcv2_timer0.o obj-$(CONFIG_ARCV2_TIMER) += arcv2_timer0.o
obj-$(CONFIG_ALTERA_AVALON_TIMER) += altera_avalon_timer.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 _CORTEX_M_SYSTICK_AND_GDB_INFO_yy = y
obj-$(CONFIG_CORTEX_M_SYSTICK) += cortex_m_systick.o obj-$(CONFIG_CORTEX_M_SYSTICK) += cortex_m_systick.o

View file

@ -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 <soc.h>
#include <clock_control.h>
#include <system_timer.h>
#include <drivers/clock_control/nrf5_clock_control.h>
#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;
}