1 /* 2 * Copyright (c) 2015 Eric Holland 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 #include <lk/err.h> 9 #include <lk/debug.h> 10 #include <lk/trace.h> 11 #include <arch/arm/cm.h> 12 #include <platform.h> 13 #include <platform/nrf51.h> 14 #include <platform/system_nrf51.h> 15 #include <platform/timer.h> 16 #include <sys/types.h> 17 18 19 static volatile uint64_t current_ticks; 20 static uint32_t tick_rate = 0; 21 static uint32_t tick_rate_mhz = 0; 22 static lk_time_t tick_interval_ms; 23 24 static platform_timer_callback cb; 25 static void *cb_args; 26 27 typedef enum handler_return (*platform_timer_callback)(void *arg, lk_time_t now); 28 29 status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) { 30 31 cb = callback; 32 cb_args = arg; 33 34 tick_interval_ms = interval; 35 36 uint32_t ticks = tick_rate / ( 1000 / interval ); 37 38 NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos; 39 NRF_CLOCK->TASKS_LFCLKSTART = 1; 40 41 NRF_RTC1->PRESCALER = ticks; 42 NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Enabled << RTC_INTENSET_TICK_Pos; 43 44 NRF_RTC1->EVENTS_TICK = 0; 45 NRF_RTC1->TASKS_START = 1; 46 NVIC_EnableIRQ(RTC1_IRQn); 47 48 return NO_ERROR; 49 } 50 51 lk_time_t current_time(void) { 52 uint64_t t; 53 54 do { 55 t = current_ticks; 56 } while (current_ticks != t); 57 58 return t * tick_interval_ms; 59 } 60 61 lk_bigtime_t current_time_hires(void) { 62 return current_time() * 1000; 63 } 64 65 void nrf51_RTC1_IRQ(void) { 66 current_ticks++; 67 arm_cm_irq_entry(); 68 69 NRF_RTC1->EVENTS_TICK = 0; 70 71 bool resched = false; 72 if (cb) { 73 lk_time_t now = current_time(); 74 if (cb(cb_args, now) == INT_RESCHEDULE) 75 resched = true; 76 } 77 arm_cm_irq_exit(resched); 78 } 79 80 void arm_cm_systick_init(uint32_t mhz) { 81 tick_rate = mhz; 82 tick_rate_mhz = mhz / 1000000; 83 } 84 85