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.Assert;
41 import xdc.runtime.Diags;
42 import xdc.runtime.Log;
43
44 import ti.sysbios.knl.Queue;
45 import ti.sysbios.knl.Clock;
46 import ti.sysbios.knl.Task;
47
48 /*!
49 * ======== Event ========
50 * Event Manager.
51 *
52 * SYS/BIOS events are a means of communication between Tasks and other
53 * threads such as Hwis, Swis, and other Tasks, or between Tasks and
54 * other SYS/BIOS objects. Other SYS/BIOS objects include semaphores,
55 * mailboxes,
56 * message queues, etc. Only tasks can wait for events; whereas tasks,
57 * Hwis, Swis, or SYS/BIOS objects can post them.
58 *
59 * In order for a task to be notified of an event from a SYS/BIOS object an
60 * event object must first be registered with that object. Separate APIs
61 * are provided (in their respective modules) for each of the SYS/BIOS object
62 * types that support this feature.
63 *
64 * Events are synchronous in nature, meaning that a receiving task will
65 * block or pend while waiting for the events to occur. When the desired
66 * events are received, the pending task continues its execution, as it
67 * would after a call to Semaphore_pend(), for example.
68 *
69 * Tasks can also wait on events that are not linked to other SYS/BIOS objects.
70 * These events are explicitly posted from other threads such as tasks,
71 * Swis, or Hwis. A task does not register to receive these events; the
72 * sending thread simply posts its event(s) to the event object the task
73 * is pending on. This scenario is similar to having an ISR post a
74 * semaphore.
75 *
76 * A task can wait on events from multiple resources and/or threads; thus,
77 * it can be waiting for a semaphore to be posted and for a message to
78 * arrive in a message queue or an ISR thread to signal that an event has
79 * occurred.
80 *
81 * Unlike Semaphores, only a single task can pend on an Event object.
82 *
83 * {@link #pend} is used to wait for events. The andMask & orMask
84 * determine which
85 * event(s) must occur before returning from {@link #pend}. The timeout
86 * parameter
87 * allows the task to wait until a timeout, wait indefinitely, or not wait
88 * at all. A return value of zero indicates that a timeout has occurred. A
89 * non-zero return value is the set of events that were active at the time
90 * the task was unblocked.
91 *
92 * The andMask defines a set of events that must ALL occur to allow
93 * {@link #pend} to return.
94 *
95 * The orMask defines a set of events that will cause {@link #pend} to
96 * return if ANY of them occur.
97 *
98 * Events are binary. Events become available (posted) on each Event_post()
99 * of the eventId and become non-available (consumed) on each qualifying
100 * Event_pend() mask.
101 *
102 * All active events present in the orMask are consumed (ie removed from
103 * the event object) upon return from {@link #pend}. Only when all events
104 * present in the andMask are active are they consumed on return from
105 * {@link #pend}.
106 *
107 * @a(Caveat)
108 * @p(html)
109 * <BLOCKQUOTE>
110 * When Events are implicitly posted while used in conjunction with
111 * Semaphore or Mailbox objects, then following the call to Event_pend()
112 * which consumes the matching Event_IDs pended on, the Event object will be
113 * updated by the intervening Semaphore_pend() or Mailbox_pend/post()
114 * call so that it reflects the current state of availability of the
115 * corresponding Semaphore or Mailbox object.
116 * </BLOCKQUOTE>
117 * @p
118 *
119 * {@link #pend} returns immediately if the andMask OR orMask conditions
120 * are true upon entry.
121 *
122 * {@link #post} is used to signal events. If a task is waiting for the event
123 * and all of the event conditions are met, {@link #post} unblocks the task.
124 * If no task is waiting, {@link #post} simply registers the event with the
125 * event object and returns.
126 *
127 * The maximum number of eventIds supported is target specific and depends
128 * on the number of bits in a UInt data type.
129 * For 6x and ARM devices the maximum number of eventIds is therefore 32.
130 * For 28x the maximum number of eventIds is 16.
131 *
132 * @p(html)
133 * <h3> Calling Context </h3>
134 * <table border="1" cellpadding="3">
135 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
136 * </colgroup>
137 *
138 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
139 * <th> Task </th><th> Main </th><th> Startup </th></tr>
140 * <!-- -->
141 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
142 * <td> Y </td><td> Y </td><td> N </td></tr>
143 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
144 * <td> Y </td><td> Y </td><td> Y </td></tr>
145 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
146 * <td> Y </td><td> Y </td><td> N </td></tr>
147 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
148 * <td> Y </td><td> Y </td><td> N </td></tr>
149 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
150 * <td> Y </td><td> Y </td><td> N </td></tr>
151 * <tr><td> {@link #getPostedEvents} </td><td> Y </td><td> Y </td>
152 * <td> Y </td><td> Y </td><td> Y </td></tr>
153 * <tr><td> {@link #pend} </td><td> N* </td><td> N* </td>
154 * <td> Y </td><td> N* </td><td> N </td></tr>
155 * <tr><td> {@link #post} </td><td> Y </td><td> Y </td>
156 * <td> Y </td><td> Y </td><td> N </td></tr>
157 * <tr><td colspan="6"> Definitions: (N* means OK to call iff the timeout
158 * parameter is set to '0'.)<br />
159 * <ul>
160 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
161 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
162 * <li> <b>Task</b>: API is callable from a Task thread. </li>
163 * <li> <b>Main</b>: API is callable during any of these phases: </li>
164 * <ul>
165 * <li> In your module startup after this module is started
166 * (e.g. Event_Module_startupDone() returns TRUE). </li>
167 * <li> During xdc.runtime.Startup.lastFxns. </li>
168 * <li> During main().</li>
169 * <li> During BIOS.startupFxns.</li>
170 * </ul>
171 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
172 * <ul>
173 * <li> During xdc.runtime.Startup.firstFxns.</li>
174 * <li> In your module startup before this module is started
175 * (e.g. Event_Module_startupDone() returns FALSE).</li>
176 * </ul>
177 * </ul>
178 * </td></tr>
179 *
180 * </table>
181 * @p
182 */
183
184 @DirectCall
185 186 187
188 @CustomHeader
189 @InstanceInitStatic
190
191 module Event
192 {
193 /*!
194 * Pre-defined Event Ids
195 *
196 * Event_Ids are provided to simplify the specification of
197 * andMasks and orMasks arguments to {@link #pend Event_pend()}.
198 *
199 * Since each Event_Id is a bitmask composed of only a single bit,
200 * a group of Event_Ids within an andMask or orMask can be indicated
201 * by simply adding them together. For instance, to indicate that a task
202 * is to be awakened only when both Event_Id_00 and Event_Id_01 have
203 * been posted, the andMask for Event_pend() would be constructed
204 * as below:
205 *
206 * @p(code)
207 * Event_pend(event, Event_Id_00+EventId_01, Event_Id_NONE,
208 * BIOS_WAIT_FOREVER);
209 * @p
210 *
211 * As shown above, Event_Id_NONE is to be used as an empty (NULL)
212 * andMask or orMask.
213 *
214 * @a(Note)
215 * For targets where a UInt is 32 bits in length,
216 * Event_Id_00 thru Event_Id_31 can be used.
217 *
218 * For targets where a UInt is 16 bits in length,
219 * Event_Id_00 thru Event_Id_15 can be used.
220 */
221
222 const UInt Id_00 = 0x1;
223 const UInt Id_01 = 0x2; /*! @see #Id_00 Pre-defined Event IDs. */
224 const UInt Id_02 = 0x4; /*! @see #Id_00 Pre-defined Event IDs. */
225 const UInt Id_03 = 0x8; /*! @see #Id_00 Pre-defined Event IDs. */
226 const UInt Id_04 = 0x10; /*! @see #Id_00 Pre-defined Event IDs. */
227 const UInt Id_05 = 0x20; /*! @see #Id_00 Pre-defined Event IDs. */
228 const UInt Id_06 = 0x40; /*! @see #Id_00 Pre-defined Event IDs. */
229 const UInt Id_07 = 0x80; /*! @see #Id_00 Pre-defined Event IDs. */
230 const UInt Id_08 = 0x100; /*! @see #Id_00 Pre-defined Event IDs. */
231 const UInt Id_09 = 0x200; /*! @see #Id_00 Pre-defined Event IDs. */
232 const UInt Id_10 = 0x400; /*! @see #Id_00 Pre-defined Event IDs. */
233 const UInt Id_11 = 0x800; /*! @see #Id_00 Pre-defined Event IDs. */
234 const UInt Id_12 = 0x1000; /*! @see #Id_00 Pre-defined Event IDs. */
235 const UInt Id_13 = 0x2000; /*! @see #Id_00 Pre-defined Event IDs. */
236 const UInt Id_14 = 0x4000; /*! @see #Id_00 Pre-defined Event IDs. */
237 const UInt Id_15 = 0x8000; /*! @see #Id_00 Pre-defined Event IDs. */
238 const UInt Id_16 = 0x10000; /*! @see #Id_00 Pre-defined Event IDs. */
239 const UInt Id_17 = 0x20000; /*! @see #Id_00 Pre-defined Event IDs. */
240 const UInt Id_18 = 0x40000; /*! @see #Id_00 Pre-defined Event IDs. */
241 const UInt Id_19 = 0x80000; /*! @see #Id_00 Pre-defined Event IDs. */
242 const UInt Id_20 = 0x100000; /*! @see #Id_00 Pre-defined Event IDs. */
243 const UInt Id_21 = 0x200000; /*! @see #Id_00 Pre-defined Event IDs. */
244 const UInt Id_22 = 0x400000; /*! @see #Id_00 Pre-defined Event IDs. */
245 const UInt Id_23 = 0x800000; /*! @see #Id_00 Pre-defined Event IDs. */
246 const UInt Id_24 = 0x1000000; /*! @see #Id_00 Pre-defined Event IDs. */
247 const UInt Id_25 = 0x2000000; /*! @see #Id_00 Pre-defined Event IDs. */
248 const UInt Id_26 = 0x4000000; /*! @see #Id_00 Pre-defined Event IDs. */
249 const UInt Id_27 = 0x8000000; /*! @see #Id_00 Pre-defined Event IDs. */
250 const UInt Id_28 = 0x10000000; /*! @see #Id_00 Pre-defined Event IDs. */
251 const UInt Id_29 = 0x20000000; /*! @see #Id_00 Pre-defined Event IDs. */
252 const UInt Id_30 = 0x40000000; /*! @see #Id_00 Pre-defined Event IDs. */
253 const UInt Id_31 = 0x80000000; /*! @see #Id_00 Pre-defined Event IDs. */
254
255 const UInt Id_NONE = 0; /*! @see #Id_00 Pre-defined Event IDs. */
256 /*!
257 * ======== BasicView ========
258 * @_nodoc
259 */
260 metaonly struct BasicView {
261 String label;
262 String postedEvents;
263 String pendedTask;
264 String andMask;
265 String orMask;
266 String timeout;
267 };
268
269 /*!
270 * ======== rovViewInfo ========
271 * @_nodoc
272 */
273 @Facet
274 metaonly config ViewInfo.Instance rovViewInfo =
275 ViewInfo.create({
276 viewMap: [
277 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',
278 structName: 'BasicView'}]
279 ]
280 });
281
282
283
284
285
286 /*! Logged on calls to Event_post() */
287 config Log.Event LM_post = {
288 mask: Diags.USER1 | Diags.USER2,
289 msg: "LM_post: event: 0x%x, currEvents: 0x%x, eventId: 0x%x"
290 };
291
292 /*! Logged on calls to Event_pend() */
293 config Log.Event LM_pend = {
294 mask: Diags.USER1 | Diags.USER2,
295 msg: "LM_pend: event: 0x%x, currEvents: 0x%x, andMask: 0x%x, orMask: 0x%x, timeout: %d"
296 };
297
298
299
300 /*!
301 * Asserted when {@link #pend} is called with andMask and orMask == 0
302 */
303 config Assert.Id A_nullEventMasks = {
304 msg: "A_nullEventMasks: orMask and andMask are null."
305 };
306
307 /*!
308 * Asserted when {@link #post} is called with eventId == 0
309 */
310 config Assert.Id A_nullEventId = {
311 msg: "A_nullEventId: posted eventId is null."
312 };
313
314 /*!
315 * Asserted when {@link #pend} is called by multiple tasks on the same
316 * Event object.
317 */
318 config Assert.Id A_eventInUse = {
319 msg: "A_eventInUse: Event object already in use."
320 };
321
322 /*!
323 * Asserted when {@link #pend} is called with non-zero timeout from other
324 * than a Task context.
325 */
326 config Assert.Id A_badContext = {
327 msg: "A_badContext: bad calling context. Must be called from a Task."
328 };
329
330 /*!
331 * ======== A_pendTaskDisabled ========
332 * Asserted in Event_pend()
333 *
334 * Assert raised if Event_pend() is called with the Task or
335 * Swi scheduler disabled.
336 */
337 config Assert.Id A_pendTaskDisabled = {
338 msg: "A_pendTaskDisabled: Cannot call Event_pend() while the Task or Swi scheduler is disabled."
339 };
340
341 instance:
342
343 /*!
344 * ======== create ========
345 * Create an Event object.
346 *
347 * This function creates a new Event object.
348 */
349 create();
350
351 /*!
352 * ======== pend ========
353 * Wait for events defined in 'and' OR 'or' masks.
354 *
355 * pend() is used to wait for events. The andMask and orMask determine
356 * which
357 * event(s) must occur before returning from pend(). The timeout parameter
358 * allows the task to wait until a timeout, wait indefinitely, or not wait
359 * at all. A return value of zero indicates that a timeout has occurred. A
360 * non-zero return value is the set of events that were active at the time
361 * the task was unblocked.
362 *
363 * The andMask defines a set of events that must
364 * ALL occur to allow pend() to return.
365 *
366 * The orMask defines a set of events
367 * that will cause pend() to return if ANY of them occur.
368 *
369 * All active events
370 * present in the orMask are consumed (i.e. removed from the event object)
371 * upon return from pend(). Only when all events present in the andMask
372 * are active are they consumed on return from pend().
373 *
374 * The pend conditions are satisfied when either ALL of the events
375 * in the andMask occur or ANY of the events in the orMask occur.
376 *
377 * A timeout value of
378 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
379 * the task to wait indefinitely for matching events to be posted.
380 *
381 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
382 * causes Event_pend to return immediately.
383 *
384 * @param(andMask) return from pend() when ALL of these
385 * events have occurred
386 * @param(orMask) return from pend() when ANY of these
387 * events have occurred
388 * @param(timeout) return from pend() after this many system
389 * time units
390 *
391 * @b(returns) All consumed events or zero if timeout.
392 */
393 UInt pend(UInt andMask, UInt orMask, UInt32 timeout);
394
395 /*!
396 * ======== post ========
397 * Post event(s) to an event object.
398 *
399 * Event_post() is used to signal events. If a task is waiting for the
400 * event and the event conditions are met, post() unblocks the
401 * task. If no tasks are waiting, post() simply registers the event with
402 * the event object and returns.
403 *
404 * @param(eventMask) mask of eventIds to post (must be non-zero)
405 */
406 Void post(UInt eventMask);
407
408 /*!
409 * ======== getPostedEvents ========
410 * Returns the set of events that have not been consumed by a task
411 * (ie those events that have not fully satisfied any pend() conditions).
412 * No events are consumed!
413 *
414 * @b(returns) All un-consumed events posted to the event.
415 */
416 UInt getPostedEvents();
417
418 /*!
419 * @_nodoc
420 * ======== sync ========
421 * synchronize an eventId to the value given
422 * must call with interrupts disabled
423 *
424 * @param(eventId) eventId to sync
425 * @param(count) count
426 */
427 Void sync(UInt eventId, UInt count);
428
429 /*!
430 * @_nodoc
431 * ======== syncMeta ========
432 * synchronize an eventId to the value given (static version)
433 *
434 * @param(eventId) eventId to sync
435 * @param(count) count
436 */
437 metaonly Void syncMeta(UInt eventId, UInt count);
438
439 internal:
440
441 /*!
442 * ======== pendTimeout ========
443 * This function is the clock event handler for pend
444 */
445 Void pendTimeout(UArg arg);
446
447 448 449 450 451 452 453
454 UInt checkEvents (Object *event, UInt andMask, UInt orMask);
455
456 457 458 459 460 461
462 metaonly config Any eventInstances[];
463
464
465 enum PendState {
466 PendState_TIMEOUT = 0,
467 PendState_POSTED = 1,
468 PendState_CLOCK_WAIT = 2,
469 PendState_WAIT_FOREVER = 3
470 };
471
472
473 struct PendElem {
474 Task.PendElem tpElem;
475 volatile PendState pendState;
476 UInt matchingEvents;
477 UInt andMask;
478 UInt orMask;
479 };
480
481 struct Instance_State {
482 volatile UInt postedEvents;
483 Queue.Object pendQ;
484
485
486 };
487 }