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 uint32_t ccen_fix_count;
50static volatile uint64_t last_tick_syscounter;
51static volatile uint32_t recover_count;
53static void schedule_next_tick(
void);
65grtc_tick_handler(int32_t
id, uint64_t cc_value,
void *context)
71 last_tick_syscounter = cc_value;
75static void wait_for_lfclk_ready(
void);
76static void wait_for_syscounter_ready(
void);
79schedule_next_tick(
void)
81 nrfx_err_t err = nrfx_grtc_syscounter_cc_relative_set(&tick_channel,
84 NRFX_GRTC_CC_RELATIVE_SYSCOUNTER);
85 last_schedule_err = err;
86 if(err == NRFX_ERROR_INTERNAL) {
87 wait_for_syscounter_ready();
88 err = nrfx_grtc_syscounter_cc_relative_set(&tick_channel,
91 NRFX_GRTC_CC_RELATIVE_SYSCOUNTER);
92 last_schedule_err = err;
95 if(err != NRFX_SUCCESS) {
96 schedule_failure_count++;
102 if(NRF_GRTC->CC[tick_channel_id].CCEN !=
103 (GRTC_CC_CCEN_ACTIVE_Enable << GRTC_CC_CCEN_ACTIVE_Pos)) {
104 NRF_GRTC->CC[tick_channel_id].CCEN =
105 (GRTC_CC_CCEN_ACTIVE_Enable << GRTC_CC_CCEN_ACTIVE_Pos);
113 nrfx_err_t err = nrfx_clock_init(NULL);
114 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
119 nrfx_clock_lfclk_start();
120 wait_for_lfclk_ready();
132 schedule_failure_count = 0;
133 tick_interval_us = (uint32_t)(((uint64_t)GRTC_TICK_FREQUENCY_HZ +
135 if(tick_interval_us == 0) {
136 tick_interval_us = 1;
141 init_error_code = NRFX_ERROR_INTERNAL;
143 nrfx_err_t err = nrfx_grtc_init(GRTC_IRQ_PRIORITY);
144 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
145 init_error_code = err;
150 NVIC_SetPriority(GRTC_IRQn, GRTC_IRQ_PRIORITY);
151 NVIC_ClearPendingIRQ(GRTC_IRQn);
152 NVIC_EnableIRQ(GRTC_IRQn);
156 uint8_t main_cc_channel = 0;
157 err = nrfx_grtc_syscounter_start(
true, &main_cc_channel);
158 if(err != NRFX_SUCCESS && err != NRFX_ERROR_ALREADY) {
159 init_error_code = err;
162 wait_for_syscounter_ready();
163 nrfx_grtc_active_request_set(
true);
167 err = nrfx_grtc_channel_alloc(&channel);
168 if(err != NRFX_SUCCESS) {
169 init_error_code = err;
173 nrfx_grtc_syscounter_cc_int_enable(channel);
176 tick_channel.channel = channel;
177 tick_channel.handler = grtc_tick_handler;
178 tick_channel.p_context = NULL;
179 tick_channel_id = channel;
181 schedule_next_tick();
183 is_initialized =
true;
184 init_error_code = NRFX_SUCCESS;
211 nrfx_coredep_delay_us(dt);
221clock_arch_get_irq_count(
void)
223 return grtc_irq_count;
227clock_arch_get_last_schedule_err(
void)
229 return last_schedule_err;
233clock_arch_get_schedule_failures(
void)
235 return schedule_failure_count;
239clock_arch_get_tick_channel(
void)
241 return tick_channel_id;
245clock_arch_get_tick_interval_us(
void)
247 return tick_interval_us;
251clock_arch_get_syscounter(
void)
257 hi = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH;
258 lo = NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERL;
259 }
while(hi != NRF_GRTC->SYSCOUNTER[1].SYSCOUNTERH);
260 return ((uint64_t)(hi & 0x001FFFFFUL) << 32) | lo;
264clock_arch_get_ccen_fix_count(
void)
266 return ccen_fix_count;
270clock_arch_get_grtc_inten(
void)
272 return NRF_GRTC->INTENSET2;
276clock_arch_get_grtc_ccen(
void)
278 return NRF_GRTC->CC[tick_channel_id].CCEN;
282clock_arch_is_initialized(
void)
284 return is_initialized;
288clock_arch_get_init_error(
void)
290 return init_error_code;
296 static clock_time_t last_check_ticks;
297 static uint32_t idle_count;
299 if(!is_initialized) {
303 clock_time_t current = ticks;
305 if(current != last_check_ticks) {
306 last_check_ticks = current;
313 if(idle_count > 5000) {
318 schedule_next_tick();
323wait_for_lfclk_ready(
void)
325 while(!nrfx_clock_lfclk_is_running()) {
331wait_for_syscounter_ready(
void)
333 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.