Appiko
ms_timer.c
1 
19 #include "ms_timer.h"
20 #include "stddef.h"
21 #include "nrf_assert.h"
22 
23 #if ISR_MANAGER == 1
24 #include "isr_manager.h"
25 #endif
26 
30 #define RTC_ID CONCAT_2(NRF_RTC,MS_TIMER_RTC_USED)
31 #define RTC_IRQN CONCAT_3(RTC, MS_TIMER_RTC_USED, _IRQn)
32 #define RTC_IRQ_Handler CONCAT_3(RTC, MS_TIMER_RTC_USED, _IRQHandler)
33 
37 #define RTC_MAX_COUNT 0xFFFFFF
38 
42 static struct ms_timer_t
43 {
44  volatile uint64_t timer_mode;
45  volatile uint32_t timer_over_flow_num;
46  void (*timer_handler)(void);
47 } ms_timer[MS_TIMER_MAX];
48 
50 static volatile uint32_t ms_timers_status;
51 
53 static volatile uint32_t overflow_req_status;
54 
62 static void cal_overflow_ticks_req (uint32_t counter_val, uint64_t ticks, uint32_t id)
63 {
64  //Check if ticks can counted before overflow happens
65  if(ticks < RTC_MAX_COUNT)
66  {
67 
68  ms_timer[id].timer_over_flow_num = 0;
69  RTC_ID->CC[id] = (ticks + counter_val) & (0xFFFFFF);
70  RTC_ID->EVTENSET = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
71  RTC_ID->INTENSET = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
72  overflow_req_status &= 0<<id;
73  }
74  else
75  {
76  ms_timer[id].timer_over_flow_num = (ticks -
77  (RTC_MAX_COUNT - counter_val)) / (1<<24) + 1;
78  RTC_ID->CC[id] = (ticks - (RTC_MAX_COUNT - counter_val)) % (0x1 << 24);
79  overflow_req_status |= 1<<id;
80  RTC_ID->INTENSET = RTC_INTENSET_OVRFLW_Msk;
81  RTC_ID->EVTENSET = RTC_EVTENSET_OVRFLW_Msk;
82  }
83 }
84 
88 void rtc_overflow_handler ()
89 {
90  for (ms_timer_num id = MS_TIMER0; id < MS_TIMER_MAX; id++)
91  {
92  if(ms_timer[id].timer_over_flow_num != 0)
93  {
94  if(ms_timer[id].timer_over_flow_num == 1)
95  {
96  RTC_ID->EVTENSET = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
97  RTC_ID->INTENSET = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
98  overflow_req_status &= 0<<id;
99  }
100  ms_timer[id].timer_over_flow_num--;
101  }
102  }
103  if(overflow_req_status == 0)
104  {
105  RTC_ID->INTENCLR = RTC_INTENSET_OVRFLW_Msk;
106  RTC_ID->EVTENCLR = RTC_EVTENSET_OVRFLW_Msk;
107  }
108 
109 }
110 
111 void ms_timer_init(uint32_t irq_priority)
112 {
113  RTC_ID->TASKS_STOP = 1;
114 
115  for (ms_timer_num i = MS_TIMER0; i < MS_TIMER_MAX; i++)
116  {
117  ms_timer[i].timer_mode = MS_SINGLE_CALL;
118  ms_timer[i].timer_over_flow_num = -1;
119  ms_timer[i].timer_handler = NULL;
120  }
121 
122  ms_timers_status = 0;
123  RTC_ID->PRESCALER = (ROUNDED_DIV(LFCLK_FREQ, MS_TIMER_FREQ)) - 1;
124 
125  NVIC_SetPriority(RTC_IRQN, irq_priority);
126  NVIC_EnableIRQ(RTC_IRQN);
127 }
128 
134 void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void (*handler)(void))
135 {
136  /* make sure the number of ticks to interrupt is less than 2^56 */
137  ticks = ticks & 0x00FFFFFFFFFFFFFF;
138  ASSERT((ticks == 0 && mode == MS_REPEATED_CALL) == false);
139  if(ticks == 0)
140  {
141  ms_timer_stop(id);
142  if(mode == MS_SINGLE_CALL)
143  {
144  handler();
145  return;
146  }
147  }
148  ticks = (ticks < 2) ? 2 : ticks;
149  uint32_t counter_val = RTC_ID->COUNTER;
150 
151  ms_timer[id].timer_handler = handler;
152  if (mode == MS_SINGLE_CALL)
153  {
154  ms_timer[id].timer_mode = MS_SINGLE_CALL;
155  }
156  else
157  {
158  ms_timer[id].timer_mode = ticks;
159  }
160 
161  cal_overflow_ticks_req (counter_val, ticks, id);
162 
163  RTC_ID->EVENTS_COMPARE[id] = 0;
164 
165  if (ms_timers_status == 0)
166  {
167  RTC_ID->EVENTS_OVRFLW = 0;
168  RTC_ID->TASKS_START = 1;
169  }
170  ms_timers_status |= 1 << id;
171 }
172 
174 {
175  ms_timer[id].timer_mode = MS_SINGLE_CALL;
176  ms_timers_status &= ~(1 << id);
177  RTC_ID->EVTENCLR = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
178  RTC_ID->INTENCLR = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
179 
180  if (ms_timers_status == 0)
181  {
182  RTC_ID->TASKS_STOP = 1;
183  }
184 }
185 
187 {
188  return ((ms_timers_status & (1 << id)) != 0);
189 }
190 
194 __attribute__((optimize("unroll-loops")))
195 #if ISR_MANAGER == 1
196 void ms_timer_rtc_Handler ()
197 #else
198 void RTC_IRQ_Handler()
199 #endif
200 {
201  uint32_t counter_val = RTC_ID->COUNTER;
202  if(RTC_ID->EVENTS_OVRFLW)
203  {
204 #if ISR_MANAGER == 0
205  RTC_ID->EVENTS_OVRFLW = 0;
206 #endif
207  rtc_overflow_handler ();
208  }
209  for (ms_timer_num id = MS_TIMER0; id < MS_TIMER_MAX; id++)
210  {
211  if (RTC_ID->EVENTS_COMPARE[id])
212  {
213  RTC_ID->EVTENCLR = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
214  RTC_ID->INTENCLR = 1 << (RTC_INTENSET_COMPARE0_Pos + id);
215 #if ISR_MANAGER == 0
216  RTC_ID->EVENTS_COMPARE[id] = 0;
217  (void)RTC_ID->EVENTS_COMPARE[id];
218 #endif
219 
220  void (*cb_handler)(void) = NULL;
221  if (ms_timer[id].timer_handler != NULL)
222  {
223  cb_handler = ms_timer[id].timer_handler;
224  }
225 
226  if (ms_timer[id].timer_mode == MS_SINGLE_CALL)
227  {
228  ms_timer_stop(id);
229  }
230  else
231  {
232  cal_overflow_ticks_req (counter_val, ms_timer[id].timer_mode, id);
233  }
234 
235  if(cb_handler != NULL)
236  {
237  cb_handler();
238  }
239  }
240  }
241 }
Strcture for Operation time.
Definition: sensepi_ble.h:38
Repeated call of the timer.
Definition: ms_timer.h:83
bool ms_timer_get_on_status(ms_timer_num id)
Definition: ms_timer.c:186
#define ASSERT(expression)
Macro for runtime assertion of an expression. If the expression is false the assert_nrf_callback func...
Definition: nrf_assert.h:48
Not a timer, just used to find the number of timers.
Definition: ms_timer.h:75
void ms_timer_init(uint32_t irq_priority)
Definition: ms_timer.c:111
ms_timer_mode
Enumeration to specify the mode of operation of the timer.
Definition: ms_timer.h:81
Millisecond Timer 0.
Definition: ms_timer.h:69
#define MS_TIMER_FREQ
Definition: ms_timer.h:55
void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void(*handler)(void))
Definition: ms_timer.c:134
ms_timer_num
Enumeration used for specifying the timers that can be used with a RTC peripheral.
Definition: ms_timer.h:68
#define LFCLK_FREQ
Frequency of the low frequency clock is 32.768 kHz.
Definition: hal_clocks.h:43
#define ROUNDED_DIV(A, B)
Rounded integer division where the result is the integer closest to the answer instead of flooring th...
Definition: common_util.h:80
void ms_timer_stop(ms_timer_num id)
Definition: ms_timer.c:173
One shot call of the timer.
Definition: ms_timer.h:82