dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_delay.c
Go to the documentation of this file.
1 
19 /*
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 3 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful, but
26  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
27  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28  * for more details.
29  *
30  * You should have received a copy of the GNU General Public License along
31  * with this program; if not, see <http://www.gnu.org/licenses/>
32  */
33 
34 /* Project Includes */
35 #include <pios.h>
36 
37 /* cycles per microsecond */
38 static uint32_t us_ticks;
39 static uint32_t us_modulo;
40 
47 int32_t PIOS_DELAY_Init(void)
48 {
49  RCC_ClocksTypeDef clocks;
50 
51  /* compute the number of system clocks per microsecond */
52  RCC_GetClocksFreq(&clocks);
53  us_ticks = clocks.SYSCLK_Frequency / 1000000;
55 
56  // Split this into two steps to avoid 64bit maths
57  us_modulo = 0xffffffff / us_ticks;
58  us_modulo += ((0xffffffff % us_ticks) + 1) / us_ticks;
59 
60  // ensure that the us_module is smaller than half of uint32_t max to make modulo operation possible
61  PIOS_Assert(us_modulo < 0x80000000);
62 
63  /* turn on access to the DWT registers */
64  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
65 
66  /* enable the CPU cycle counter */
67  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
68 
69  return 0;
70 }
71 
83 int32_t PIOS_DELAY_WaituS(uint32_t uS)
84 {
85  uint32_t elapsed = 0;
86  uint32_t last_count;
87 
88  /* turn on access to the DWT registers */
89  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
90  last_count = DWT->CYCCNT;
91 
92  for (;;) {
93  uint32_t current_count;
94  uint32_t elapsed_uS;
95 
96  /* turn on access to the DWT registers */
97  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
98  current_count = DWT->CYCCNT;
99 
100  /* measure the time elapsed since the last time we checked */
101  elapsed += current_count - last_count;
102  last_count = current_count;
103 
104  /* convert to microseconds */
105  elapsed_uS = elapsed / us_ticks;
106  if (elapsed_uS >= uS)
107  break;
108 
109  /* reduce the delay by the elapsed time */
110  uS -= elapsed_uS;
111 
112  /* keep fractional microseconds for the next iteration */
113  elapsed %= us_ticks;
114  }
115 
116  /* No error */
117  return 0;
118 }
119 
131 int32_t PIOS_DELAY_WaitmS(uint32_t mS)
132 {
133  while (mS--) {
134  PIOS_DELAY_WaituS(1000);
135  }
136 
137  /* No error */
138  return 0;
139 }
140 
145 uint32_t PIOS_DELAY_GetuS()
146 {
147  /* turn on access to the DWT registers */
148  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
149  return DWT->CYCCNT / us_ticks;
150 }
151 
157 uint32_t PIOS_DELAY_GetuSSince(uint32_t t)
158 {
159  return (PIOS_DELAY_GetuS() + us_modulo - t) % us_modulo;
160 }
161 
167 uint32_t PIOS_DELAY_GetuSExpired(uint32_t t)
168 {
169  uint32_t interval = PIOS_DELAY_GetuSSince(t);
170 
171  /* Use a windowed approach with the maximum timeval */
172  if (interval < (us_modulo / 2)) {
173  return true;
174  }
175 
176  return false;
177 }
178 
183 uint32_t PIOS_DELAY_GetRaw()
184 {
185  /* turn on access to the DWT registers */
186  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
187  return DWT->CYCCNT;
188 }
189 
194 uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
195 {
196  /* turn on access to the DWT registers */
197  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
198 
199  return PIOS_DELAY_DiffuS2(raw, DWT->CYCCNT);
200 }
201 
206 uint32_t PIOS_DELAY_DiffuS2(uint32_t raw, uint32_t later) {
207  uint32_t diff = later - raw;
208  return diff / us_ticks;
209 }
210 
uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
Subtract raw time from now and convert to us.
Definition: pios_delay.c:159
uint32_t PIOS_DELAY_GetuS()
Query the Delay timer for the current uS.
Definition: pios_delay.c:173
Main PiOS header to include all the compiled in PiOS options.
uint32_t PIOS_DELAY_DiffuS2(uint32_t raw, uint32_t baseline)
Subrtact two raw times and convert to us.
Definition: pios_delay.c:164
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
uint32_t PIOS_DELAY_GetuSExpired(uint32_t t)
Calculates whether a given time has passed.
Definition: pios_delay.c:193
uint32_t PIOS_DELAY_GetuSSince(uint32_t t)
Calculate time in microseconds since a previous time.
Definition: pios_delay.c:183
static uint32_t us_modulo
Definition: pios_delay.c:39
int32_t PIOS_DELAY_Init(void)
Definition: pios_delay.c:98
static uint32_t us_ticks
Definition: pios_delay.c:38
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140
int32_t PIOS_DELAY_WaituS(uint32_t uS)
Definition: pios_delay.c:116
uint32_t PIOS_DELAY_GetRaw()
Get the raw delay timer, useful for timing.
Definition: pios_delay.c:153