Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2017 Oticon A/S 3 : : * 4 : : * SPDX-License-Identifier: Apache-2.0 5 : : */ 6 : : 7 : : /** 8 : : * For all purposes, Zephyr threads see a CPU running at an infinitely high 9 : : * clock. 10 : : * 11 : : * Therefore, the code will always run until completion after each interrupt, 12 : : * after which arch_cpu_idle() will be called releasing the execution back to 13 : : * the HW models. 14 : : * 15 : : * The HW models raising an interrupt will "awake the cpu" by calling 16 : : * posix_interrupt_raised() which will transfer control to the irq handler, 17 : : * which will run inside SW/Zephyr context. After which a arch_swap() to 18 : : * whatever Zephyr thread may follow. Again, once Zephyr is done, control is 19 : : * given back to the HW models. 20 : : * 21 : : * The Zephyr OS+APP code and the HW models are gated by a mutex + 22 : : * condition as there is no reason to let the zephyr threads run while the 23 : : * HW models run or vice versa 24 : : * 25 : : */ 26 : : 27 : : #include <zephyr/arch/posix/posix_soc_if.h> 28 : : #include "posix_soc.h" 29 : : #include "posix_board_if.h" 30 : : #include "posix_core.h" 31 : : #include "posix_arch_internal.h" 32 : : #include "kernel_internal.h" 33 : : #include "soc.h" 34 : : #include "nce_if.h" 35 : : 36 : : static void *nce_st; 37 : : 38 : 0 : int posix_is_cpu_running(void) 39 : : { 40 : 0 : return nce_is_cpu_running(nce_st); 41 : : } 42 : : 43 : : /** 44 : : * Helper function which changes the status of the CPU (halted or running) 45 : : * and waits until somebody else changes it to the opposite 46 : : * 47 : : * Both HW and SW threads will use this function to transfer control to the 48 : : * other side. 49 : : * 50 : : * This is how the idle thread halts the CPU and gets halted until the HW models 51 : : * raise a new interrupt; and how the HW models awake the CPU, and wait for it 52 : : * to complete and go to idle. 53 : : */ 54 : 0 : void posix_change_cpu_state_and_wait(bool halted) 55 : : { 56 [ # # ]: 0 : if (halted) { 57 : 0 : nce_halt_cpu(nce_st); 58 : : } else { 59 : 0 : nce_wake_cpu(nce_st); 60 : : } 61 : 0 : } 62 : : 63 : : /** 64 : : * HW models shall call this function to "awake the CPU" 65 : : * when they are raising an interrupt 66 : : */ 67 : 0 : void posix_interrupt_raised(void) 68 : : { 69 : : /* We change the CPU to running state (we awake it), and block this 70 : : * thread until the CPU is halted again 71 : : */ 72 : 0 : nce_wake_cpu(nce_st); 73 : 0 : } 74 : : 75 : : 76 : : /** 77 : : * Normally called from arch_cpu_idle(): 78 : : * the idle loop will call this function to set the CPU to "sleep". 79 : : * Others may also call this function with care. The CPU will be set to sleep 80 : : * until some interrupt awakes it. 81 : : * Interrupts should be enabled before calling. 82 : : */ 83 : 0 : void posix_halt_cpu(void) 84 : : { 85 : : /* 86 : : * We set the CPU in the halted state (this blocks this pthread 87 : : * until the CPU is awoken again by the HW models) 88 : : */ 89 : 0 : nce_halt_cpu(nce_st); 90 : : 91 : : /* We are awoken, normally that means some interrupt has just come 92 : : * => let the "irq handler" check if/what interrupt was raised 93 : : * and call the appropriate irq handler. 94 : : * 95 : : * Note that, the interrupt handling may trigger a arch_swap() to 96 : : * another Zephyr thread. When posix_irq_handler() returns, the Zephyr 97 : : * kernel has swapped back to this thread again 98 : : */ 99 : 0 : posix_irq_handler(); 100 : : 101 : : /* 102 : : * And we go back to whatever Zephyr thread called us. 103 : : */ 104 : 0 : } 105 : : 106 : : 107 : : /** 108 : : * Implementation of arch_cpu_atomic_idle() for this SOC 109 : : */ 110 : 0 : void posix_atomic_halt_cpu(unsigned int imask) 111 : : { 112 : 0 : posix_irq_full_unlock(); 113 : 0 : posix_halt_cpu(); 114 : 0 : posix_irq_unlock(imask); 115 : 0 : } 116 : : 117 : : /** 118 : : * The HW models will call this function to "boot" the CPU 119 : : * == spawn the Zephyr init thread, which will then spawn 120 : : * anything it wants, and run until the CPU is set back to idle again 121 : : */ 122 : 1 : void posix_boot_cpu(void) 123 : : { 124 : 1 : nce_st = nce_init(); 125 : 1 : posix_arch_init(); 126 : 1 : nce_boot_cpu(nce_st, z_cstart); 127 : 0 : } 128 : : 129 : : /** 130 : : * Clean up all memory allocated by the SOC and POSIX core 131 : : * 132 : : * This function can be called from both HW and SW threads 133 : : */ 134 : 2 : void posix_soc_clean_up(void) 135 : : { 136 : 2 : nce_terminate(nce_st); 137 : 1 : posix_arch_clean_up(); 138 : 1 : run_native_tasks(_NATIVE_ON_EXIT_LEVEL); 139 : 1 : }