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