Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion drivers/timer/Kconfig.nrf_grtc
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,20 @@ config NRF_GRTC_TIMER_CLOCK_MANAGEMENT
the GRTC. Usually this is only needed by the processor that is starting
the SYSCOUNTER, but can be shared by multiple processors in the system.

config NRF_GRTC_SLEEP_MINIMUM_LATENCY
config NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY
int
default 1000
depends on NRF_GRTC_SLEEP_ALLOWED
help
The value (in us) ensures that the wakeup event will not fire
too early. In other words, applying SYSCOUNTER sleep state for less than
NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY period makes no sense.

config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE
bool
default y if NRF_GRTC_START_SYSCOUNTER
help
This feature prevents the SYSCOUNTER to sleep when any core is in
active state.

endif # NRF_GRTC_TIMER
94 changes: 25 additions & 69 deletions drivers/timer/nrf_grtc_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@

#define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS
#define EXT_CHAN_COUNT (CHAN_COUNT - 1)
/* The reset value of waketime is 1, which doesn't seem to work.
* It's being looked into, but for the time being use 4.
* Timeout must always be higher than waketime, so setting that to 5.
*/
#define WAKETIME (4)
#define TIMEOUT (WAKETIME + 1)

#ifndef GRTC_SYSCOUNTERL_VALUE_Msk
#define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERL_VALUE_Msk
Expand All @@ -55,9 +49,6 @@

#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)

/* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */
#define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51

#if defined(CONFIG_TEST)
const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE);
#endif
Expand All @@ -78,36 +69,6 @@ static nrfx_grtc_channel_t system_clock_channel_data = {
__ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) && \
((chan) != system_clock_channel_data.channel))

static inline void grtc_active_set(void)
{
#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1)
nrfy_grtc_sys_counter_active_set(NRF_GRTC, true);
while (!nrfy_grtc_sys_conter_ready_check(NRF_GRTC)) {
}
#else
nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, true);
k_busy_wait(GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US);
#endif
}

static inline void grtc_wakeup(void)
{
if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
grtc_active_set();
}
}

static inline void grtc_sleep(void)
{
if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1)
nrfy_grtc_sys_counter_active_set(NRF_GRTC, false);
#else
nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, false);
#endif
}
}

static inline uint64_t counter_sub(uint64_t a, uint64_t b)
{
return (a - b);
Expand All @@ -116,10 +77,7 @@ static inline uint64_t counter_sub(uint64_t a, uint64_t b)
static inline uint64_t counter(void)
{
uint64_t now;

grtc_wakeup();
nrfx_grtc_syscounter_get(&now);
grtc_sleep();
return now;
}

Expand All @@ -141,10 +99,8 @@ static inline uint64_t get_comparator(uint32_t chan)
static void system_timeout_set(uint64_t value)
{
if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) {
grtc_wakeup();
nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true,
NRFX_GRTC_CC_RELATIVE_SYSCOUNTER);
grtc_sleep();
} else {
nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(),
true);
Expand Down Expand Up @@ -319,18 +275,21 @@ uint64_t z_nrf_grtc_timer_get_ticks(k_timeout_t t)
int64_t curr_tick;
int64_t result;
int64_t abs_ticks;
int64_t grtc_ticks;

curr_time = counter();
curr_tick = sys_clock_tick_get();

grtc_ticks = t.ticks * CYC_PER_TICK;
abs_ticks = Z_TICK_ABS(t.ticks);
if (abs_ticks < 0) {
/* relative timeout */
return (t.ticks > (int64_t)COUNTER_SPAN) ? -EINVAL : (curr_time + t.ticks);
return (grtc_ticks > (int64_t)COUNTER_SPAN) ?
-EINVAL : (curr_time + grtc_ticks);
}

/* absolute timeout */
result = abs_ticks - curr_tick;
result = (abs_ticks - curr_tick) * CYC_PER_TICK;

if (result > (int64_t)COUNTER_SPAN) {
return -EINVAL;
Expand Down Expand Up @@ -370,6 +329,7 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time)
*/

uint64_t capt_time;
nrfx_err_t result;

IS_CHANNEL_ALLOWED_ASSERT(chan);

Expand All @@ -380,8 +340,10 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time)
*/
return -EBUSY;
}

capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan);
result = nrfx_grtc_syscounter_cc_value_read(chan, &capt_time);
if (result != NRFX_SUCCESS) {
return -EPERM;
}

__ASSERT_NO_MSG(capt_time < COUNTER_SPAN);

Expand All @@ -396,16 +358,22 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
nrfx_err_t err_code;
static uint8_t systemoff_channel;
uint64_t now = counter();
nrfx_grtc_sleep_config_t sleep_cfg;
/* Minimum time that ensures valid execution of system-off procedure. */
uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) +
nrfy_grtc_timeout_get(NRF_GRTC) +
CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY;
uint32_t minimum_latency_us;
uint32_t chan;
int ret;

nrfx_grtc_sleep_configuration_get(&sleep_cfg);
minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) * USEC_PER_SEC / 32768 +
CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY;
sleep_cfg.auto_mode = false;
nrfx_grtc_sleep_configure(&sleep_cfg);

if (minimum_latency_us > wake_time_us) {
return -EINVAL;
}

k_spinlock_key_t key = k_spin_lock(&lock);

err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
Expand All @@ -414,7 +382,9 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
return -ENOMEM;
}
(void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
ret = compare_set(systemoff_channel, now + wake_time_us, NULL, NULL);
ret = compare_set(systemoff_channel,
now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL,
NULL);
if (ret < 0) {
k_spin_unlock(&lock, key);
return ret;
Expand All @@ -430,7 +400,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
}

/* Make sure that wake_time_us was not triggered yet. */
if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, systemoff_channel)) {
if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) {
k_spin_unlock(&lock, key);
return -EINVAL;
}
Expand All @@ -441,7 +411,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
MAX_CC_LATCH_WAIT_TIME_US;
k_busy_wait(wait_time);
#if NRF_GRTC_HAS_CLKSEL
nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFXO);
nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFXO);
#endif
k_spin_unlock(&lock, key);
return 0;
Expand Down Expand Up @@ -482,16 +452,9 @@ static int sys_clock_driver_init(void)
#if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \
(defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1))
/* Use System LFCLK as the low-frequency clock source. */
nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFCLK);
nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFCLK);
#endif

#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER)
/* SYSCOUNTER needs to be turned off before initialization. */
nrfy_grtc_sys_counter_set(NRF_GRTC, false);
nrfy_grtc_timeout_set(NRF_GRTC, TIMEOUT);
nrfy_grtc_waketime_set(NRF_GRTC, WAKETIME);
#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */

IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_grtc_irq_handler, 0, 0);

err_code = nrfx_grtc_init(0);
Expand All @@ -504,20 +467,13 @@ static int sys_clock_driver_init(void)
if (err_code != NRFX_SUCCESS) {
return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM;
}
if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
nrfy_grtc_sys_counter_auto_mode_set(NRF_GRTC, false);
}
#else
err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel);
if (err_code != NRFX_SUCCESS) {
return -ENOMEM;
}
#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */

if (!IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
grtc_active_set();
}

int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
system_timeout_set(CYC_PER_TICK);
Expand Down
2 changes: 1 addition & 1 deletion include/zephyr/drivers/timer/nrf_grtc_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ uint64_t z_nrf_grtc_timer_compare_read(int32_t chan);
*
* @param chan Channel ID.
*
* @param target_time Absolute target time in ticks.
* @param target_time Absolute target time in GRTC ticks.
*
* @param handler User function called in the context of the GRTC interrupt.
*
Expand Down
15 changes: 13 additions & 2 deletions modules/hal_nordic/nrfx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,19 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM)
zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c)
endif()

if (CONFIG_NRF_GRTC_TIMER AND CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT)
zephyr_library_compile_definitions(NRF_GRTC_HAS_EXTENDED=1)
if (CONFIG_NRF_GRTC_TIMER)
if (CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT)
zephyr_library_compile_definitions(NRF_GRTC_HAS_EXTENDED=1)
endif()
if (CONFIG_NRF_GRTC_SLEEP_ALLOWED)
zephyr_compile_definitions(NRFX_GRTC_CONFIG_SLEEP_ALLOWED=1)
endif()
if (CONFIG_NRF_GRTC_TIMER_AUTO_KEEP_ALIVE)
zephyr_compile_definitions(NRFX_GRTC_CONFIG_AUTOEN=1)
endif()
if (CONFIG_NRF_GRTC_START_SYSCOUNTER)
zephyr_compile_definitions(NRFX_GRTC_CONFIG_AUTOSTART=1)
endif()
endif()

# Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to
Expand Down