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