17#include "nrfx_clock.h"
18#include "soc/nrfx_coredep.h"
33#define GRTC_IRQ_PRIORITY 6
34#define GRTC_TICK_FREQUENCY_HZ 1000000UL
37#error CLOCK_CONF_SIZE must be 4 (32 bit)
40static volatile clock_time_t ticks;
41static uint32_t tick_interval_us;
42static nrfx_grtc_channel_t tick_channel;
43static bool is_initialized;
44static volatile nrfx_err_t last_schedule_err;
45static volatile uint32_t schedule_failure_count;
46static nrfx_err_t init_error_code;
47volatile uint8_t tick_channel_id;
48static volatile uint32_t grtc_irq_count;
49static volatile uint64_t last_tick_syscounter;
50static volatile uint32_t recover_count;
52static void schedule_next_tick(
void);
64grtc_tick_handler(int32_t
id, uint64_t cc_value,
void *context)
70 last_tick_syscounter = cc_value;
74static void wait_for_lfclk_ready(
void);
75static void wait_for_syscounter_ready(
void);
76uint64_t clock_arch_get_syscounter(
void);
79schedule_next_tick(
void)
97 uint64_t deadline = clock_arch_get_syscounter() + tick_interval_us;
98 nrfx_err_t err = nrfx_grtc_syscounter_cc_absolute_set(&tick_channel,
101 last_schedule_err = err;
102 if(err == NRFX_ERROR_INTERNAL) {
103 wait_for_syscounter_ready();
104 deadline = clock_arch_get_syscounter() + tick_interval_us;
105 err = nrfx_grtc_syscounter_cc_absolute_set(&tick_channel,
108 last_schedule_err = err;
111 if(err != NRFX_SUCCESS) {
112 schedule_failure_count++;
121 NRF_GRTC->CC[tick_channel_id].CCEN =
122 (GRTC_CC_CCEN_ACTIVE_Enable << GRTC_CC_CCEN_ACTIVE_Pos);
128 nrfx_err_t err = nrfx_clock_init(NULL);
129 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
134 nrfx_clock_lfclk_start();
135 wait_for_lfclk_ready();
147 schedule_failure_count = 0;
148 tick_interval_us = (uint32_t)(((uint64_t)GRTC_TICK_FREQUENCY_HZ +
150 if(tick_interval_us == 0) {
151 tick_interval_us = 1;
156 init_error_code = NRFX_ERROR_INTERNAL;
158 nrfx_err_t err = nrfx_grtc_init(GRTC_IRQ_PRIORITY);
159 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
160 init_error_code = err;
165 NVIC_SetPriority(GRTC_IRQn, GRTC_IRQ_PRIORITY);
166 NVIC_ClearPendingIRQ(GRTC_IRQn);
167 NVIC_EnableIRQ(GRTC_IRQn);
171 uint8_t main_cc_channel = 0;
172 err = nrfx_grtc_syscounter_start(
true, &main_cc_channel);
173 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
174 init_error_code = err;
177 wait_for_syscounter_ready();
178 nrfx_grtc_active_request_set(
true);
182 err = nrfx_grtc_channel_alloc(&channel);
183 if(err != NRFX_SUCCESS) {
184 init_error_code = err;
188 nrfx_grtc_syscounter_cc_int_enable(channel);
191 tick_channel.channel = channel;
192 tick_channel.handler = grtc_tick_handler;
193 tick_channel.p_context = NULL;
194 tick_channel_id = channel;
196 schedule_next_tick();
198 is_initialized =
true;
199 init_error_code = NRFX_SUCCESS;
226 nrfx_coredep_delay_us(dt);
236clock_arch_get_irq_count(
void)
238 return grtc_irq_count;
242clock_arch_get_last_schedule_err(
void)
244 return last_schedule_err;
248clock_arch_get_schedule_failures(
void)
250 return schedule_failure_count;
254clock_arch_get_tick_channel(
void)
256 return tick_channel_id;
260clock_arch_get_tick_interval_us(
void)
262 return tick_interval_us;
266clock_arch_get_syscounter(
void)
272 hi = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH;
273 lo = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL;
274 }
while(hi != NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH);
275 return ((uint64_t)(hi & 0x001FFFFFUL) << 32) | lo;
279clock_arch_get_grtc_inten(
void)
281 return NRF_GRTC->INTENSET2;
285clock_arch_get_grtc_ccen(
void)
287 return NRF_GRTC->CC[tick_channel_id].CCEN;
291clock_arch_is_initialized(
void)
293 return is_initialized;
297clock_arch_get_init_error(
void)
299 return init_error_code;
305 static clock_time_t last_check_ticks;
306 static uint32_t idle_count;
308 if(!is_initialized) {
312 clock_time_t current = ticks;
314 if(current != last_check_ticks) {
315 last_check_ticks = current;
322 if(idle_count > 5000) {
327 schedule_next_tick();
332wait_for_lfclk_ready(
void)
334 while(!nrfx_clock_lfclk_is_running()) {
340wait_for_syscounter_ready(
void)
342 while(!nrfx_grtc_ready_check()) {
#define CLOCK_SECOND
A second, measured in system clock time.
int etimer_pending(void)
Check if there are any non-expired event timers.
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
void clock_init(void)
Initialize the clock library.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
void clock_wait(clock_time_t i)
Wait for a given number of ticks.
clock_time_t clock_time(void)
Get the current clock time.
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
static void start(void)
Start measurement.