source: ReferenceDesigns/w3_802.11/c/wlan_w3_common/w3_mac_time_util.c

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

1.8.0 release wlan-mac-se

File size: 9.1 KB
Line 
1/** @file wlan_mac_time_util.c
2 *  @brief Time Utilities
3 *
4 *  This contains code common to both CPU_LOW and CPU_HIGH that allows them
5 *  to interact with the MAC Time and User IO cores.
6 *
7 *  @copyright Copyright 2013-2019, Mango Communications. All rights reserved.
8 *          Distributed under the Mango Communications Reference Design License
9 *              See LICENSE.txt included in the design archive or
10 *              at http://mangocomm.com/802.11/license
11 *
12 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
13 */
14
15/***************************** Include Files *********************************/
16
17// Xilinx / Standard library includes
18#include <xparameters.h>
19#include <xil_io.h>
20
21// WLAN include files
22#include "wlan_mac_common.h"
23#include "wlan_mac_mailbox_util.h"
24#include "wlan_platform_common.h"
25
26#include "include/w3_mac_time_util.h"
27
28
29/*********************** Global Variable Definitions *************************/
30
31
32/*************************** Variable Definitions ****************************/
33
34
35/*************************** Functions Prototypes ****************************/
36
37
38/******************************** Functions **********************************/
39
40
41/*****************************************************************************/
42/**
43 * @brief Get MAC Time
44 *
45 * The Reference Design includes a 64-bit counter that increments every microsecond
46 * and can be updated (ie the MAC time).  This function returns the value of the
47 * counter at the time the function is called and is used throughout the framework
48 * as a timestamp.  The MAC time can be updated by the set_mac_time_usec() and
49 * apply_mac_time_delta_usec() methods.
50 *
51 * @param   None
52 * @return  u64              - Current number of microseconds of MAC time.
53 */
54u64 get_mac_time_usec() {
55    //The MAC time core register interface is only 32-bit, so the 64-bit time
56    // is read from two 32-bit registers and reconstructed here.
57
58    u32 time_high_u32;
59    u32 time_low_u32;
60    u64 time_u64;
61
62    time_high_u32 = Xil_In32(WLAN_MAC_TIME_REG_MAC_TIME_MSB);
63    time_low_u32  = Xil_In32(WLAN_MAC_TIME_REG_MAC_TIME_LSB);
64
65    // Catch very rare race when 32-LSB of 64-bit value wraps between the two 32-bit reads
66    if((time_high_u32 & 0x1) != (Xil_In32(WLAN_MAC_TIME_REG_MAC_TIME_MSB) & 0x1)) {
67        //32-LSB wrapped - start over
68        time_high_u32 = Xil_In32(WLAN_MAC_TIME_REG_MAC_TIME_MSB);
69        time_low_u32  = Xil_In32(WLAN_MAC_TIME_REG_MAC_TIME_LSB);
70    }
71
72    time_u64 = (((u64)time_high_u32) << 32) + ((u64)time_low_u32);
73
74    return time_u64;
75}
76
77
78
79/*****************************************************************************/
80/**
81 * @brief Get System Timestamp (Microsecond Counter)
82 *
83 * The Reference Design includes a 64-bit counter that increments every microsecond
84 * and can not be updated (ie the system time).  This function returns the value of
85 * the counter at the time the function is called and is used throughout the framework
86 * as a timestamp.  The system time can not be updated and reflects the number of
87 * microseconds that has past since the hardware booted.
88 *
89 * @param   None
90 * @return  u64              - Current number of microseconds that have elapsed
91 *                             since the hardware has booted.
92 */
93u64 get_system_time_usec() {
94    // The MAC time core register interface is only 32-bit, so the 64-bit time
95    // is read from two 32-bit registers and reconstructed here.
96
97    u32 time_high_u32;
98    u32 time_low_u32;
99    u64 time_u64;
100
101    time_high_u32 = Xil_In32(WLAN_MAC_TIME_REG_SYSTEM_TIME_MSB);
102    time_low_u32  = Xil_In32(WLAN_MAC_TIME_REG_SYSTEM_TIME_LSB);
103
104    // Catch very rare race when 32-LSB of 64-bit value wraps between the two 32-bit reads
105    if((time_high_u32 & 0x1) != (Xil_In32(WLAN_MAC_TIME_REG_SYSTEM_TIME_MSB) & 0x1) ) {
106        // 32-LSB wrapped - start over
107        time_high_u32 = Xil_In32(WLAN_MAC_TIME_REG_SYSTEM_TIME_MSB);
108        time_low_u32  = Xil_In32(WLAN_MAC_TIME_REG_SYSTEM_TIME_LSB);
109    }
110
111    time_u64 = (((u64)time_high_u32)<<32) + ((u64)time_low_u32);
112
113    return time_u64;
114}
115
116
117#if WLAN_COMPILE_FOR_CPU_HIGH
118// CPU_HIGH implementations
119
120/*****************************************************************************/
121/**
122 * @brief Set MAC time
123 *
124 * The Reference Design includes a 64-bit counter that increments every microsecond
125 * and can be updated (ie the MAC time).  This function sets the counter value.
126 * Some 802.11 handshakes require updating the MAC time to match a partner node's
127 * MAC time value (reception of a beacon, for example)
128 *
129 * @param   new_time         - u64 number of microseconds for the new MAC time of the node
130 * @return  None
131 */
132void set_mac_time_usec(u64 new_time) {
133
134    wlan_ipc_msg_t ipc_msg_to_low;
135    u64 ipc_msg_to_low_payload = new_time;
136
137    // Send message to CPU Low
138    ipc_msg_to_low.msg_id            = IPC_MBOX_MSG_ID(IPC_MBOX_SET_MAC_TIME);
139    ipc_msg_to_low.arg0              = 0; //Indicates that the payload is absolute
140    ipc_msg_to_low.num_payload_words = 2;
141    ipc_msg_to_low.payload_ptr       = (u32*)(&(ipc_msg_to_low_payload));
142
143    write_mailbox_msg(&ipc_msg_to_low);
144
145}
146
147
148
149/*****************************************************************************/
150/**
151 * @brief Apply time delta to MAC time
152 *
153 * The Reference Design includes a 64-bit counter that increments every microsecond
154 * and can be updated (ie the MAC time).  This function updates the counter value
155 * by time_delta microseconds (note that the time delta is an s64 and can be positive
156 * or negative).  Some 802.11 handshakes require updating the MAC time to match a
157 * partner node's MAC time value (reception of a beacon, for example)
158 *
159 * @param   time_delta       - s64 number of microseconds to change the MAC time of the node
160 * @return  None
161 */
162void apply_mac_time_delta_usec(s64 time_delta) {
163
164    wlan_ipc_msg_t ipc_msg_to_low;
165    s64 ipc_msg_to_low_payload = time_delta;
166
167    // Send message to CPU Low
168    ipc_msg_to_low.msg_id            = IPC_MBOX_MSG_ID(IPC_MBOX_SET_MAC_TIME);
169    ipc_msg_to_low.arg0              = 1; //Indicates that the payload is a delta
170    ipc_msg_to_low.num_payload_words = 2;
171    ipc_msg_to_low.payload_ptr       = (u32*)(&(ipc_msg_to_low_payload));
172
173    write_mailbox_msg(&ipc_msg_to_low);
174}
175
176#else
177// CPU_LOW implementations
178
179/*****************************************************************************/
180/**
181 * @brief Set MAC time
182 *
183 * The Reference Design includes a 64-bit counter that increments every microsecond
184 * and can be updated (ie the MAC time).  This function sets the counter value.
185 * Some 802.11 handshakes require updating the MAC time to match a partner node's
186 * MAC time value (reception of a beacon, for example)
187 *
188 * @param   new_time         - u64 number of microseconds for the new MAC time of the node
189 * @return  None
190 */
191void set_mac_time_usec(u64 new_time) {
192
193    Xil_Out32(WLAN_MAC_TIME_REG_NEW_MAC_TIME_MSB, (u32)(new_time >> 32));
194    Xil_Out32(WLAN_MAC_TIME_REG_NEW_MAC_TIME_LSB, (u32)(new_time & 0xFFFFFFFF));
195
196    Xil_Out32(WLAN_MAC_TIME_REG_CONTROL, (Xil_In32(WLAN_MAC_TIME_REG_CONTROL) & ~WLAN_MAC_TIME_CTRL_REG_UPDATE_MAC_TIME));
197    Xil_Out32(WLAN_MAC_TIME_REG_CONTROL, (Xil_In32(WLAN_MAC_TIME_REG_CONTROL) | WLAN_MAC_TIME_CTRL_REG_UPDATE_MAC_TIME));
198    Xil_Out32(WLAN_MAC_TIME_REG_CONTROL, (Xil_In32(WLAN_MAC_TIME_REG_CONTROL) & ~WLAN_MAC_TIME_CTRL_REG_UPDATE_MAC_TIME));
199}
200
201
202
203/*****************************************************************************/
204/**
205 * @brief Apply time delta to MAC time
206 *
207 * The Reference Design includes a 64-bit counter that increments every microsecond
208 * and can be updated (ie the MAC time).  This function updates the counter value
209 * by time_delta microseconds (note that the time delta is an s64 and can be positive
210 * or negative).  Some 802.11 handshakes require updating the MAC time to match a
211 * partner node's MAC time value (reception of a beacon, for example)
212 *
213 * @param   time_delta       - s64 number of microseconds to change the MAC time of the node
214 * @return  None
215 */
216void apply_mac_time_delta_usec(s64 time_delta) {
217
218    u64 new_mac_time;
219
220    // Compute the new MAC time based on the current MAC time and the time delta
221    // The extra 1 usec is empirically determined. This compensates for the time it
222    // takes to read, modify, then write the new MAC time back to the core.
223    new_mac_time = get_mac_time_usec() + time_delta + 1;
224
225    // Update the time in the MAC Time HW core
226    set_mac_time_usec(new_mac_time);
227}
228#endif
229
230
231/*****************************************************************************/
232/**
233 * @brief Sleep delay (in microseconds)
234 *
235 * Function will delay execution for the specified amount of time.
236 *
237 * NOTE:  This function is based on the system timestamp so it will not be affected
238 *     by updates to the MAC time.
239 *
240 * @param   delay            - Time to sleep in microseconds (u64)
241 * @return  None
242 */
243void wlan_usleep(u64 delay) {
244    u64 timestamp = get_system_time_usec();
245    while (get_system_time_usec() < (timestamp + delay)) {}
246    return;
247}
248
249
250
Note: See TracBrowser for help on using the repository browser.