HAL
HAL layer above libopencm3 library.
 All Files Functions Macros Groups Pages
delay.h
Go to the documentation of this file.
1 /*
2  * This file is part of the HAL project, inline library above libopencm3.
3  *
4  * This library is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 /** @defgroup DELAY_module DELAY module
18  *
19  * @brief Spin-waiting blocking API
20  *
21  * @ingroup modules
22  *
23  * LGPL License Terms @ref lgpl_license
24  */
25 #ifndef HAL_DELAY_H_INCLUDED
26 #define HAL_DELAY_H_INCLUDED
27 
28 #include <hal/common.h>
29 
30 /**@{*/
31 
32 /*****************************************************************************/
33 /* API definitions */
34 /*****************************************************************************/
35 
36 /*****************************************************************************/
37 /* API Functions */
38 /*****************************************************************************/
39 
40 BEGIN_DECLS
41 
42 /*---------------------------------------------------------------------------*/
43 /** @brief Spin-wait delay, spinning specified amount of processor cycles
44  *
45  * @note this function can be used for delays of max 2500000 cycles.
46  * For larger delays, please consider using timers or other waiting techniques.
47  *
48  * @param[in] cycles Cycles count need to spent in spin-wait
49  */
50 static void delay_cycles(const int64_t cycles);
51 
52 /*---------------------------------------------------------------------------*/
53 /** @brief Spin-wait delay, spinning specified amount of microseconds
54  *
55  * @note this function can be used for delays max 25 sec @ 168MHz CPU clock, or
56  * max 525 sec @ 8MHz CPU clock! For larger delays, please consider using
57  * timers or other waiting techniques.
58  *
59  * @param[in] us Microseconds needed to spin wait.
60  * @param[in] cpufreq Current CPU frequency in Hz
61  */
62 static void delay_us(uint32_t us, uint64_t cpufreq);
63 
64 /*---------------------------------------------------------------------------*/
65 /** @brief Spin-wait delay, spinning specified amount of microseconds
66  *
67  * @note this function can be used for delays max 25 sec @ 168MHz CPU clock, or
68  * max 525 sec @ 8MHz CPU clock! For larger delays, please consider using
69  * timers or other waiting techniques.
70  *
71  * @param[in] ms Milliseconds needed to spin wait.
72  * @param[in] cpufreq Current CPU frequency in Hz
73  */
74 static void delay_ms(uint32_t ms, uint64_t cpufreq);
75 
76 END_DECLS
77 
78 /**@}*/
79 
80 /*****************************************************************************/
81 /* Architecture dependent implementations */
82 /*****************************************************************************/
83 
84 /* 3 Tcyc per tick, 4Tcyc call/ret, 1Tcyc hidden reg assignment */
85 static void _delay_3t(uint32_t cycles) __attribute__((naked))
86 {
87  asm __volatile__ (
88  "1: \n"
89  " subs %[cyc],#1 \n" /* 1Tck */
90  " bne 1b \n" /* 2Tck */
91  " bx lr \n"
92  : /* No output */
93  : [cyc] "r" (cycles)
94  : /* No memory */
95  );
96 }
97 
98 
99 INLINE void delay_cycles(const int64_t cycles)
100 {
101  if (cycles <= 0)
102  return;
103 
104  switch (cycles % 3) {
105  default:
106  case 0: break;
107  case 1: asm __volatile__ ("nop"); break;
108  case 2: asm __volatile__ ("nop\nnop"); break;
109  }
110 
111  if (cycles > 3)
112  _delay_3t((uint32_t)(cycles / 3));
113  else /* same delay as the function call */
114  asm __volatile__ ("nop\nnop\nnop\nnop\nnop\nnop\n");
115 }
116 
117 
118 /* max 25 sec @ 168MHz! */
119 /* max 525 sec @ 8MHz! */
120 INLINE void delay_us(uint32_t us, uint64_t cpufreq)
121 {
122  if (us == 0)
123  return;
124 
125  delay_cycles(us * cpufreq / 1000000 - 6);
126 }
127 
128 /* max 25 sec @ 168MHz! */
129 /* max 525 sec @ 8MHz! */
130 INLINE void delay_ms(uint32_t ms, uint64_t cpufreq)
131 {
132  if (ms == 0)
133  return;
134 
135  delay_cycles(ms * cpufreq / 1000 - 6);
136 }
137 
138 #endif /* HAL_DELAY_H_INCLUDED */