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