1 /*
2  * Copyright (c) 2017 Oticon A/S
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include "fake_timer.h"
11 #include <zephyr/arch/posix/posix_soc_if.h>
12 #include <posix_board_if.h>
13 #include <posix_soc.h>
14 #include "nsi_hw_scheduler.h"
15 
16 /**
17  * Replacement to the kernel k_busy_wait()
18  * Will block this thread (and therefore the whole Zephyr) during usec_to_wait
19  *
20  * Note that interrupts may be received in the meanwhile and that therefore this
21  * thread may lose context.
22  * Therefore the wait time may be considerably longer.
23  *
24  * All this function ensures is that it will return after usec_to_wait or later.
25  */
arch_busy_wait(uint32_t usec_to_wait)26 void arch_busy_wait(uint32_t usec_to_wait)
27 {
28 	bs_time_t time_end = nsi_hws_get_time() + usec_to_wait;
29 
30 	while (nsi_hws_get_time() < time_end) {
31 		/*
32 		 * There may be wakes due to other interrupts or nested calls to
33 		 * k_busy_wait in interrupt handlers
34 		 */
35 		nhw_fake_timer_wake_in_time(CONFIG_NATIVE_SIMULATOR_MCU_N, time_end);
36 		posix_halt_cpu();
37 	}
38 }
39 
40 /**
41  * Will block this thread (and therefore the whole Zephyr) during usec_to_waste
42  *
43  * Very similar to arch_busy_wait(), but if an interrupt or context switch
44  * occurs this function will continue waiting after, ensuring that
45  * usec_to_waste are spent in this context, irrespectively of how much more
46  * time would be spent on interrupt handling or possible switched-in tasks.
47  *
48  * Can be used to emulate code execution time.
49  */
posix_cpu_hold(uint32_t usec_to_waste)50 void posix_cpu_hold(uint32_t usec_to_waste)
51 {
52 	bs_time_t time_start;
53 	int64_t to_wait = usec_to_waste;
54 
55 	while (to_wait > 0) {
56 		/*
57 		 * There may be wakes due to other interrupts or nested calls to
58 		 * cpu_hold in interrupt handlers
59 		 */
60 		time_start = nsi_hws_get_time();
61 		nhw_fake_timer_wake_in_time(CONFIG_NATIVE_SIMULATOR_MCU_N, time_start + to_wait);
62 		posix_change_cpu_state_and_wait(true);
63 		to_wait -= nsi_hws_get_time() - time_start;
64 
65 		posix_irq_handler();
66 	}
67 }
68