1 /**
2  ****************************************************************************************
3  *
4  * @file ke_msg.h
5  *
6  * @brief This file contains the definition related to message scheduling.
7  *
8  * Copyright (C) RivieraWaves 2009-2015
9  *
10  *
11  ****************************************************************************************
12  */
13 
14 #ifndef _KE_MSG_H_
15 #define _KE_MSG_H_
16 
17 /**
18  ****************************************************************************************
19  * @defgroup MSG Message Exchange
20  * @ingroup KERNEL
21  * @brief Message scheduling module.
22  *
23  * The MSG module implements message scheduling functions.
24 
25  * A kernel message has an ID, a receiver task ID and a source task ID.
26  * In most cases, it also has parameters which are defined in
27  * a structure dynamically embedded in the message structure,
28  * so the whole message will be managed internally as one block.
29  *
30  * A message can also have one extra parameter which is referenced
31  * in the normal parameter structure. This extra block is assumed
32  * to be large by the kernel and will be moved by DMA if needed.
33  * This feature allows moving MMPDU from LMAC to UMAC.
34  *
35  * In order to send a message, a function first have to allocate
36  * the memory for this message. It can be done with the wrapper
37  * macro KE_MSG_ALLOC() (which will call ke_msg_alloc()).
38 
39  * The message can then be sent with ke_msg_send(). The kernel
40  * will take care of freeing the allocated memory.
41 
42  * If the message has no parameters, the ke_msg_send_basic() function
43  * can be used.
44  *
45  * @{
46  ****************************************************************************************
47  */
48 
49 #include <stddef.h>          // standard definition
50 #include <stdint.h>          // standard integer
51 #include <stdbool.h>         // standard boolean
52 #include "ble_arch.h"       // architectural definition
53 //#include "compiler.h"        // compiler definition
54 #include "ke_config.h"       // kernel configuration
55 #include "co_list.h"         // list definition
56 
57 
58 /// Task Identifier. Composed by the task type and the task index.
59 typedef uint16_t ke_task_id_t;
60 
61 /// Builds the task identifier from the type and the index of that task.
62 #define KE_BUILD_ID(type, index) ( (ke_task_id_t)(((index) << 8)|(type)) )
63 
64 /// Retrieves task type from task id.
65 #define KE_TYPE_GET(ke_task_id) ((ke_task_id) & 0xFF)
66 
67 /// Retrieves task index number from task id.
68 #define KE_IDX_GET(ke_task_id) (((ke_task_id) >> 8) & 0xFF)
69 
70 /// Task State
71 typedef uint8_t ke_state_t;
72 
73 /// Message Identifier. The number of messages is limited to 0xFFFF.
74 /// The message ID is divided in two parts:
75 /// bits[15~8]: task index (no more than 255 tasks support)
76 /// bits[7~0]: message index(no more than 255 messages per task)
77 typedef uint16_t ke_msg_id_t;
78 
79 /// Message structure.
80 struct ke_msg
81 {
82     struct co_list_hdr hdr;     ///< List header for chaining
83 
84     ke_msg_id_t     id;         ///< Message id.
85     ke_task_id_t    dest_id;    ///< Destination kernel identifier.
86     ke_task_id_t    src_id;     ///< Source kernel identifier.
87     uint16_t        param_len;  ///< Parameter embedded struct length.
88     uint32_t        param[1];   ///< Parameter embedded struct. Must be word-aligned.
89 };
90 
91 
92 /// Status returned by a task when handling a message
93 enum ke_msg_status_tag
94 {
95     KE_MSG_CONSUMED = 0, ///< consumed, msg and ext are freed by the kernel
96     KE_MSG_NO_FREE,      ///< consumed, nothing is freed by the kernel
97     KE_MSG_SAVED,        ///< not consumed, will be pushed in the saved queue
98 };
99 
100 /**
101  ****************************************************************************************
102  * @brief Convert a parameter pointer to a message pointer
103  *
104  * @param[in]  param_ptr Pointer to the parameter member of a ke_msg
105  *                       Usually retrieved by a ke_msg_alloc()
106  *
107  * @return The pointer to the ke_msg
108  ****************************************************************************************
109  */
ke_param2msg(void const * param_ptr)110 __INLINE struct ke_msg * ke_param2msg(void const *param_ptr)
111 {
112     return (struct ke_msg*) (((uint8_t*)param_ptr) - offsetof(struct ke_msg, param));
113 }
114 
115 /**
116  ****************************************************************************************
117  * @brief Convert a message pointer to a parameter pointer
118  *
119  * @param[in]  msg Pointer to the ke_msg.
120  *
121  * @return The pointer to the param member
122  ****************************************************************************************
123  */
ke_msg2param(struct ke_msg const * msg)124 __INLINE void * ke_msg2param(struct ke_msg const *msg)
125 {
126     return (void*) (((uint8_t*) msg) + offsetof(struct ke_msg, param));
127 }
128 
129 /**
130  ****************************************************************************************
131  * @brief Convenient wrapper to ke_msg_alloc()
132  *
133  * This macro calls ke_msg_alloc() and cast the returned pointer to the
134  * appropriate structure. Can only be used if a parameter structure exists
135  * for this message (otherwise, use ke_msg_send_basic()).
136  *
137  * @param[in] id        Message identifier
138  * @param[in] dest      Destination Identifier
139  * @param[in] src       Source Identifier
140  * @param[in] param_str parameter structure tag
141  *
142  * @return Pointer to the parameter member of the ke_msg.
143  ****************************************************************************************
144  */
145 #define KE_MSG_ALLOC(id, dest, src, param_str) \
146     (struct param_str*) ke_msg_alloc(id, dest, src, sizeof(struct param_str))
147 
148 /**
149  ****************************************************************************************
150  * @brief Convenient wrapper to ke_msg_free()
151  *
152  * This macro calls ke_msg_free() with the appropriate msg pointer as parameter, according
153  * to the message parameter pointer passed.
154  *
155  * @param[in] param_ptr parameter structure pointer
156  ****************************************************************************************
157  */
158 #define KE_MSG_FREE(param_ptr) ke_msg_free(ke_param2msg((param_ptr)))
159 
160 /**
161  ****************************************************************************************
162  * @brief Convenient wrapper to ke_msg_alloc()
163  *
164  * This macro calls ke_msg_alloc() and cast the returned pointer to the
165  * appropriate structure with a variable length. Can only be used if a parameter structure exists
166  * for this message (otherwise, use ke_msg_send_basic()).Can only be used if the data array is
167  * located at the end of the structure.
168  *
169  * @param[in] id        Message identifier
170  * @param[in] dest      Destination Identifier
171  * @param[in] src       Source Identifier
172  * @param[in] param_str parameter structure tag
173  * @param[in] length    length for the data
174  *
175  * @return Pointer to the parameter member of the ke_msg.
176  ****************************************************************************************
177  */
178 #define KE_MSG_ALLOC_DYN(id, dest, src, param_str,length)  (struct param_str*)ke_msg_alloc(id, dest, src, \
179     (sizeof(struct param_str) + (length)));
180 
181 /**
182  ****************************************************************************************
183  * @brief Allocate memory for a message
184  *
185  * This primitive allocates memory for a message that has to be sent. The memory
186  * is allocated dynamically on the heap and the length of the variable parameter
187  * structure has to be provided in order to allocate the correct size.
188  *
189  * Several additional parameters are provided which will be preset in the message
190  * and which may be used internally to choose the kind of memory to allocate.
191  *
192  * The memory allocated will be automatically freed by the kernel, after the
193  * pointer has been sent to ke_msg_send(). If the message is not sent, it must
194  * be freed explicitly with ke_msg_free().
195  *
196  * Allocation failure is considered critical and should not happen.
197  *
198  * @param[in] id        Message identifier
199  * @param[in] dest_id   Destination Task Identifier
200  * @param[in] src_id    Source Task Identifier
201  * @param[in] param_len Size of the message parameters to be allocated
202  *
203  * @return Pointer to the parameter member of the ke_msg. If the parameter
204  *         structure is empty, the pointer will point to the end of the message
205  *         and should not be used (except to retrieve the message pointer or to
206  *         send the message)
207  ****************************************************************************************
208  */
209 void *ke_msg_alloc(ke_msg_id_t const id, ke_task_id_t const dest_id,
210                    ke_task_id_t const src_id, uint16_t const param_len);
211 
212 /**
213  ****************************************************************************************
214  * @brief Message sending.
215  *
216  * Send a message previously allocated with any ke_msg_alloc()-like functions.
217  *
218  * The kernel will take care of freeing the message memory.
219  *
220  * Once the function have been called, it is not possible to access its data
221  * anymore as the kernel may have copied the message and freed the original
222  * memory.
223  *
224  * @param[in] param_ptr  Pointer to the parameter member of the message that
225  *                       should be sent.
226  ****************************************************************************************
227  */
228 
229 void ke_msg_send(void const *param_ptr);
230 
231 /**
232  ****************************************************************************************
233  * @brief Basic message sending.
234  *
235  * Send a message that has a zero length parameter member. No allocation is
236  * required as it will be done internally.
237  *
238  * @param[in] id        Message identifier
239  * @param[in] dest_id   Destination Identifier
240  * @param[in] src_id    Source Identifier
241  ****************************************************************************************
242  */
243 void ke_msg_send_basic(ke_msg_id_t const id, ke_task_id_t const dest_id, ke_task_id_t const src_id);
244 
245 /**
246  ****************************************************************************************
247  * @brief Message forwarding.
248  *
249  * Forward a message to another task by changing its destination and source tasks IDs.
250  *
251  * @param[in] param_ptr  Pointer to the parameter member of the message that
252  *                       should be sent.
253  * @param[in] dest_id New destination task of the message.
254  * @param[in] src_id New source task of the message.
255  ****************************************************************************************
256  */
257 void ke_msg_forward(void const *param_ptr, ke_task_id_t const dest_id, ke_task_id_t const src_id);
258 
259 /**
260  ****************************************************************************************
261  * @brief Message forwarding.
262  *
263  * Forward a message to another task by changing its message ID and its destination and source tasks IDs.
264  *
265  * @param[in] param_ptr  Pointer to the parameter member of the message that
266  *                       should be sent.
267  * @param[in] msg_id  New ID of the message.
268  * @param[in] dest_id New destination task of the message.
269  * @param[in] src_id  New source task of the message.
270  ****************************************************************************************
271  */
272 void ke_msg_forward_new_id(void const *param_ptr,
273                            ke_msg_id_t const msg_id, ke_task_id_t const dest_id, ke_task_id_t const src_id);
274 
275 /**
276  ****************************************************************************************
277  * @brief Free allocated message
278  *
279  * @param[in] msg   Pointer to the message to be freed (not the parameter member!)
280  ****************************************************************************************
281  */
282 void ke_msg_free(struct ke_msg const *param);
283 
284 
285 
286 /**
287  ****************************************************************************************
288  * @brief Retrieve destination task identifier of a kernel message
289  *
290  * @param[in] param_ptr  Pointer to the parameter member of the message.
291  *
292  * @return message destination task
293  ****************************************************************************************
294  */
295 ke_msg_id_t ke_msg_dest_id_get(void const *param_ptr);
296 
297 
298 
299 /**
300  ****************************************************************************************
301  * @brief Retrieve source task identifier of a kernel message
302  *
303  * @param[in] param_ptr  Pointer to the parameter member of the message.
304  *
305  * @return message source task
306  ****************************************************************************************
307  */
308 ke_msg_id_t ke_msg_src_id_get(void const *param_ptr);
309 
310 /**
311  * Used to know if message is present in kernel queue or not.
312  *
313  * @param[in]  param_ptr  Pointer to the parameter member of the message.
314  *
315  * @return True if message is present in Kernel Queue, False else.
316  */
317 bool ke_msg_in_queue(void const *param_ptr);
318 /// @} MSG
319 
320 #endif // _KE_MSG_H_
321