source: ReferenceDesigns/w3_802.11/c/high_periphs/timer/axi_timer/wlan_axi_timer.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.2 KB
Line 
1/** @file wlan_axi_timer.c
2 *
3 *  Wrapper for axi_timer peripheral
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 "wlan_platform_timer.h"
18#include "xtmrctr.h"
19
20#define TIMER_NUMBER 0 // currently only timer #0 is used
21
22void timer_isr(void* instance_ptr);
23int timer_null_callback();
24
25static XTmrCtr timer_instance;
26
27static u32 timer_interval;
28function_ptr_t timer_callback;
29
30/*****************************************************************************/
31/**
32 * Timer initialization
33 *
34 * @param   timer_dev_id - Timer peripheral device ID, from xparameters
35 * @param   interval     - Timer interval in clock ticks
36 * @param   callback     - Function timer ISR should call on every interrupt
37 *
38 * @return  status - WLAN_SUCCESS or WLAN_FAILURE
39 *
40 *****************************************************************************/
41int wlan_timer_init(int timer_dev_id, u32 interval) {
42
43    // Initialize the timer
44    // The driver for the timer does not handle a reboot of CPU_HIGH
45    // gracefully. Before initializing it, we should stop any running
46    // timers. Note: we cannot use the official XTmrCtr_Stop() function
47    // for this since it requires that the timer instance be initialized.
48    int status;
49    u32 csr_reg;
50    XTmrCtr_Config *TmrCtrConfigPtr = XTmrCtr_LookupConfig(timer_dev_id);
51
52    // Assign a safe do-nothing callback, catches unlikely case of this init() failing below
53    //  but an interrupt still occurring later
54    timer_callback = timer_null_callback;
55
56    if(interval < 100) {
57        xil_printf("ERROR (wlan_timer_init): interval %d too small, must be >100\n", interval);
58        return WLAN_FAILURE;
59    }
60
61    timer_interval = interval;
62
63    // Disable both timers in the core
64    if(TmrCtrConfigPtr != NULL) {
65        csr_reg = XTmrCtr_ReadReg(TmrCtrConfigPtr->BaseAddress, 0, XTC_TCSR_OFFSET);
66        csr_reg &= ~(XTC_CSR_ENABLE_TMR_MASK);
67        XTmrCtr_WriteReg(TmrCtrConfigPtr->BaseAddress, 0, XTC_TCSR_OFFSET, csr_reg);
68
69        csr_reg = XTmrCtr_ReadReg(TmrCtrConfigPtr->BaseAddress, 1, XTC_TCSR_OFFSET);
70        csr_reg &= ~(XTC_CSR_ENABLE_TMR_MASK);
71        XTmrCtr_WriteReg(TmrCtrConfigPtr->BaseAddress, 1, XTC_TCSR_OFFSET, csr_reg);
72
73        status = XTmrCtr_Initialize(&timer_instance, timer_dev_id);
74        if (status != XST_SUCCESS) {
75            xil_printf("ERROR: XTmrCtr_Initialize failed with status %d\n", status);
76            return WLAN_FAILURE;
77        }
78
79        // Configure timer 0 for use by the platform
80        //  Timer counts down from the software-set value, interrupt occurs at 0
81        //  Timer is automatically reloaded when it wraps, software only needs to acknowledge the interrupt
82        XTmrCtr_SetResetValue(&timer_instance, TIMER_NUMBER, timer_interval);
83        XTmrCtr_SetOptions(&timer_instance, TIMER_NUMBER, XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION);
84
85        return WLAN_SUCCESS;
86
87    } else {
88        //Could not find XTmrCtr_Config for the timer
89        xil_printf("ERROR: timer init failed - no config struct found by XTmrCtr_LookupConfig()\n");
90        return WLAN_FAILURE;
91    }
92}
93
94/*****************************************************************************/
95/**
96 * Sets up timer interrupt
97 *
98 * @param   int_id - Interrupt ID for timer peripheral, from xparameters
99 *
100 * @return  status - WLAN_SUCCESS or WLAN_FAILURE
101 *
102 *****************************************************************************/
103int wlan_timer_setup_interrupt(int int_id, function_ptr_t callback) {
104    int status;
105
106    timer_callback = callback;
107
108    status = wlan_platform_interrupt_connect(int_id, timer_isr, &timer_instance);
109    wlan_platform_interrupt_enable(int_id);
110
111    return status;
112}
113
114
115/*****************************************************************************/
116/**
117 * Starts the timer. Timer is always reset to its interval when started. First
118 * timer interrupt will occur one interval after calling this function.
119 *
120 * @return  None
121 *
122 *****************************************************************************/
123void wlan_timer_start() {
124    // Reset timer counter to the full interval value n every start
125    // The first timer interrupt will occur one interval after the timer is started
126    XTmrCtr_SetResetValue(&timer_instance, TIMER_NUMBER, timer_interval);
127    XTmrCtr_Start(&timer_instance, TIMER_NUMBER);
128}
129
130/*****************************************************************************/
131/**
132 * Stops the timer
133 *
134 * @return  WLAN_SUCCESS (cannot fail)
135 *
136 *****************************************************************************/
137int wlan_timer_stop() {
138    XTmrCtr_Stop(&timer_instance, TIMER_NUMBER);
139    return WLAN_SUCCESS;
140}
141
142/*****************************************************************************/
143/**
144 * Timer interrupt handler
145 *
146 * @param   instance_ptr     - Pointer to the timer instance
147 *
148 * @return  None
149 *
150 * @note    This function is based on the timer's default ISR XTmrCtr_InterruptHandler
151 *          This version only checks one timer number and calls the framework's callback
152 *          directly, instead of via the timer config struct Handler field
153 *
154 *****************************************************************************/
155void timer_isr(void* instance_ptr) {
156
157    XTmrCtr* timer_ptr;
158    u32 base_addr;
159    u32 csr_reg;
160
161    // Verify inputs are valid
162    if (instance_ptr == NULL) { return; }
163
164    timer_ptr = (XTmrCtr *)instance_ptr;
165    base_addr = timer_ptr->BaseAddress;
166
167    // Read Control / Status register
168    csr_reg = XTmrCtr_ReadReg(base_addr, TIMER_NUMBER, XTC_TCSR_OFFSET);
169
170    // Check if interrupt is enabled and interrupt is asserted
171    if((csr_reg & XTC_CSR_ENABLE_INT_MASK) && (csr_reg & XTC_CSR_INT_OCCURED_MASK)) {
172
173        // Increment statistics for the number of interrupts
174        timer_ptr->Stats.Interrupts++;
175
176        // Call the function set by the platform/framework
177        timer_callback();
178
179        // Acknowledge the interrupt
180        //  The INT_OCCURED_MASK bit is self-clearing - code only needs to write 1 to clear the interrupt
181        XTmrCtr_WriteReg(base_addr, TIMER_NUMBER, XTC_TCSR_OFFSET, (csr_reg | XTC_CSR_INT_OCCURED_MASK));
182    }
183
184    return;
185}
186
187int timer_null_callback() {
188    return 0;
189}
Note: See TracBrowser for help on using the repository browser.