Branch data Line data Source code
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 : : */ 34 : 0 : void arch_busy_wait(uint32_t usec_to_wait) 35 : : { 36 : 0 : uint64_t time_end = hwm_get_time() + usec_to_wait; 37 : : 38 [ # # ]: 0 : 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 : 0 : hwtimer_wake_in_time(time_end); 44 : 0 : posix_halt_cpu(); 45 : : } 46 : 0 : } 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 : : */ 58 : 0 : void posix_cpu_hold(uint32_t usec_to_waste) 59 : : { 60 : 0 : uint64_t time_start; 61 : 0 : int64_t to_wait = usec_to_waste; 62 : : 63 [ # # ]: 0 : 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 : 0 : time_start = hwm_get_time(); 69 : 0 : hwtimer_wake_in_time(time_start + to_wait); 70 : 0 : posix_change_cpu_state_and_wait(true); 71 : 0 : to_wait -= hwm_get_time() - time_start; 72 : : 73 : 0 : posix_irq_handler(); 74 : : } 75 : 0 : }