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 : }
|