Mbed OS Reference
Loading...
Searching...
No Matches
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
25extern "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 */
78void 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 */
105void wait_ns(unsigned int ns);
106
107/* Optimize if we know the rate */
108#if DEVICE_USTICKER && defined US_TICKER_PERIOD_NUM
109void _wait_us_ticks(uint32_t ticks);
110void _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
116extern 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 */
132inline 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.