1 /* 2 * Copyright (c) 2023 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <stdbool.h> 8 #include <stdint.h> 9 #include "nsi_cpu0_interrupts.h" 10 #include "irq_ctrl.h" 11 #include "nsi_tasks.h" 12 #include "nsi_hws_models_if.h" 13 14 static 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 21 /** 22 * Initialize the counter with prescaler of HW 23 */ hw_counter_init(void)24static void hw_counter_init(void) 25 { 26 hw_counter_timer = NSI_NEVER; 27 counter_target = NSI_NEVER; 28 counter_value = 0; 29 counter_running = false; 30 counter_period = NSI_NEVER; 31 } 32 33 NSI_TASK(hw_counter_init, HW_INIT, 10); 34 hw_counter_triggered(void)35static void hw_counter_triggered(void) 36 { 37 if (!counter_running) { 38 hw_counter_timer = NSI_NEVER; 39 return; 40 } 41 42 hw_counter_timer = nsi_hws_get_time() + counter_period; 43 counter_value = counter_value + 1; 44 45 if (counter_value == counter_target) { 46 hw_irq_ctrl_set_irq(COUNTER_EVENT_IRQ); 47 } 48 } 49 50 NSI_HW_EVENT(hw_counter_timer, hw_counter_triggered, 20); 51 52 /** 53 * Configures the counter period. 54 * The counter will be incremented every 'period' microseconds. 55 */ hw_counter_set_period(uint64_t period)56void hw_counter_set_period(uint64_t period) 57 { 58 counter_period = period; 59 } 60 61 /** 62 * Starts the counter. It must be previously configured with 63 * hw_counter_set_period() and hw_counter_set_target(). 64 */ hw_counter_start(void)65void hw_counter_start(void) 66 { 67 if (counter_running) { 68 return; 69 } 70 71 counter_running = true; 72 73 hw_counter_timer = nsi_hws_get_time() + counter_period; 74 nsi_hws_find_next_event(); 75 } 76 77 /** 78 * Stops the counter at current value. 79 * On the next call to hw_counter_start, the counter will 80 * start from the value at which it was stopped. 81 */ hw_counter_stop(void)82void hw_counter_stop(void) 83 { 84 counter_running = false; 85 hw_counter_timer = NSI_NEVER; 86 nsi_hws_find_next_event(); 87 } 88 89 /** 90 * Returns the current counter value. 91 */ hw_counter_get_value(void)92uint64_t hw_counter_get_value(void) 93 { 94 return counter_value; 95 } 96 97 /** 98 * Configures the counter to generate an interrupt 99 * when its count value reaches target. 100 */ hw_counter_set_target(uint64_t target)101void hw_counter_set_target(uint64_t target) 102 { 103 counter_target = target; 104 } 105