source: ReferenceDesigns/w3_802.11/c/wlan_mac_common_framework/wlan_mac_mailbox_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: 8.1 KB
Line 
1/** @file wlan_mac_mailbox_util.c
2 *  @brief Inter-processor Communication (Mailbox) Framework
3 *
4 *  This contains code common to both CPU_LOW and CPU_HIGH that allows them
5 *  to pass messages to one another.
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#include "stdlib.h"
18#include "stdio.h"
19
20#include "xstatus.h"
21#include "xparameters.h"
22#include "xmbox.h"
23
24#include "wlan_platform_common.h"
25#include "wlan_mac_common.h"
26#include "wlan_mac_mailbox_util.h"
27#include "wlan_cpu_id.h"
28
29#if WLAN_COMPILE_FOR_CPU_HIGH
30#include "wlan_platform_intc.h"
31#endif
32
33
34/*********************** Global Variable Definitions *************************/
35
36/*************************** Variable Definitions ****************************/
37
38
39static XMbox ipc_mailbox;
40
41static platform_common_dev_info_t platform_common_dev_info;
42
43
44/*************************** Functions Prototypes ****************************/
45
46
47/******************************** Functions **********************************/
48
49
50/*****************************************************************************/
51/**
52 * Initialize Mailbox
53 *
54 * This function should be used to initialize
55 * the mailbox peripheral used for IPC messages.  This function supports both
56 * using the mailbox in a polling mode or with interrupts.
57 *
58 * @return  XMbox*              - pointer to mailbox driver instance
59 *****************************************************************************/
60XMbox* init_mailbox() {
61
62    platform_common_dev_info = wlan_platform_common_get_dev_info();
63
64    XMbox_Config *mbox_config_ptr;
65
66    // Initialize the IPC mailbox core
67    mbox_config_ptr = XMbox_LookupConfig(platform_common_dev_info.mailbox_dev_id);
68    XMbox_CfgInitialize(&ipc_mailbox, mbox_config_ptr, mbox_config_ptr->BaseAddress);
69
70    return &ipc_mailbox;
71}
72
73
74#if WLAN_COMPILE_FOR_CPU_HIGH
75#include "wlan_mac_high.h"
76#include "wlan_platform_high.h"
77#endif
78
79/*****************************************************************************/
80/**
81 * Write IPC message
82 *
83 * This function will write an IPC message to the mailbox for the other CPU.
84 * This function is blocking and each message write is atomic in the sense that
85 * it will not be interrupted.
86 *
87 * @param   msg              - Pointer to IPC message structure to write
88 *
89 * @return  int              - Status:
90 *                                 IPC_MBOX_SUCCESS - Message sent successfully
91 *                                 IPC_MBOX_INVALID_MSG - Message invalid
92 *****************************************************************************/
93int write_mailbox_msg(wlan_ipc_msg_t* msg) {
94    // Check that msg points to a valid IPC message
95    if (((msg->msg_id) & IPC_MBOX_MSG_ID_DELIM) != IPC_MBOX_MSG_ID_DELIM) {
96        xil_printf("ERROR (write_mailbox_msg): Message missing delimeter)");
97        return IPC_MBOX_INVALID_MSG;
98    }
99
100    // Check that msg isn't too long
101    if ((msg->num_payload_words) > MAILBOX_MSG_MAX_NUM_WORDS) {
102        xil_printf("ERROR (write_mailbox_msg): Message ID %d too long - %d > %d\n", msg->msg_id, msg->num_payload_words, MAILBOX_MSG_MAX_NUM_WORDS);
103        return IPC_MBOX_INVALID_MSG;
104    }
105
106    // Check that the message payload is 4-byte aligned
107    if( ((msg->num_payload_words) > 0) && ((u32)(msg->payload_ptr) & 0x3)) {
108        xil_printf("ERROR (write_mailbox_msg): Attempted to send message ID %d with unaligned payload\n", msg->msg_id);
109        return IPC_MBOX_INVALID_MSG;
110    }
111
112#if WLAN_COMPILE_FOR_CPU_HIGH
113    interrupt_state_t     prev_interrupt_state;
114    prev_interrupt_state = wlan_platform_intc_stop();
115#endif
116    // Write msg header (first 32b word)
117    XMbox_WriteBlocking(&ipc_mailbox, (u32*)msg, 4);
118
119    // Write msg payload
120    if ((msg->num_payload_words) > 0) {
121        XMbox_WriteBlocking(&ipc_mailbox, (u32*)(msg->payload_ptr), (u32)(4 * (msg->num_payload_words)));
122    }
123
124#if WLAN_COMPILE_FOR_CPU_HIGH
125    wlan_platform_intc_set_state(prev_interrupt_state);
126#endif
127    return IPC_MBOX_SUCCESS;
128}
129
130
131
132/*****************************************************************************/
133/**
134 * Send IPC message
135 *
136 * This function is a wrapper method that will send an IPC message to the other
137 * CPU. This function will create a wlan_ipc_msg_t message and send it using
138 * write_mailbox_msg().  Therefore, this function is blocking.
139 *
140 * @param   msg_id           - IPC Message ID (should not contain IPC_MBOX_MSG_ID_DELIM)
141 * @param   arg              - Optional u8 argument to the IPC message
142 * @param   num_words        - Number of u32 words in the payload
143 * @param   payload          - u32 pointer to the payload
144 *
145 * @return  int              - Status:
146 *                                 IPC_MBOX_SUCCESS - Message sent successfully
147 *                                 IPC_MBOX_INVALID_MSG - Message invalid
148 *****************************************************************************/
149int send_msg(u16 msg_id, u8 arg, u8 num_words, u32* payload) {
150    wlan_ipc_msg_t ipc_msg;
151
152    // Set message fields
153    ipc_msg.msg_id            = IPC_MBOX_MSG_ID(msg_id);
154    ipc_msg.num_payload_words = num_words;
155    ipc_msg.arg0              = arg;
156    ipc_msg.payload_ptr       = payload;
157
158    // Send message
159    return write_mailbox_msg(&ipc_msg);
160}
161
162
163/*****************************************************************************/
164/**
165 * Read IPC message
166 *
167 * This function will read an IPC message from the mailbox from the other CPU.
168 * This function is blocking and will block until entire message is read.
169 *
170 * In the current 802.11 framework, mailbox messages are only read in polling
171 * mode on a single threaded CPU or in an interrupt service routine.  In both
172 * cases, this will effectively make the read operation atomic.  If a mailbox
173 * read needed to occur in an interruptable context, it would required the
174 * interrupt stop / restore code to be added as in write_mailbox_msg().
175 *
176 * @param   msg              - Pointer to IPC message structure to place read data
177 *
178 * @return  int              - Status:
179 *                                 IPC_MBOX_SUCCESS      - Message sent successfully
180 *                                 IPC_MBOX_NO_MSG_AVAIL - No message available
181 *                                 IPC_MBOX_INVALID_MSG  - Message invalid
182 *****************************************************************************/
183int read_mailbox_msg(wlan_ipc_msg_t* msg) {
184    u32 bytes_read;
185    u32 i;
186    u32 trash_bin;
187    int status;
188
189    // Check if there is a message to read
190    if (XMbox_IsEmpty(&ipc_mailbox)) {
191        return IPC_MBOX_INVALID_MSG;
192    }
193
194    // Attempt to read one 32b word from the mailbox into the user-supplied msg
195    status = XMbox_Read(&ipc_mailbox, (u32*)msg, 4, &bytes_read);
196
197    if ((status != XST_SUCCESS) || (bytes_read != 4)) {
198        return IPC_MBOX_NO_MSG_AVAIL;
199    }
200
201    // Check if the received word is a valid msg
202    if (((msg->msg_id) & IPC_MBOX_MSG_ID_DELIM) != IPC_MBOX_MSG_ID_DELIM) {
203        // Flush the mailbox to hopefully get back to a known state
204        XMbox_Flush(&ipc_mailbox);
205        return IPC_MBOX_INVALID_MSG;
206    }
207
208    // Check that msg isn't too long
209    if ((msg->num_payload_words) > MAILBOX_MSG_MAX_NUM_WORDS) {
210        for (i = 0; i < (msg->num_payload_words); i++) {
211            // Read out message into trash since there is not enough space available to hold it
212            XMbox_ReadBlocking(&ipc_mailbox, &trash_bin, 4);
213        }
214
215        return IPC_MBOX_INVALID_MSG;
216    }
217
218    // Read message payload
219    if ((msg->num_payload_words) > 0) {
220        XMbox_ReadBlocking(&ipc_mailbox, (u32*)(msg->payload_ptr), 4 * (msg->num_payload_words));
221    }
222
223    return IPC_MBOX_SUCCESS;
224}
225
226
Note: See TracBrowser for help on using the repository browser.