ADF7030-1 Device Drivers API Reference Manual  Alpha 0.0.1
Device Drivers for ADF7030-1 Transceiver
adf7030-1__timer.c
1 /*********************************************************************************
2 
3 Copyright(c) 2016 Analog Devices, Inc. All Rights Reserved.
4 
5 This software is proprietary and confidential. By using this software you agree
6 to the terms of the associated Analog Devices License Agreement.
7 
8 *********************************************************************************/
27 #ifndef _ADF7030_1__TIMER_C_
28 
29 #define _ADF7030_1__TIMER_C_
30 
31 #include <stddef.h>
32 #include <string.h>
33 #include <assert.h>
34 #include "system.h"
35 #include "common.h"
36 
37 #include <services/tmr/adi_tmr.h>
38 #include <services/gpio/adi_gpio.h>
39 //#include <devices/rf/adf703x/adi_adf7030-1.h>
40 //#include <devices/rf/adf703x/adi_adf7030-1_reg.h>
41 #include <devices/rf/adf703x/adf7030-1__timer.h>
42 
43 #ifdef __ICCARM__
44 /*
45 * IAR MISRA C 2004 error suppressions.
46 *
47 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
48 * The rule makes an exception for memory-mapped register accesses.
49 *
50 * Pm073 (rule 14.7): a function should have a single point of exit.
51 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function.
52 * Multiple returns are used for error handling.
53 */
54 #pragma diag_suppress=Pm073,Pm143
55 #endif /* __ICCARM__ */
56 
59 #define ADF7030_1_TIMER_TICK 2
60 #define ADF7030_1_TIMER_FAST 0
61 
62 #define SYS_CLK_FREQ 26000000
63 #define ADF7030_1_TIMER_1MS_VAL (SYS_CLK_FREQ / 1000)
64 #define ADF7030_1_TIMER_1US_VAL (ADF7030_1_TIMER_1MS_VAL / 1000)
65 
66 /* Memory required for TIMER driver */
67 static uint8_t aDeviceMemory0[ADI_TMR_MEMORY_SIZE];
68 static uint8_t aDeviceMemory2[ADI_TMR_MEMORY_SIZE];
69 
70 /* Timers device handles */
71 static ADI_TMR_HANDLE hTMR0Device;
72 static ADI_TMR_HANDLE hTMR2Device;
73 
74 /* Global Timestamp */
75 ADI_ADF7030_1_TIMESTAMP adf7030_1_time;
76 ADI_ADF7030_1_TIMESTAMP adf7030_1_time_capture;
77 
78 volatile bool_t bWait_uS_Flag;
79 
80 /* Initializes TIMER device */
81 uint32_t adf7030_1__TIMER_Init
82 (
83  void
84 )
85 {
86  /* Configure Timer2 as a background Global Time Stamp timer */
87  if(adi_tmr_Open(ADF7030_1_TIMER_TICK,
88  aDeviceMemory2,
89  ADI_TMR_MEMORY_SIZE,
90  &hTMR2Device) != ADI_TMR_SUCCESS)
91  {
92  return FAILURE;
93  }
94 
95  /* Set prescalar */
96  if(adi_tmr_SetPrescaler(hTMR2Device, ADI_GPT_PRESCALER_1) != ADI_TMR_SUCCESS)
97  {
98  return FAILURE;
99  }
100 
101  /* Set clock source */
102  if(adi_tmr_SetClockSource(hTMR2Device, ADI_TMR_CLOCK_PCLK) != ADI_TMR_SUCCESS)
103  {
104  return FAILURE;
105  }
106 
107  /* Set to run in periodic mode */
108  if(adi_tmr_SetRunMode(hTMR2Device, ADI_TMR_PERIODIC_MODE) != ADI_TMR_SUCCESS)
109  {
110  return FAILURE;
111  }
112 
113  /* Set to count down from Load value */
114  if(adi_tmr_SetCountMode(hTMR2Device, ADI_TMR_COUNT_DOWN) != ADI_TMR_SUCCESS)
115  {
116  return FAILURE;
117  }
118 
119  /* Enable automatic reloading (optional???) */
120  if(adi_tmr_EnableReloading(hTMR2Device, true) != ADI_TMR_SUCCESS)
121  {
122  return FAILURE;
123  }
124 
125  /* Set Load Value to give us a timeout every 1ms */
126  if(adi_tmr_SetLoadValue(hTMR2Device, ADF7030_1_TIMER_1MS_VAL / ERROR_COMPENSATION_DIV) != ADI_TMR_SUCCESS)
127  {
128  return FAILURE;
129  }
130 
131  /* Register the Timer2 Callback function */
132  if(adi_tmr_RegisterCallback(hTMR2Device, GPTimer2Callback, hTMR2Device) != ADI_TMR_SUCCESS)
133  {
134  return FAILURE;
135  }
136 
137  /* Configure capture event on external Interrupt from the adf7030-1 radio SPI */
138  if(adi_tmr_SetEventToCapture(hTMR2Device, ADI_TMR2_CAPTURE_EVENT_EXT_INT_0) != ADI_TMR_SUCCESS)
139  {
140  return FAILURE;
141  }
142 
143  /* Enable the capture event */
144  if(adi_tmr_EnableEventCapture(hTMR2Device, true) != ADI_TMR_SUCCESS)
145  {
146  return FAILURE;
147  }
148 
149  /* Clear the time stamp global variable */
150  adf7030_1_time.ms = 0;
151  adf7030_1_time.ticks = 0;
152 
153  /* Start up the Timer2 */
154  if(adi_tmr_Enable(hTMR2Device, true) != ADI_TMR_SUCCESS)
155  {
156  return FAILURE;
157  }
158 
159  /* Configure Timer0 as general purpose (us resolution) timer for wait and timeout */
160  if(adi_tmr_Open(ADF7030_1_TIMER_FAST,
161  aDeviceMemory0,
162  ADI_TMR_MEMORY_SIZE,
163  &hTMR0Device) != ADI_TMR_SUCCESS)
164  {
165  return FAILURE;
166  }
167 
168  /* Set prescalar */
169  if(adi_tmr_SetPrescaler(hTMR0Device, ADI_GPT_PRESCALER_1) != ADI_TMR_SUCCESS)
170  {
171  return FAILURE;
172  }
173 
174  /* Set clock source */
175  if(adi_tmr_SetClockSource(hTMR0Device, ADI_TMR_CLOCK_PCLK) != ADI_TMR_SUCCESS)
176  {
177  return FAILURE;
178  }
179 
180  /* Set to run in periodic mode */
181  if(adi_tmr_SetRunMode(hTMR0Device, ADI_TMR_PERIODIC_MODE) != ADI_TMR_SUCCESS)
182  {
183  return FAILURE;
184  }
185 
186  /* Set to count down from Load value */
187  if(adi_tmr_SetCountMode(hTMR0Device, ADI_TMR_COUNT_DOWN) != ADI_TMR_SUCCESS)
188  {
189  return FAILURE;
190  }
191 
192  /* Disable automatic reloading */
193  if(adi_tmr_EnableReloading(hTMR0Device, false) != ADI_TMR_SUCCESS)
194  {
195  return FAILURE;
196  }
197 
198  return SUCCESS;
199 }
200 
201 /* Uninitializes TIMER device */
202 uint32_t adf7030_1__TIMER_UnInit
203 (
204  void
205 )
206 {
207  if(adi_tmr_EnableEventCapture(hTMR2Device, false) != ADI_TMR_SUCCESS)
208  {
209  return FAILURE;
210  }
211 
212  if(adi_tmr_Enable(hTMR2Device, false) != ADI_TMR_SUCCESS)
213  {
214  return FAILURE;
215  }
216 
217  if(adi_tmr_Close(hTMR2Device) != ADI_TMR_SUCCESS)
218  {
219  return FAILURE;
220  }
221 
222  if(adi_tmr_Enable(hTMR0Device, false) != ADI_TMR_SUCCESS)
223  {
224  return FAILURE;
225  }
226 
227  if(adi_tmr_Close(hTMR0Device) != ADI_TMR_SUCCESS)
228  {
229  return FAILURE;
230  }
231 
232 
233  return SUCCESS;
234 }
235 
236 /* Clear the Global Time Count */
237 uint32_t adf7030_1__TIMER_ClrTime
238 (
240 )
241 {
242  pTime->ms = 0;
243  pTime->ticks = 0;
244 
245  return SUCCESS;
246 }
247 
248 
249 /* Capture the current Time Count */
250 uint32_t adf7030_1__TIMER_GetTime
251 (
253 )
254 {
255  pTime->ms = adf7030_1_time.ms;
256  if(adi_GPT_GetCurrentValue(hTMR2Device, &pTime->ticks) != ADI_TMR_SUCCESS)
257  {
258  return FAILURE;
259  }
260 
261  return SUCCESS;
262 }
263 
264 
265 uint32_t adf7030_1__TIMER_Start_uS
266 (
267  const uint16_t u_sec,
268  ADI_CALLBACK const pfCallback
269 )
270 {
271  if(u_sec > TOTAL_TMR_ERROR)
272  {
273  /* Calculate the Load value for the desired uS delay */
274  //uint32_t Val_uS = ADF7030_1_TIMER_1US_VAL * ((u_sec > TOTAL_TMR_ERROR) ? (u_sec - TOTAL_TMR_ERROR) : ERROR_COMPENSATION_DIV);
275  uint32_t Val_uS = ADF7030_1_TIMER_1US_VAL * (u_sec - TOTAL_TMR_ERROR);
276 
277  /* Saturates at 2530 us max */
278  if(Val_uS >> 16) Val_uS = 65520;
279 
280  /* Set Load Value to give u_sec uS a delay */
281  if(adi_tmr_SetLoadValue(hTMR0Device, ((uint16_t)Val_uS) / ERROR_COMPENSATION_DIV) != ADI_TMR_SUCCESS)
282  {
283  return FAILURE;
284  }
285 
286  /* Register custom Timer0 Callback function */
287  if(adi_tmr_RegisterCallback(hTMR0Device, pfCallback, hTMR0Device) != ADI_TMR_SUCCESS)
288  {
289  return FAILURE;
290  }
291 
292  bWait_uS_Flag = true;
293 
294  adi_gpio_SetHigh(ADI_GPIO_PORT0, ADI_GPIO_PIN_12);
295 
296  /* Start up the Timer0 */
297  if(adi_tmr_Enable(hTMR0Device, true) != ADI_TMR_SUCCESS)
298  {
299  return FAILURE;
300  }
301  }
302  else
303  {
304  adi_gpio_SetHigh(ADI_GPIO_PORT0, ADI_GPIO_PIN_12);
305 
307 
308  bWait_uS_Flag = false;
309  adf7030_1__TIMER_GetTime(&adf7030_1_time_capture);
310 
311  adi_gpio_SetLow(ADI_GPIO_PORT0, ADI_GPIO_PIN_12);
312 
313  }
314  return SUCCESS;
315 }
316 
317 uint32_t adf7030_1__TIMER_Stop_uS
318 (
319  void
320 )
321 {
322  /* Disable the Timer0 */
323  if(adi_tmr_Enable(hTMR0Device, false) != ADI_TMR_SUCCESS)
324  {
325  return FAILURE;
326  }
327 
328  /* Unregister Timer0 Callback function */
329  if(adi_tmr_RegisterCallback(hTMR0Device, NULL, hTMR0Device) != ADI_TMR_SUCCESS)
330  {
331  return FAILURE;
332  }
333 
334  bWait_uS_Flag = false;
335 
336  return SUCCESS;
337 }
338 
339 uint32_t adf7030_1__TIMER_Wait_uS
340 (
341  const uint16_t u_sec,
342  ADI_CALLBACK const pfCallback
343 )
344 {
345  if(adf7030_1__TIMER_Start_uS(u_sec, pfCallback) != SUCCESS)
346  {
347  return FAILURE;
348  }
349 
350  while(bWait_uS_Flag == true);
351 
352  if(adf7030_1__TIMER_Stop_uS() != SUCCESS)
353  {
354  return FAILURE;
355  }
356 
357  return SUCCESS;
358 }
359 
364 (
365  const uint16_t delay_us
366 )
367 {
368  // The loop below has 8 ticks per pass in the Cortex M0
369  #define INSTRUCTIONS_PER_LOOP 8
370 
371  // exit immediately if no delay
372  if (delay_us) {
373  // The number of loops per us multiplied by the number of us, all divided by the number of system ticks per loop
374  const uint32_t cycles_per_loop = INSTRUCTIONS_PER_LOOP;
375  const uint32_t usec_div = ADF7030_1_TIMER_1US_VAL;
376  const uint32_t loops = (delay_us * usec_div) / cycles_per_loop;
377 
378  for (uint32_t i = 0; i < loops; i++) {
379  //\todo: compiler pragma to stop optimisation of NOPs
380  __NOP();
381  __NOP();
382  __NOP();
383  __NOP();
384  }
385  }
386 
387  //Always return ok for now
388  return SUCCESS;
389 }
390 
391 
392 /* Default Callback event parsing for TIMER0 device (GP high resolution timer) */
393 void GPTimer0Callback
394 (
395  void *pCBParam,
396  uint32_t Event,
397  void *pArg
398 )
399 {
400  switch(Event)
401  {
402  case ADI_TMR_EVENT_TIMEOUT:
403  bWait_uS_Flag = false;
404  adf7030_1__TIMER_GetTime(&adf7030_1_time_capture);
405  break;
406  default:
407  break;
408  }
409  adi_gpio_SetLow(ADI_GPIO_PORT0, ADI_GPIO_PIN_12);
410 }
411 
412 
413 /* Default Callback event parsing for TIMER2 device (Timestamp) */
414 void GPTimer2Callback
415 (
416  void *pCBParam,
417  uint32_t Event,
418  void *pArg
419 )
420 {
421  adi_gpio_SetHigh(ADI_GPIO_PORT2, ADI_GPIO_PIN_0);
422  switch(Event)
423  {
424  case ADI_TMR_EVENT_TIMEOUT:
425  adf7030_1_time.ms += 1;
426  adf7030_1_time.ticks = 0;
427  break;
428  case ADI_TMR_EVENT_CAPTURED:
429  adf7030_1_time_capture.ms = adf7030_1_time.ms;
430  adi_tmr_GetCapturedValue(pCBParam, &adf7030_1_time_capture.ticks);
431  break;
432  default:
433  break;
434  }
435  adi_gpio_SetLow(ADI_GPIO_PORT2, ADI_GPIO_PIN_0);
436 }
437 
438 
439 #endif /* _ADF7030_1__TIMER_C_ */
440  /* End of group adf7030-1__timer Timers Interface layer */ /* End of group adf7030-1 adf7030-1 Driver */
uint32_t adf7030_1__TIMER_Active_Delay_uS(const uint16_t delay_us)
Active wait using NOPs This function loops using NOPs to give short delays.