source: ReferenceDesigns/w3_802.11/c/high_periphs/intc/axi_intc/wlan_platform_intc.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 6.6 KB
Line 
1/** @file wlan_platform_intc.c
2 *
3 *  Wrapper for axi_intc interrupt controller driver
4 *
5 *  @copyright Copyright 2013-2019, Mango Communications. All rights reserved.
6 *          Distributed under the Mango Communications Reference Design License
7 *                See LICENSE.txt included in the design archive or
8 *                at http://mangocomm.com/802.11/license
9 *
10 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
11 */
12
13#include "wlan_mac_common.h"
14#include "wlan_mac_high.h"
15#include "wlan_platform_common.h"
16#include "wlan_platform_intc.h"
17#include "xil_exception.h"
18#include "xintc.h"
19#include "string.h"
20
21static XIntc InterruptController;
22static volatile interrupt_state_t interrupt_state;
23
24
25/**
26 * @brief Connects a peripheral interrupt input to an interrupt service routine
27 *
28 * @param u32 intr_id
29 *      - Interrupt vector ID, from xparameters.h
30 * @param wlan_intr_handler_t* handler
31 *      - Function pointer to ISR
32 * @param void *callback_ref
33 *      - Argument passed to every invocation of the ISR
34 *
35 * @return int
36 *      - Returns a non-zero error if interrupt cannot be connected. Refer to axi_intc driver for error codes.
37 */
38int wlan_platform_interrupt_connect(u32 intr_id, wlan_intr_handler_t handler, void *callback_ref) {
39    int s;
40
41    s = XIntc_Connect(&InterruptController, intr_id, (XInterruptHandler)handler, callback_ref);
42
43    if(s == XST_SUCCESS) s = WLAN_SUCCESS;
44
45    return s;
46}
47
48/**
49 * @brief Enables a peripheral interrupt input
50 *
51 * @param u32 intr_id
52 *      - Interrupt vector ID, from xparameters.h
53*/
54void wlan_platform_interrupt_enable(u32 intr_id) {
55
56    XIntc_Enable(&InterruptController, intr_id);
57
58    return;
59}
60
61/**
62 * @brief Disables a peripheral interrupt input
63 *
64 * @param u32 intr_id
65 *      - Interrupt vector ID, from xparameters.h
66*/
67void wlan_platform_interrupt_disable(u32 intr_id) {
68
69    XIntc_Disable(&InterruptController, intr_id);
70
71    return;
72}
73
74/**
75 * @brief Initializes the axi_intc interrupt controller core
76 *
77 * @param u32 intc_dev_id
78 *      - Device ID for axi_intc core, from xparameters.h
79
80 * @return int
81 *      - Returns an error (-1) if the interrupt controller init fails. Refer to the
82 *      axi_intc driver for specific error codes.
83 *
84 * @note This init function does not enable any interrupt inputs and leaves the interrupt output
85 * disabled. The calling code must later enable the interrupt output by calling
86 * wlan_platform_intc_set_state(INTERRUPTS_ENABLED)
87 */
88int wlan_platform_intc_init(u32 intc_dev_id) {
89    int s;
90
91    /* XIntc_Initialize() doesn't deal well with a reboot
92     * of CPU_HIGH where interrupt peripherals are still
93     * running. We'll explicitly do the following before
94     * re-initializing the interrupt controller:
95     *
96     * - Disable IRQ output signal
97     * - Disable all interrupt sources
98     * - Acknowledge all sources
99     */
100    XIntc_Config *CfgPtr = XIntc_LookupConfig(intc_dev_id);
101
102    XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0);
103    XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0);
104    XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF);
105
106    bzero(&InterruptController, sizeof(XIntc));
107
108    s = XIntc_Initialize(&InterruptController, intc_dev_id);
109    if ((s != XST_SUCCESS)) {
110        xil_printf("wlan_platform_intc.c: XIntc_Initialize failed (%d)\n", s);
111        return s;
112    }
113
114    // The axi_intc driver has two modes for processing multiple asserted interrupts
115    //  We need the "Service All Interrupts" mode where the controller handles interrupts
116    //   in order of priority, but always serves all asserted interrupts before going back
117    //   to a higher-priority, still-asserted interrupt
118    XIntc_SetOptions(&InterruptController, XIN_SVC_ALL_ISRS_OPTION);
119
120    // Connect the interrupt controller's exception handler to the CPU Interrupt exception
121    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
122                                 (Xil_ExceptionHandler) XIntc_DeviceInterruptHandler,
123                                 (void *)((u32)intc_dev_id));
124
125
126    return WLAN_SUCCESS;
127}
128
129/**
130 * @brief Sets the stopped/started state of the interrupt controller
131 *
132 * @param interrupt_state_t new_interrupt_state
133 *      - State to return interrupts. Typically, this argument is the output of a previous
134 *      call to wlan_platform_intc_stop()
135 * @return int
136 *      - Returns an error (-1) if the caller requests to enable interrupts
137 *      but the controller is either not ready or already started. Typically
138 *      the caller can ignore this error, as failing to start an already-started
139 *      controller leaves hardware in the desired state.
140 */
141inline int wlan_platform_intc_set_state(interrupt_state_t new_interrupt_state) {
142    interrupt_state = new_interrupt_state;
143
144    if(interrupt_state == INTERRUPTS_ENABLED) {
145        if(InterruptController.IsReady && InterruptController.IsStarted == 0) {
146            return XIntc_Start(&InterruptController, XIN_REAL_MODE);
147        } else {
148            return WLAN_FAILURE;
149        }
150    } else {
151        return WLAN_SUCCESS;
152    }
153}
154
155/**
156 * @brief Returns the state of the interrupt controller
157 *
158 * This function checks the state of the interrupt controller but does not
159 * alter the state. Callers can use this function to know whether interrupts
160 * are currently enabled or disabled.
161 *
162 * @param None
163 * @returns interrupt_state_t INTERRUPTS_ENABLED or INTERRUPTS_DISABLED
164 */
165interrupt_state_t wlan_platform_intc_get_state() {
166    return interrupt_state;
167}
168
169/**
170 * @brief Starts the interrupt controller
171 *
172 * This function starts the interrupt controller, enabling the interrupt output to the CPU.
173 *
174 * @param None
175 * @return 0 on success
176 */
177inline int wlan_platform_intc_start() {
178    interrupt_state = INTERRUPTS_ENABLED;
179
180    return XIntc_Start(&InterruptController, XIN_REAL_MODE);
181}
182
183/**
184 * @brief Stop the interrupt controller
185 *
186 * This function stops the interrupt controller, effectively pausing interrupts. The function
187 * returns the previous state of interrupts (ENABLED or DISABLED). This return value should
188 * be passed to wlan_platform_intc_set_state() to restore the state of interrupts. This stop/
189 * restore scheme makes nested calls to stop()/set_state() safe
190 *
191 * @param None
192 * @return interrupt_state_t
193 *      - INTERRUPTS_ENABLED if interrupts were enabled at the time this function was called
194 *      - INTERRUPTS_DISABLED if interrupts were disabled at the time this function was called
195 *
196 * @note Interrupts that occur while the interrupt controller is off will be executed once it is
197 * turned back on. They will not be "lost" as the interrupt inputs to the controller will remain
198 * high.
199 */
200inline interrupt_state_t wlan_platform_intc_stop() {
201    interrupt_state_t curr_state = interrupt_state;
202    if(InterruptController.IsReady && InterruptController.IsStarted) XIntc_Stop(&InterruptController);
203    interrupt_state = INTERRUPTS_DISABLED;
204    return curr_state;
205}
206
207
Note: See TracBrowser for help on using the repository browser.