ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_nrf5_sdk15_timer.c
Go to the documentation of this file.
3 #if RUUVI_NRF5_SDK15_TIMER_ENABLED
4 #include "ruuvi_driver_error.h"
6 #include "ruuvi_interface_log.h"
7 
8 #include "nrf_error.h"
9 #include "nrf_drv_clock.h"
10 #include "sdk_errors.h"
11 #include "app_timer.h"
12 
13 #include <stdbool.h>
14 
15 #if RI_TIMER_MAX_INSTANCES > 10
16 #error "Allocating over 10 timers is not supported"
17 #endif
18 #if RI_TIMER_MAX_INSTANCES > 9
19 APP_TIMER_DEF (timer_9);
20 #endif
21 #if RI_TIMER_MAX_INSTANCES > 8
22 APP_TIMER_DEF (timer_8);
23 #endif
24 #if RI_TIMER_MAX_INSTANCES > 7
25 APP_TIMER_DEF (timer_7);
26 #endif
27 #if RI_TIMER_MAX_INSTANCES > 6
28 APP_TIMER_DEF (timer_6);
29 #endif
30 #if RI_TIMER_MAX_INSTANCES > 5
31 APP_TIMER_DEF (timer_5);
32 #endif
33 #if RI_TIMER_MAX_INSTANCES > 4
34 APP_TIMER_DEF (timer_4);
35 #endif
36 #if RI_TIMER_MAX_INSTANCES > 3
37 APP_TIMER_DEF (timer_3);
38 #endif
39 #if RI_TIMER_MAX_INSTANCES > 2
40 APP_TIMER_DEF (timer_2);
41 #endif
42 #if RI_TIMER_MAX_INSTANCES > 1
43 APP_TIMER_DEF (timer_1);
44 #endif
45 #if RI_TIMER_MAX_INSTANCES > 0
46 APP_TIMER_DEF (timer_0);
47 #endif
48 #if 0 >= RI_TIMER_MAX_INSTANCES
49 #error "No instances enabled for application timer"
50 #endif
51 
52 static uint8_t timer_idx = 0;
53 static bool m_is_init = false;
54 
58 static app_timer_id_t get_timer_id (void)
59 {
60  switch (timer_idx++)
61  {
62 #if RI_TIMER_MAX_INSTANCES > 0
63 
64  case 0:
65  return timer_0;
66 #endif
67 #if RI_TIMER_MAX_INSTANCES > 1
68 
69  case 1:
70  return timer_1;
71 #endif
72 #if RI_TIMER_MAX_INSTANCES > 2
73 
74  case 2:
75  return timer_2;
76 #endif
77 #if RI_TIMER_MAX_INSTANCES > 3
78 
79  case 3:
80  return timer_3;
81 #endif
82 #if RI_TIMER_MAX_INSTANCES > 4
83 
84  case 4:
85  return timer_4;
86 #endif
87 #if RI_TIMER_MAX_INSTANCES > 5
88 
89  case 5:
90  return timer_5;
91 #endif
92 #if RI_TIMER_MAX_INSTANCES > 6
93 
94  case 6:
95  return timer_6;
96 #endif
97 #if RI_TIMER_MAX_INSTANCES > 7
98 
99  case 7:
100  return timer_7;
101 #endif
102 #if RI_TIMER_MAX_INSTANCES > 8
103 
104  case 8:
105  return timer_8;
106 #endif
107 #if RI_TIMER_MAX_INSTANCES > 9
108 
109  case 9:
110  return timer_9;
111 #endif
112 
113  default:
114  return NULL;
115  }
116 }
117 
119 {
120  rd_status_t err_code = RD_SUCCESS;
121  ret_code_t nrf_code = NRF_SUCCESS;
122 
123  if (m_is_init)
124  {
125  err_code |= RD_ERROR_INVALID_STATE;
126  }
127  // Initialize clock if not already initialized
128  else if (false == nrf_drv_clock_init_check())
129  {
130  nrf_code |= nrf_drv_clock_init();
131  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (nrf_code);
132  }
133 
134  if (RD_SUCCESS == err_code)
135  {
136  nrf_drv_clock_lfclk_request (NULL);
137  nrf_code |= app_timer_init();
138  }
139 
140  if (NRF_SUCCESS == nrf_code)
141  {
142  m_is_init = true;
143  }
144 
145  return ruuvi_nrf5_sdk15_to_ruuvi_error (nrf_code) | err_code;
146 }
147 
148 //return true if timers have been successfully initialized.
149 bool ri_timer_is_init (void)
150 {
151  return m_is_init;
152 }
153 
155  p_timer_id, const ri_timer_mode_t mode,
156  const ruuvi_timer_timeout_handler_t timeout_handler)
157 {
158  rd_status_t err_code = RD_SUCCESS;
159  app_timer_mode_t nrf_mode = APP_TIMER_MODE_SINGLE_SHOT;
160 
161  if (m_is_init)
162  {
163  if (RI_TIMER_MODE_REPEATED == mode)
164  {
165  nrf_mode = APP_TIMER_MODE_REPEATED;
166  }
167 
168  app_timer_id_t tid = get_timer_id();
169 
170  if (NULL != tid)
171  {
172  ret_code_t nrf_code = app_timer_create (&tid,
173  nrf_mode,
174  (app_timer_timeout_handler_t) timeout_handler);
175 
176  if (NRF_SUCCESS == nrf_code)
177  {
178  *p_timer_id = (void *) tid;
179  }
180 
181  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
182  }
183  else
184  {
185  err_code |= RD_ERROR_RESOURCES;
186  }
187  }
188  else
189  {
190  err_code |= RD_ERROR_INVALID_STATE;
191  }
192 
193  return err_code;
194 }
195 
197  timer_id, const uint32_t ms,
198  void * const context)
199 {
200  // Counters are 24 bits
201  // nrf5 sdk_config.h has prescaler setting for timer, resolution can be traded for run time
202  if (APP_TIMER_TICKS (ms) >= (1 << 24))
203  {
204  ri_log (RI_LOG_LEVEL_ERROR, "Timer overflow, timer not started\r\n");
205  return RD_ERROR_INVALID_PARAM;
206  }
207 
208  ret_code_t err_code = app_timer_start ( (app_timer_id_t) timer_id, APP_TIMER_TICKS (ms),
209  context);
210  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
211 }
212 
214 {
215  ret_code_t err_code = app_timer_stop ( (app_timer_id_t) timer_id);
216  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
217 }
218 
220 {
221  app_timer_stop_all();
222  nrf_drv_clock_lfclk_release();
223  timer_idx = 0;
224  m_is_init = false;
225  return RD_SUCCESS;
226 }
227 
228 #endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
uint32_t rd_status_t
bitfield for representing errors
rd_status_t ruuvi_nrf5_sdk15_to_ruuvi_error(const ret_code_t error)
convert nrf5 sdk15 error code into Ruuvi error code.
#define RD_ERROR_RESOURCES
Not enough resources for operation.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
void ri_log(const ri_log_severity_t severity, const char *const message)
Queues messages into log.
@ RI_LOG_LEVEL_ERROR
bool ri_timer_is_init(void)
Check if timer is initialized.
rd_status_t ri_timer_uninit(void)
rd_status_t ri_timer_start(ri_timer_id_t timer_id, uint32_t ms, void *const context)
Start given timer at a mode defined in ri_timer_create.
rd_status_t ri_timer_create(ri_timer_id_t *p_timer_id, ri_timer_mode_t mode, ruuvi_timer_timeout_handler_t timeout_handler)
void(* ruuvi_timer_timeout_handler_t)(void *const p_context)
Function to be called when timer times out.
rd_status_t ri_timer_init(void)
ri_timer_mode_t
Enable implementation selected by application.
rd_status_t ri_timer_stop(ri_timer_id_t timer_id)
void * ri_timer_id_t
Pointer to timer data.
@ RI_TIMER_MODE_REPEATED
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Interface functions to timer.