WXK
2025-01-21 8f1a91a8ec98e430cfe4357bda099d495917198e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * Copyright (c) 2017 Oticon A/S
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * SW side of the IRQ handling
 */
 
#include <stdint.h>
#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();
    }
}