1 /* 2 * Copyright (c) 2020 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <stdbool.h> 8 #include <stdint.h> 9 #include "hw_models_top.h" 10 #include "board_soc.h" 11 #include "board_irq.h" 12 #include "irq_ctrl.h" 13 14 uint64_t hw_counter_timer; 15 16 static bool counter_running; 17 static uint64_t counter_value; 18 static uint64_t counter_target; 19 static uint64_t counter_period; 20 static uint64_t counter_wrap; 21 22 /** 23 * Initialize the counter with prescaler of HW 24 */ hw_counter_init(void)25void hw_counter_init(void) 26 { 27 hw_counter_timer = NEVER; 28 counter_target = NEVER; 29 counter_value = 0; 30 counter_running = false; 31 counter_period = NEVER; 32 counter_wrap = NEVER; 33 } 34 hw_counter_triggered(void)35void hw_counter_triggered(void) 36 { 37 if (!counter_running) { 38 hw_counter_timer = NEVER; 39 return; 40 } 41 42 hw_counter_timer = hwm_get_time() + counter_period; 43 counter_value = (counter_value + 1) % counter_wrap; 44 45 if (counter_value == counter_target) { 46 hw_irq_ctrl_set_irq(COUNTER_EVENT_IRQ); 47 } 48 } 49 50 /** 51 * Configures the counter period. 52 * The counter will be incremented every 'period' microseconds. 53 */ hw_counter_set_period(uint64_t period)54void hw_counter_set_period(uint64_t period) 55 { 56 counter_period = period; 57 } 58 59 /* 60 * Set the count value at which the counter will wrap 61 * The counter will count up to (counter_wrap-1), i.e.: 62 * 0, 1, 2,.., (counter_wrap - 1), 0 63 */ hw_counter_set_wrap_value(uint64_t wrap_value)64void hw_counter_set_wrap_value(uint64_t wrap_value) 65 { 66 counter_wrap = wrap_value; 67 } 68 69 /** 70 * Starts the counter. It must be previously configured with 71 * hw_counter_set_period() and hw_counter_set_target(). 72 */ hw_counter_start(void)73void hw_counter_start(void) 74 { 75 if (counter_running) { 76 return; 77 } 78 79 counter_running = true; 80 81 hw_counter_timer = hwm_get_time() + counter_period; 82 hwm_find_next_timer(); 83 } 84 85 /** 86 * Stops the counter at current value. 87 * On the next call to hw_counter_start, the counter will 88 * start from the value at which it was stopped. 89 */ hw_counter_stop(void)90void hw_counter_stop(void) 91 { 92 counter_running = false; 93 hw_counter_timer = NEVER; 94 hwm_find_next_timer(); 95 } 96 hw_counter_is_started(void)97bool hw_counter_is_started(void) 98 { 99 return counter_running; 100 } 101 102 /** 103 * Returns the current counter value. 104 */ hw_counter_get_value(void)105uint64_t hw_counter_get_value(void) 106 { 107 return counter_value; 108 } 109 110 /** 111 * Resets the counter value. 112 */ hw_counter_reset(void)113void hw_counter_reset(void) 114 { 115 counter_value = 0; 116 } 117 118 /** 119 * Configures the counter to generate an interrupt 120 * when its count value reaches target. 121 */ hw_counter_set_target(uint64_t target)122void hw_counter_set_target(uint64_t target) 123 { 124 counter_target = target; 125 } 126