/* * Copyright (c) 2017 Oticon A/S * * SPDX-License-Identifier: Apache-2.0 * * SW side of the IRQ handling */ #include #include "irq_ctrl.h" #include "irq_sources.h" #include "os/sim.h" static int currently_running_irq = -1; extern void (* const systemVectors[256])(void); /** * When an interrupt is raised, this function is called to handle it and, if * needed, swap to a re-enabled thread * * Note that even that this function is executing in a Zephyr thread, it is * effectively the model of the interrupt controller passing context to the IRQ * handler and therefore its priority handling */ void posix_interrupt_raised(void) { uint64_t irq_lock; int irq_nbr; irq_lock = hw_irq_ctrl_get_current_lock(); if (irq_lock) { /* "spurious" wakes can happen with interrupts locked */ return; } while ((irq_nbr = hw_irq_ctrl_get_highest_prio_irq()) != -1) { int last_current_running_prio = hw_irq_ctrl_get_cur_prio(); int last_running_irq = currently_running_irq; hw_irq_ctrl_set_cur_prio(hw_irq_ctrl_get_prio(irq_nbr)); hw_irq_ctrl_clear_irq(irq_nbr); currently_running_irq = irq_nbr; systemVectors[irq_nbr + 16](); currently_running_irq = last_running_irq; hw_irq_ctrl_set_cur_prio(last_current_running_prio); } } /** * Thru this function the IRQ controller can raise an immediate interrupt which * will interrupt the SW itself * (this function should only be called from the HW model code, from SW threads) */ void posix_irq_handler_im_from_sw(void) { /* * if a higher priority interrupt than the possibly currently running is * pending we go immediately into irq_handler() to vector into its * handler */ if (hw_irq_ctrl_get_highest_prio_irq() != -1) { posix_interrupt_raised(); } }