Mistake on this page?
Report an issue in GitHub or email us
mbed_wait_api.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2019 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef MBED_WAIT_API_H
18 #define MBED_WAIT_API_H
19 
20 #include "platform/mbed_toolchain.h"
21 #include "platform/mbed_atomic.h"
22 #include "device.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /** \addtogroup platform-public-api */
29 /** @{*/
30 
31 /**
32  * \defgroup platform_wait_api wait_api functions
33  * @{
34  */
35 
36 /** Generic wait functions.
37  *
38  * These provide simple NOP type wait capabilities.
39  *
40  * Example:
41  * @code
42  * #include "mbed.h"
43  *
44  * // Blinking rate in milliseconds
45  * #define BLINKING_RATE_MS 500
46  * DigitalOut led(LED2);
47  * InterruptIn button(SW2);
48  *
49  * void blink_led() {
50  * led = 1;
51  * wait_us(BLINKING_RATE_MS * 1000);
52  * led = 0;
53  * }
54  *
55  * int main() {
56  * button.fall(&blink_led);
57  * while(1) {
58  * // Do nothing
59  * }
60  * }
61  * @endcode
62  */
63 
64 /** Waits a number of microseconds.
65  *
66  * @param us the whole number of microseconds to wait
67  *
68  * @note
69  * This function always spins to get the exact number of microseconds.
70  * This will affect power and multithread performance. Therefore, spinning for
71  * millisecond wait is not recommended, and ThisThread::sleep_for should
72  * be used instead.
73  *
74  * @note You may call this function from ISR context, but large delays may
75  * impact system stability - interrupt handlers should take less than
76  * 50us.
77  */
78 void wait_us(int us);
79 
80 /** Waits a number of nanoseconds.
81  *
82  * This function spins the CPU to produce a small delay. It should normally
83  * only be used for delays of 10us (10000ns) or less. As it is calculated
84  * based on the expected execution time of a software loop, it may well run
85  * slower than requested based on activity from other threads and interrupts.
86  * If greater precision is required, this can be called from inside a critical
87  * section.
88  *
89  * @param ns the number of nanoseconds to wait
90  *
91  * @note
92  * wait_us() will likely give more precise time than wait_ns for large-enough
93  * delays, as it is based on a timer, but its set-up time may be excessive
94  * for the smallest microsecond counts, at which point wait_ns() is better.
95  *
96  * @note
97  * Any delay larger than a millisecond (1000000ns) is liable to cause
98  * overflow in the internal loop calculation. You shouldn't normally be
99  * using this for such large delays anyway in real code, but be aware if
100  * calibrating. Make repeated calls for longer test runs.
101  *
102  * @note You may call this function from ISR context.
103  *
104  */
105 void wait_ns(unsigned int ns);
106 
107 /* Optimize if we know the rate */
108 #if DEVICE_USTICKER && defined US_TICKER_PERIOD_NUM
109 void _wait_us_ticks(uint32_t ticks);
110 void _wait_us_generic(unsigned int us);
111 
112 /* Further optimization if we know us_ticker is always running */
113 #if MBED_CONF_TARGET_INIT_US_TICKER_AT_BOOT
114 #define _us_ticker_is_initialized true
115 #else
116 extern bool _us_ticker_initialized;
117 #define _us_ticker_is_initialized core_util_atomic_load_bool(&_us_ticker_initialized)
118 #endif
119 
120 #if US_TICKER_PERIOD_DEN == 1 && (US_TICKER_MASK * US_TICKER_PERIOD_NUM) >= 0xFFFFFFFF
121 /* Ticker is wide and slow enough to have full 32-bit range - can always use it directly */
122 #define _us_is_small_enough(us) true
123 #else
124 /* Threshold is determined by specification of us_ticker_api.h - smallest possible
125  * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves
126  * headroom for the multiplication in 32 bits.
127  */
128 #define _us_is_small_enough(us) ((us) < 8192)
129 #endif
130 
131 /* Speed optimisation for small wait_us. Care taken to preserve binary compatibility */
132 inline void _wait_us_inline(unsigned int us)
133 {
134  /* Threshold is determined by specification of us_ticker_api.h - smallest possible
135  * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves
136  * headroom for the multiplication in 32 bits.
137  */
138  if (_us_is_small_enough(us) && _us_ticker_is_initialized) {
139  const uint32_t ticks = ((us * US_TICKER_PERIOD_DEN) + US_TICKER_PERIOD_NUM - 1) / US_TICKER_PERIOD_NUM;
140  _wait_us_ticks(ticks);
141  } else {
142  _wait_us_generic(us);
143  }
144 }
145 
146 #define wait_us(us) _wait_us_inline(us)
147 #endif // Known-rate, initialised timer
148 
149 #ifdef __cplusplus
150 }
151 #endif
152 
153 #endif
154 
155 /** @}*/
156 /** @}*/
void wait_us(int us)
Generic wait functions.
void wait_ns(unsigned int ns)
Waits a number of nanoseconds.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.