Appiko
us_timer.c
1 
19 #include "us_timer.h"
20 #include "nrf_util.h"
21 #include <stddef.h>
22 
23 #if ISR_MANAGER == 1
24 #include "isr_manager.h"
25 #endif
26 
30 #define TIMER_ID CONCAT_2(NRF_TIMER, US_TIMER_USED)
31 #define TIMER_IRQN CONCAT_3(TIMER, US_TIMER_USED, _IRQn)
32 #define TIMER_IRQ_Handler CONCAT_3(TIMER, US_TIMER_USED, _IRQHandler)
33 #define TIMER_SIZE CONCAT_3(NRF_TIMER, US_TIMER_USED, _MAX_SIZE)
34 
38 #define TIMER_PRESCALER 4
39 
40 #if(TIMER_SIZE ==32)
41 #define TIMER_BITSIZE TIMER_BITMODE_BITMODE_32Bit
42 #else
43 #define TIMER_BITSIZE TIMER_BITMODE_BITMODE_16Bit
44 #endif
45 
48 static struct us_timer_t{
49  volatile uint32_t timer_mode;
50  void (*timer_handler)(void);
51 }us_timer[US_TIMER_MAX];
52 
54 static volatile uint32_t us_timers_status;
55 
56 void us_timer_init(uint32_t irq_priority){
57  for(us_timer_num id = US_TIMER0; id < US_TIMER_MAX; id++){
58  us_timer[id].timer_mode = US_SINGLE_CALL;
59  us_timer[id].timer_handler = NULL;
60  }
61  us_timers_status = 0;
62 
63  TIMER_ID->TASKS_STOP = 1; // Stop timer.
64  TIMER_ID->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode.
65  TIMER_ID->PRESCALER = TIMER_PRESCALER; // Prescaler 4 produces 1 MHz.
66  TIMER_ID->BITMODE = TIMER_BITSIZE; // 32 bit mode.
67  TIMER_ID->TASKS_CLEAR = 1; // clear the Timer first to be usable for later.
68  TIMER_ID->TASKS_START = 1;
69 
70  NVIC_SetPriority(TIMER_IRQN, irq_priority);
71  NVIC_EnableIRQ(TIMER_IRQN);
72 }
73 
74 void us_timer_start(us_timer_num id, us_timer_mode mode, uint32_t time_us, void (*handler)(void)){
75  us_timer[id].timer_handler = handler;
76  if(mode == US_SINGLE_CALL){
77  us_timer[id].timer_mode = US_SINGLE_CALL;
78  }else{
79  us_timer[id].timer_mode = time_us;
80  }
81 
82  TIMER_ID->TASKS_CAPTURE[id] = 1;
83  TIMER_ID->CC[id] += time_us;
84 
85  TIMER_ID->EVENTS_COMPARE[id] = 0;
86  TIMER_ID->INTENSET = 1 << (TIMER_INTENSET_COMPARE0_Pos + id);
87 
88  //If no timers are currently on
89  if (us_timers_status == 0)
90  {
91  TIMER_ID->TASKS_START = 1;
92  }
93 
94  us_timers_status |= 1 << id;
95 }
96 
98  us_timer[id].timer_mode = US_SINGLE_CALL;
99  us_timers_status &= ~(1 << id);
100 
101  TIMER_ID->INTENCLR = 1 << (TIMER_INTENSET_COMPARE0_Pos + id);
102 
103  //If the stopped timer is the last timer that's on
104  if (us_timers_status == 0)
105  {
106  TIMER_ID->TASKS_STOP = 1; // Stop timer.
107  TIMER_ID->TASKS_SHUTDOWN = 1; // Fully stop timer.
108  }
109 }
110 
112  return ((us_timers_status & (1<<id)) != 0);
113 }
114 
118 #if ISR_MANAGER == 1
119 void us_timer_timer_Handler ()
120 #else
121 void TIMER_IRQ_Handler()
122 #endif
123 {
124  for(us_timer_num id = US_TIMER0; id < US_TIMER_MAX; id++){
125  if(TIMER_ID->EVENTS_COMPARE[id]){
126 #if ISR_MANAGER == 0
127  TIMER_ID->EVENTS_COMPARE[id] = 0;
128  (void) TIMER_ID->EVENTS_COMPARE[id];
129 #endif
130  void (*cb_handler)(void) = NULL;
131  if(us_timer[id].timer_handler != NULL)
132  {
133  cb_handler = us_timer[id].timer_handler;
134  }
135 
136  if (us_timer[id].timer_mode == US_SINGLE_CALL)
137  {
138  us_timer_stop(id);
139  }
140  else
141  {
142  TIMER_ID->TASKS_CAPTURE[id] = 1;
143  TIMER_ID->CC[id] += us_timer[id].timer_mode;
144  }
145 
146  if(cb_handler != NULL)
147  {
148  cb_handler();
149  }
150  }
151  }
152 }
153 
us_timer_num
Enumeration used for specifying the timers that can be used with this TIMER peripheral.
Definition: us_timer.h:56
void us_timer_start(us_timer_num id, us_timer_mode mode, uint32_t time_us, void(*handler)(void))
Definition: us_timer.c:74
void us_timer_init(uint32_t irq_priority)
Initialize the TIMER peripheral to use as a micro-second timer.
Definition: us_timer.c:56
One shot call of the timer.
Definition: us_timer.h:72
bool us_timer_get_on_status(us_timer_num id)
Definition: us_timer.c:111
Not a timer, just used to find the number of timers.
Definition: us_timer.h:65
void us_timer_stop(us_timer_num id)
Definition: us_timer.c:97
Microsecond Timer 0.
Definition: us_timer.h:57
us_timer_mode
Enumeration to specify the mode of operation of the timer.
Definition: us_timer.h:71