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