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> Y* </td><td> Y* </td>
108 * <td> Y </td><td> N </td><td> N </td></tr>
109 * <tr><td> {@link #post} </td><td> Y </td><td> Y </td>
110 * <td> Y </td><td> N </td><td> N </td></tr>
111 * <tr><td colspan="6"> Definitions: <br />
112 * <ul>
113 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
114 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
115 * <li> <b>Task</b>: API is callable from a Task thread. </li>
116 * <li> <b>Main</b>: API is callable during any of these phases: </li>
117 * <ul>
118 * <li> In your module startup after this module is started
119 * (e.g. Mailbox_Module_startupDone() returns TRUE). </li>
120 * <li> During xdc.runtime.Startup.lastFxns. </li>
121 * <li> During main().</li>
122 * <li> During BIOS.startupFxns.</li>
123 * </ul>
124 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
125 * <ul>
126 * <li> During xdc.runtime.Startup.firstFxns.</li>
127 * <li> In your module startup before this module is started
128 * (e.g. Mailbox_Module_startupDone() returns FALSE).</li>
129 * </ul>
130 * <li> <b>*</b>: Yes but only for a timeout value of zero. </li>
131 * </ul>
132 * </td></tr>
133 *
134 * </table>
135 * @p
136 */
137
138 @ModuleStartup
139 @InstanceFinalize
140 @InstanceInitError
141
142 module Mailbox
143 {
144 metaonly struct BasicView {
145 String label;
146 SizeT msgSize;
147 UInt numMsgs;
148 }
149
150 metaonly struct DetailedView {
151 String label;
152 SizeT msgSize;
153 UInt numMsgs;
154 UInt curNumMsgs;
155 UInt freeSlots;
156 String pendQueue[];
157 String postQueue[];
158 }
159
160 @Facet
161 metaonly config ViewInfo.Instance rovViewInfo =
162 ViewInfo.create({
163 viewMap: [
164 [
165 'Basic',
166 {
167 type: ViewInfo.INSTANCE,
168 viewInitFxn: 'viewInitBasic',
169 structName: 'BasicView'
170 }
171 ],
172 [
173 'Detailed',
174 {
175 type: ViewInfo.INSTANCE,
176 viewInitFxn: 'viewInitDetailed',
177 structName: 'DetailedView'
178 }
179 ]
180 ]
181 });
182
183 struct MbxElem {
184 Queue.Elem elem;
185 };
186
187 /*!
188 * Assert raised when the bufSize parameter is too small
189 * to handle (size of messages + sizeof(MbxElem)) * number of messages. See
190 * {@link ti.sysbios.knl.MailBox#buf} for more information on the buf
191 * parameter.
192 */
193 config xdc.runtime.Assert.Id A_invalidBufSize =
194 {msg: "Mailbox_create's bufSize parameter is invalid (too small)"};
195
196 instance:
197
198 /*!
199 * ======== create ========
200 * Create a mailbox
201 *
202 * Mailbox_create creates a mailbox object which is initialized to contain
203 * numMsgs messages of size msgSize.
204 *
205 * @param(msgSize) size of message
206 * @param(numMsgs) length of mailbox
207 */
208 @DirectCall
209 create(SizeT msgSize, UInt numMsgs);
210
211 /*!
212 * ======== heap ========
213 * The IHeap instance used for dynamic creates.
214 *
215 * This heap is used only for dynamic instances is ignored for static
216 * instances.
217 */
218 config xdc.runtime.IHeap.Handle heap = null;
219
220 /*!
221 * ======== sectionName ========
222 * Section name for the buffer managed by the instance.
223 *
224 * The default section is the 'dataSection' in the platform.
225 */
226 metaonly config String sectionName = null;
227
228 /*!
229 * ======== readerEvent ========
230 * Mailbox not empty event if using Events. Default is null.
231 *
232 * Posted whenever a mailbox is written to.
233 * Reader task pends on this event.
234 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
235 * Semaphore.supportsEvents} has to be
236 * set to true for Mailbox to support Events.
237 */
238 config Event.Handle readerEvent = null;
239
240 /*!
241 * ======== readerEventId ========
242 * Mailbox not empty event Id if using Events. Default is 1.
243 *
244 * Posted whenever a mailbox is written to.
245 * Reader task pends on this eventId.
246 * Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
247 * Semaphore.supportsEvents} has to be
248 * set to true for Mailbox to support Events.
249 */
250 config UInt readerEventId = 1;
251
252 /*!
253 * ======== writerEvent ========
254 * Mailbox not full event if using Events. Default is null.
255 *
256 * Posted whenever a mailbox is read from.
257 * Writer 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 writerEvent = null;
263
264 /*!
265 * ======== writerEventId ========
266 * Mailbox not full event Id if using Events. Default is 1.
267 *
268 * Posted whenever a mailbox is read from.
269 * Writer 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 writerEventId = 1;
275
276 /*!
277 * ======== buf ========
278 * The address of the buffer used for creating messages.
279 *
280 * This property is only used for dynamically created Mailboxes.
281 * If set to 'null', the messages will be allocated from the heap
282 * during runtime, otherwise the user may set this to a buffer of their
283 * creation to be used for allocating the messages.
284 *
285 * The module will split the buf into
286 * {@link ti.sysbios.knl.Mailbox#numMsgs} number of blocks (one block per
287 * Mailbox message).
288 *
289 * Please note that if the buffer is user supplied, then it is the user's
290 * responsibility to ensure that it is aligned properly and is also large
291 * enough to contain {@link ti.sysbios.knl.Mailbox#numMsgs} number of
292 * blocks. The size of each block is defined as follows:
293 * @p(code)
294 * sizeof(Mailbox_MbxElem) + msgSize
295 * @p
296 *
297 * Since the buffer must be a aligned properly, it may be necessary to
298 * 'round up' the total size of the buffer to the next multiple of the
299 * alignment for odd sized messages.
300 *
301 */
302 config Ptr buf = null;
303
304 /*!
305 * ======== bufSize ========
306 * The size of the buffer that 'buf' points to.
307 *
308 * This property is only used for dynamically created Mailboxes.
309 */
310 config UInt bufSize = 0;
311
312 /*!
313 * ======== getNumFreeMsgs ========
314 * Returns the number messages available for use for a Mailbox instance.
315 */
316 @DirectCall
317 Int getNumFreeMsgs();
318
319 /*!
320 * ======== getNumPendingMsgs ========
321 * Returns the number of messages that are ready to be read for a Mailbox
322 * instance.
323 */
324 @DirectCall
325 Int getNumPendingMsgs();
326
327 /*!
328 * ======== pend ========
329 * Wait for a message from mailbox
330 *
331 * If the mailbox is not empty, Mailbox_pend copies the first message into
332 * msg and returns TRUE. Otherwise, Mailbox_pend suspends the execution of
333 * the current task until Mailbox_post is called or the timeout expires.
334 *
335 * A timeout value of
336 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
337 * the task to wait indefinitely for a message.
338 *
339 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
340 * causes Mailbox_pend to return immediately.
341 *
342 * The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
343 * should be passed to Mailbox_pend() to retrieve a message after
344 * Event_pend() is called outside of Mailbox_pend to wait on an incoming
345 * message.
346 *
347 * Mailbox_pend's return value indicates whether the mailbox was signaled
348 * successfully.
349 *
350 * @param(msg) message pointer
351 * @param(timeout) maximum duration in system clock ticks
352 * @b(returns) TRUE if successful, FALSE if timeout
353 */
354 @DirectCall
355 Bool pend(Ptr msg, UInt timeout);
356
357 /*!
358 * ======== post ========
359 * Post a message to mailbox
360 *
361 * Mailbox_post checks to see if there are any free message slots before
362 * copying msg into the mailbox. Mailbox_post readies the first task
363 * (if any) waiting on the mailbox. If the mailbox is full and a timeout
364 * is specified the task remains suspended until Mailbox_pend is called
365 * or the timeout expires.
366 *
367 * A timeout value of
368 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
369 * the task to wait indefinitely for a free slot.
370 *
371 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
372 * causes Mailbox_post to return immediately.
373 *
374 * The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
375 * should be passed to Mailbox_post() to post a message after
376 * Event_pend() is called outside of Mailbox_post to wait on an
377 * available message buffer.
378 *
379 * Mailbox_post's return value indicates whether the msg was
380 * copied or not.
381 *
382 * @param(msg) message pointer
383 * @param(timeout) maximum duration in system clock ticks
384 * @b(returns) TRUE if successful, FALSE if timeout
385 */
386 @DirectCall
387 Bool post(Ptr msg, UInt timeout);
388
389 internal:
390
391 Void cleanQue(Queue.Handle obj);
392
393 394 395 396
397 Int postInit(Object *obj, SizeT blockSize);
398
399
400 struct Instance_State {
401 xdc.runtime.IHeap.Handle heap;
402 SizeT msgSize;
403 UInt numMsgs;
404 Ptr buf;
405 Queue.Object dataQue;
406 Queue.Object freeQue;
407 Semaphore.Object dataSem;
408 Semaphore.Object freeSem;
409 UInt numFreeMsgs;
410 Char allocBuf[];
411 };
412 }
413 414 415 416
417