1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36 package ti.sysbios.knl;
37
38 import xdc.rov.ViewInfo;
39
40 import xdc.runtime.IHeap;
41
42 /*!
43 * ======== Mailbox ========
44 * Mailbox Manager
45 *
46 * The Mailbox module makes available a set of functions that manipulate
47 * mailbox objects accessed through handles of type Mailbox_Handle.
48 *
49 * {@link #pend()} is used to wait for a message from a mailbox.
50 * The timeout parameter to Mailbox_pend allows the task to wait until a
51 * timeout specified in terms of system clock ticks.
52 * A timeout value of {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}
53 * causes the task to wait indefinitely for a message.
54 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT BIOS_NO_WAIT}
55 * causes Mailbox_pend to return immediately.
56 * Mailbox_pend's return value indicates whether the mailbox was signaled
57 * successfully.
58 *
59 * When a Mailbox has been configured with a {@link #readerEvent} Event
60 * object and a task has returned from {@link Event#pend()} with the
61 * corresponding {@link #readerEventId}, then BIOS_NO_WAIT
62 * should be passed to Mailbox_pend() to retrieve the message.
63 *
64 * NOTE: Since only a single reader can pend on a {@link #readerEvent}
65 * Event object,
66 * a Mailbox configured with a {@link #readerEvent} Event object does not
67 * support multiple readers.
68 *
69 * {@link #post()} is used to send a message to a mailbox.
70 * The timeout parameter to Mailbox_post specifies the amount of time the
71 * calling task waits if the mailbox is full.
72 *
73 * When a Mailbox has been configured with a {@link #writerEvent} Event
74 * object and a task has returned from {@link Event#pend()} with the
75 * corresponding {@link #writerEventId}, then BIOS_NO_WAIT
76 * should be passed to Mailbox_post() knowing that the message
77 * will be successfully posted.
78 *
79 * NOTE: Since only a single writer can pend on a {@link #writerEvent}
80 * Event object,
81 * a Mailbox configured with a {@link #writerEvent} Event object does not
82 * support multiple writers.
83 *
84 * @p(html)
85 * <h3> Calling Context </h3>
86 * <table border="1" cellpadding="3">
87 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
88 * </colgroup>
89 *
90 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
91 * <th> Task </th><th> Main </th><th> Startup </th></tr>
92 * <!-- -->
93 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
94 * <td> Y </td><td> Y </td><td> Y </td></tr>
95 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
96 * <td> Y </td><td> Y </td><td> N </td></tr>
97 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
98 * <td> Y </td><td> Y </td><td> N </td></tr>
99 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
100 * <td> Y </td><td> Y </td><td> N </td></tr>
101 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
102 * <td> Y </td><td> Y </td><td> N </td></tr>
103 * <tr><td> {@link #getNumFreeMsgs} </td><td> Y </td><td> Y </td>
104 * <td> Y </td><td> N </td><td> N </td></tr>
105 * <tr><td> {@link #getNumPendingMsgs} </td><td> Y </td><td> Y </td>
106 * <td> Y </td><td> N </td><td> N </td></tr>
107 * <tr><td> {@link #pend} </td><td> N* </td><td> N* </td>
108 * <td> Y </td><td> N* </td><td> N </td></tr>
109 * <tr><td> {@link #post} </td><td> N* </td><td> N* </td>
110 * <td> Y </td><td> N* </td><td> N </td></tr>
111 * <tr><td colspan="6"> Definitions: (N* means OK to call iff the timeout
112 * parameter is set to '0'.)<br />
113 * <ul>
114 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
115 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
116 * <li> <b>Task</b>: API is callable from a Task thread. </li>
117 * <li> <b>Main</b>: API is callable during any of these phases: </li>
118 * <ul>
119 * <li> In your module startup after this module is started
120 * (e.g. Mailbox_Module_startupDone() returns TRUE). </li>
121 * <li> During xdc.runtime.Startup.lastFxns. </li>
122 * <li> During main().</li>
123 * <li> During BIOS.startupFxns.</li>
124 * </ul>
125 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
126 * <ul>
127 * <li> During xdc.runtime.Startup.firstFxns.</li>
128 * <li> In your module startup before this module is started
129 * (e.g. Mailbox_Module_startupDone() returns FALSE).</li>
130 * </ul>
131 * </ul>
132 * </td></tr>
133 *
134 * </table>
135 * @p
136 */
137
138 @ModuleStartup
139 @InstanceFinalize
140 @InstanceInitError
141
142 module Mailbox
143 {
144 /*!
145 * ======== BasicView ========
146 * @_nodoc
147 */
148 metaonly struct BasicView {
149 String label;
150 SizeT msgSize;
151 UInt numMsgs;
152 }
153
154 /*!
155 * ======== DetailedView ========
156 * @_nodoc
157 */
158 metaonly struct DetailedView {
159 String label;
160 SizeT msgSize;
161 UInt numMsgs;
162 UInt curNumMsgs;
163 UInt freeSlots;
164 String pendQueue[];
165 String postQueue[];
166 }
167
168 /*!
169 * ======== rovViewInfo ========
170 * @_nodoc
171 */
172 @Facet
173 metaonly config ViewInfo.Instance rovViewInfo =
174 ViewInfo.create({
175 viewMap: [
176 [
177 'Basic',
178 {
179 type: ViewInfo.INSTANCE,
180 viewInitFxn: 'viewInitBasic',
181 structName: 'BasicView'
182 }
183 ],
184 [
185 'Detailed',
186 {
187 type: ViewInfo.INSTANCE,
188 viewInitFxn: 'viewInitDetailed',
189 structName: 'DetailedView'
190 }
191 ]
192 ]
193 });
194
195 /*!
196 * ======== MbxElem ========
197 * The header used to save each Mailbox message
198 *
199 * Mailbox messages are stored in a queue that requires a header in
200 * front of each message. This structure defines that header and its
201 * size must be factored into the total data size requirements for a
202 * mailbox instance.
203 */
204 struct MbxElem {
205 Queue.Elem elem;
206 };
207
208 /*!
209 * ======== A_invalidBufSize ========
210 * Assert raised when the bufSize parameter is too small
211 *
212 * This assert is raised when bufSize is too small to handle
213 * (size of messages + sizeof(MbxElem)) * number of messages.
214 * See {@link ti.sysbios.knl.MailBox#buf} for more information on the buf
215 * parameter.
216 */
217 config xdc.runtime.Assert.Id A_invalidBufSize =
218 {msg: "Mailbox_create's bufSize parameter is invalid (too small)"};
219
220 instance:
221
222 /*!
223 * ======== create ========
224 * Create a mailbox
225 *
226 * Mailbox_create creates a mailbox object which is initialized to contain
227 * numMsgs messages of size msgSize.
228 *
229 * @param(msgSize) size of message
230 * @param(numMsgs) length of mailbox
231 */
232 @DirectCall
233 create(SizeT msgSize, UInt numMsgs);
234
235 /*!
236 * ======== heap ========
237 * The IHeap instance used for dynamic creates
238 *
239 * This heap is used only for dynamic instances is ignored for static
240 * instances.
241 */
242 config xdc.runtime.IHeap.Handle heap = null;
243
244 /*!
245 * ======== sectionName ========
246 * Section name for the buffer managed by the instance
247 *
248 * The default section is the 'dataSection' in the platform.
249 */
250 metaonly config String sectionName = null;
251
252 /*!
253 * ======== readerEvent ========
254 * Mailbox not empty event if using Events. Default is null
255 *
256 * Posted whenever a mailbox is written to.
257 * Reader task pends on this event.
258 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
259 * Semaphore.supportsEvents} has to be
260 * set to true for Mailbox to support Events.
261 */
262 config Event.Handle readerEvent = null;
263
264 /*!
265 * ======== readerEventId ========
266 * Mailbox not empty event Id if using Events. Default is 1
267 *
268 * Posted whenever a mailbox is written to.
269 * Reader task pends on this eventId.
270 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
271 * Semaphore.supportsEvents} has to be
272 * set to true for Mailbox to support Events.
273 */
274 config UInt readerEventId = 1;
275
276 /*!
277 * ======== writerEvent ========
278 * Mailbox not full event if using Events. Default is null
279 *
280 * Posted whenever a mailbox is read from.
281 * Writer task pends on this event.
282 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
283 * Semaphore.supportsEvents} has to be
284 * set to true for Mailbox to support Events.
285 */
286 config Event.Handle writerEvent = null;
287
288 /*!
289 * ======== writerEventId ========
290 * Mailbox not full event Id if using Events
291 *
292 * Posted whenever a mailbox is read from.
293 * Writer task pends on this eventId.
294 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
295 * Semaphore.supportsEvents} has to be
296 * set to true for Mailbox to support Events.
297 */
298 config UInt writerEventId = 1;
299
300 /*!
301 * ======== buf ========
302 * The address of the buffer used for creating messages
303 *
304 * This property is only used for dynamically created Mailboxes.
305 * If set to 'null', the messages will be allocated from the heap
306 * during runtime, otherwise the user may set this to a buffer of their
307 * creation to be used for allocating the messages.
308 *
309 * The module will split the buf into
310 * {@link ti.sysbios.knl.Mailbox#numMsgs} number of blocks (one block per
311 * Mailbox message).
312 *
313 * Please note that if the buffer is user supplied, then it is the user's
314 * responsibility to ensure that it is aligned properly and is also large
315 * enough to contain {@link ti.sysbios.knl.Mailbox#numMsgs} number of
316 * blocks. The size of each block is defined as follows:
317 * @p(code)
318 * sizeof(Mailbox_MbxElem) + msgSize
319 * @p
320 *
321 * Since the buffer must be a aligned properly, it may be necessary to
322 * 'round up' the total size of the buffer to the next multiple of the
323 * alignment for odd sized messages.
324 *
325 * @see #MbxElem
326 */
327 config Ptr buf = null;
328
329 /*!
330 * ======== bufSize ========
331 * The size of the buffer that 'buf' references
332 *
333 * This property is only used for dynamically created Mailboxes.
334 */
335 config UInt bufSize = 0;
336
337 /*!
338 * ======== getMsgSize ========
339 * Get the message size
340 */
341 @DirectCall
342 SizeT getMsgSize();
343
344 /*!
345 * ======== getNumFreeMsgs ========
346 * Get the number messages available for use
347 */
348 @DirectCall
349 Int getNumFreeMsgs();
350
351 /*!
352 * ======== getNumPendingMsgs ========
353 * Get the number of messages that are ready to be read
354 */
355 @DirectCall
356 Int getNumPendingMsgs();
357
358 /*!
359 * ======== pend ========
360 * Wait for a message from mailbox
361 *
362 * If the mailbox is not empty, Mailbox_pend copies the first message into
363 * msg and returns TRUE. Otherwise, Mailbox_pend suspends the execution of
364 * the current task until Mailbox_post is called or the timeout expires.
365 *
366 * A timeout value of
367 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
368 * the task to wait indefinitely for a message.
369 *
370 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
371 * causes Mailbox_pend to return immediately.
372 *
373 * The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
374 * should be passed to Mailbox_pend() to retrieve a message after
375 * Event_pend() is called outside of Mailbox_pend to wait on an incoming
376 * message.
377 *
378 * Mailbox_pend's return value indicates whether the mailbox was signaled
379 * successfully.
380 *
381 * @param(msg) message pointer
382 * @param(timeout) maximum duration in system clock ticks
383 * @b(returns) TRUE if successful, FALSE if timeout
384 */
385 @DirectCall
386 Bool pend(Ptr msg, UInt timeout);
387
388 /*!
389 * ======== post ========
390 * Post a message to mailbox
391 *
392 * Mailbox_post checks to see if there are any free message slots before
393 * copying msg into the mailbox. Mailbox_post readies the first task
394 * (if any) waiting on the mailbox. If the mailbox is full and a timeout
395 * is specified the task remains suspended until Mailbox_pend is called
396 * or the timeout expires.
397 *
398 * A timeout value of
399 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
400 * the task to wait indefinitely for a free slot.
401 *
402 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
403 * causes Mailbox_post to return immediately.
404 *
405 * The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
406 * should be passed to Mailbox_post() to post a message after
407 * Event_pend() is called outside of Mailbox_post to wait on an
408 * available message buffer.
409 *
410 * Mailbox_post's return value indicates whether the msg was
411 * copied or not.
412 *
413 * @param(msg) message pointer
414 * @param(timeout) maximum duration in system clock ticks
415 * @b(returns) TRUE if successful, FALSE if timeout
416 */
417 @DirectCall
418 Bool post(Ptr msg, UInt timeout);
419
420 internal:
421
422 Void cleanQue(Queue.Handle obj);
423
424 425 426 427
428 Int postInit(Object *obj, SizeT blockSize);
429
430
431 struct Instance_State {
432 xdc.runtime.IHeap.Handle heap;
433 SizeT msgSize;
434 UInt numMsgs;
435 Ptr buf;
436 Queue.Object dataQue;
437 Queue.Object freeQue;
438 Semaphore.Object dataSem;
439 Semaphore.Object freeSem;
440 UInt numFreeMsgs;
441 Char allocBuf[];
442 };
443 }
444 445 446 447
448