1 /* 2 * Copyright (c) 2020 Oticon A/S 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <stdbool.h> 8 #include "timer_model.h" 9 #include <zephyr/arch/posix/posix_soc_if.h> 10 #include <posix_board_if.h> 11 #include <posix_soc.h> 12 13 /** 14 * Replacement to the kernel k_busy_wait() 15 * Will block this thread (and therefore the whole Zephyr) during usec_to_wait 16 * 17 * Note that interrupts may be received in the meanwhile and that therefore this 18 * thread may lose context. 19 * Therefore the wait time may be considerably longer. 20 * 21 * All this function ensures is that it will return after usec_to_wait or later. 22 * 23 * This special arch_busy_wait() is necessary due to how the POSIX arch/SOC INF 24 * models a CPU. Conceptually it could be thought as if the MCU was running 25 * at an infinitely high clock, and therefore no simulated time passes while 26 * executing instructions(*1). 27 * Therefore to be able to busy wait this function does the equivalent of 28 * programming a dedicated timer which will raise a non-maskable interrupt, 29 * and halting the CPU. 30 * 31 * (*1) In reality simulated time is simply not advanced just due to the "MCU" 32 * running. Meaning, the SW running on the MCU is assumed to take 0 time. 33 */ arch_busy_wait(uint32_t usec_to_wait)34void arch_busy_wait(uint32_t usec_to_wait) 35 { 36 uint64_t time_end = hwm_get_time() + usec_to_wait; 37 38 while (hwm_get_time() < time_end) { 39 /* 40 * There may be wakes due to other interrupts including 41 * other threads calling arch_busy_wait 42 */ 43 hwtimer_wake_in_time(time_end); 44 posix_halt_cpu(); 45 } 46 } 47 48 /** 49 * Will block this thread (and therefore the whole Zephyr) during usec_to_waste 50 * 51 * Very similar to arch_busy_wait(), but if an interrupt or context switch 52 * occurs this function will continue waiting after, ensuring that 53 * usec_to_waste are spent in this context, irrespectively of how much more 54 * time would be spent on interrupt handling or possible switched-in tasks. 55 * 56 * Can be used to emulate code execution time. 57 */ posix_cpu_hold(uint32_t usec_to_waste)58void posix_cpu_hold(uint32_t usec_to_waste) 59 { 60 uint64_t time_start; 61 int64_t to_wait = usec_to_waste; 62 63 while (to_wait > 0) { 64 /* 65 * There may be wakes due to other interrupts or nested calls to 66 * cpu_hold in interrupt handlers 67 */ 68 time_start = hwm_get_time(); 69 hwtimer_wake_in_time(time_start + to_wait); 70 posix_change_cpu_state_and_wait(true); 71 to_wait -= hwm_get_time() - time_start; 72 73 posix_irq_handler(); 74 } 75 } 76