1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/timer/system_timer.h>
9 #include <zephyr/sys_clock.h>
10 #include <kernel_arch_interface.h>
11 
z_impl_k_busy_wait(uint32_t usec_to_wait)12 void z_impl_k_busy_wait(uint32_t usec_to_wait)
13 {
14 	SYS_PORT_TRACING_FUNC_ENTER(k_thread, busy_wait, usec_to_wait);
15 	if (usec_to_wait == 0U) {
16 		SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait);
17 		return;
18 	}
19 
20 #if defined(CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT)
21 	arch_busy_wait(usec_to_wait);
22 #elif defined(CONFIG_SYS_CLOCK_EXISTS)
23 	uint32_t start_cycles = k_cycle_get_32();
24 
25 	/* use 64-bit math to prevent overflow when multiplying */
26 	uint32_t cycles_to_wait = (uint32_t)(
27 		(uint64_t)usec_to_wait *
28 		(uint64_t)sys_clock_hw_cycles_per_sec() /
29 		(uint64_t)USEC_PER_SEC
30 	);
31 
32 	for (;;) {
33 		uint32_t current_cycles = k_cycle_get_32();
34 
35 		/* this handles the rollover on an unsigned 32-bit value */
36 		if ((current_cycles - start_cycles) >= cycles_to_wait) {
37 			break;
38 		}
39 	}
40 #else
41 	/*
42 	 * Crude busy loop for the purpose of being able to configure out
43 	 * system timer support.
44 	 */
45 	unsigned int loops_per_usec = CONFIG_BUSYWAIT_CPU_LOOPS_PER_USEC;
46 	unsigned int loops = loops_per_usec * usec_to_wait;
47 
48 	while (loops-- > 0) {
49 		arch_nop();
50 	}
51 #endif
52 
53 	SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait);
54 }
55 
56 #ifdef CONFIG_USERSPACE
z_vrfy_k_busy_wait(uint32_t usec_to_wait)57 static inline void z_vrfy_k_busy_wait(uint32_t usec_to_wait)
58 {
59 	z_impl_k_busy_wait(usec_to_wait);
60 }
61 #include <syscalls/k_busy_wait_mrsh.c>
62 #endif /* CONFIG_USERSPACE */
63