1 /*
2 * Copyright (c) 2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== Event.xdc ========
34 *
35 *1 aren't synced to Semaphore state
36 *! 04-Mar-2008 agd Stripped down to support binary only and
37 *! single task.
38 *! 23-Jan-2008 agd 01/22/08 review changes
39 *! 13-Dec-2007 agd Added Event_Id_NONE
40 *! 10-Dec-2007 connell updated call context table
41 *! 23-May-2007 agd Addressed SDSCM00017698
42 *! 11-May-2007 agd Addressed SDSCM00016595
43 *! 16-Apr-2007 cmcc Added calling context table
44 *! 01-Feb-2007 rt Added Log.Events
45 *! 16-Jan-2007 agd Moved to ipc package
46 *! 12-Dec-2006 agd integrate 12/5/06 code review comments
47 *! 27-Sep-2006 agd reworked pre-defined event masks
48 *! 21-Apr-2006 agd reworked to support counting Events
49 *! 02-Mar-2006 agd redefined default event mask constants
50 *! 14-Feb-2006 agd reworked to conform to
51 *! current design requirements
52 *! 31-Jan-2006 nitya/agd created
53 */
54
55 package ti.sysbios.knl;
56
57 import xdc.rov.ViewInfo;
58
59 import xdc.runtime.Assert;
60 import xdc.runtime.Diags;
61 import xdc.runtime.Log;
62
63 import ti.sysbios.knl.Queue;
64 import ti.sysbios.knl.Clock;
65 import ti.sysbios.knl.Task;
66
67 /*!
68 * ======== Event ========
69 * Event Manager.
70 *
71 * SYS/BIOS events are a means of communication between Tasks and other
72 * threads such as Hwis, Swis, and other Tasks, or between Tasks and
73 * other SYS/BIOS objects. Other SYS/BIOS objects include semaphores,
74 * mailboxes,
75 * message queues, etc. Only tasks can wait for events; whereas tasks,
76 * Hwis, Swis, or SYS/BIOS objects can post them.
77 *
78 * In order for a task to be notified of an event from a SYS/BIOS object an
79 * event object must first be registered with that object. Separate APIs
80 * are provided (in their respective modules) for each of the SYS/BIOS object
81 * types that support this feature.
82 *
83 * Events are synchronous in nature, meaning that a receiving task will
84 * block or pend while waiting for the events to occur. When the desired
85 * events are received, the pending task continues its execution, as it
86 * would after a call to Semaphore_pend(), for example.
87 *
88 * Tasks can also wait on events that are not linked to other SYS/BIOS objects.
89 * These events are explicitly posted from other threads such as tasks,
90 * Swis, or Hwis. A task does not register to receive these events; the
91 * sending thread simply posts its event(s) to the event object the task
92 * is pending on. This scenario is similar to having an ISR post a
93 * semaphore.
94 *
95 * A task can wait on events from multiple resources and/or threads; thus,
96 * it can be waiting for a semaphore to be posted and for a message to
97 * arrive in a message queue or an ISR thread to signal that an event has
98 * occurred.
99 *
100 * Events are binary. Events become available (posted) on each Event_post()
101 * of the eventId and become non-available (consumed) on each qualifying
102 * Event_pend() mask.
103 *
104 * Unlike Semaphores, only a single task can pend on an Event object.
105 *
106 * {@link #pend} is used to wait for events. The andMask & orMask
107 * determine which
108 * event(s) must occur before returning from {@link #pend}. The timeout
109 * parameter
110 * allows the task to wait until a timeout, wait indefinitely, or not wait
111 * at all. A return value of zero indicates that a timeout has occurred. A
112 * non-zero return value is the set of events that were active at the time
113 * the task was unblocked.
114 *
115 * The andMask defines a set of events that must ALL occur to allow
116 * {@link #pend} to return.
117 *
118 * The orMask defines a set of events that will cause {@link #pend} to
119 * return if ANY of them occur.
120 *
121 * All active events present in the orMask are consumed (ie removed from
122 * the event object) upon return from {@link #pend}. Only when all events
123 * present in the andMask are active are they consumed on return from
124 * {@link #pend}.
125 *
126 * {@link #pend} returns immediately if the andMask OR orMask conditions
127 * are true upon entry.
128 *
129 * {@link #post} is used to signal events. If a task is waiting for the event
130 * and all of the event conditions are met, {@link #post} unblocks the task.
131 * If no task is waiting, {@link #post} simply registers the event with the
132 * event object and returns.
133 *
134 * The maximum number of eventIds supported is target specific and depends
135 * on the number of bits in a UInt data type.
136 * For 6x and ARM devices the maximum number of eventIds is therefore 32.
137 * For 28x and MSP430 devices, the maximum number of eventIds is 16.
138 *
139 * @p(html) 140 * <h3> Calling Context </h3>
141 * <table border="1" cellpadding="3">
142 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
143 * </colgroup>
144 *
145 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
146 * <th> Task </th><th> Main </th><th> Startup </th></tr>
147 * <!-- -->
148 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
149 * <td> Y </td><td> Y </td><td> N </td></tr>
150 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
151 * <td> Y </td><td> Y </td><td> Y </td></tr>
152 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
153 * <td> Y </td><td> Y </td><td> N </td></tr>
154 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
155 * <td> Y </td><td> Y </td><td> N </td></tr>
156 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
157 * <td> Y </td><td> Y </td><td> N </td></tr>
158 * <tr><td> {@link #getPostedEvents} </td><td> Y </td><td> Y </td>
159 * <td> Y </td><td> Y </td><td> Y </td></tr>
160 * <tr><td> {@link #pend} </td><td> N* </td><td> N* </td>
161 * <td> Y </td><td> N* </td><td> N </td></tr>
162 * <tr><td> {@link #post} </td><td> Y </td><td> Y </td>
163 * <td> Y </td><td> Y </td><td> N </td></tr>
164 * <tr><td colspan="6"> Definitions: (N* means OK to call iff the timeout
165 * parameter is set to '0'.)<br />
166 * <ul>
167 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
168 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
169 * <li> <b>Task</b>: API is callable from a Task thread. </li>
170 * <li> <b>Main</b>: API is callable during any of these phases: </li>
171 * <ul>
172 * <li> In your module startup after this module is started
173 * (e.g. Event_Module_startupDone() returns TRUE). </li>
174 * <li> During xdc.runtime.Startup.lastFxns. </li>
175 * <li> During main().</li>
176 * <li> During BIOS.startupFxns.</li>
177 * </ul>
178 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
179 * <ul>
180 * <li> During xdc.runtime.Startup.firstFxns.</li>
181 * <li> In your module startup before this module is started
182 * (e.g. Event_Module_startupDone() returns FALSE).</li>
183 * </ul>
184 * </ul>
185 * </td></tr>
186 *
187 * </table>
188 * @p 189 */
190
191 /*
192 * To remove Event.Ids not defined for targets with 16 bit Ints
193 */
194 @CustomHeader
195
196 module Event
197 {
198 /*!
199 * Pre-defined Event Ids
200 *
201 * Event_Ids are provided to simplify the specification of
202 * andMasks and orMasks arguments to {@link #pend Event_pend()}.
203 *
204 * Since each Event_Id is a bitmask composed of only a single bit,
205 * a group of Event_Ids within an andMask or orMask can be indicated
206 * by simply adding them together. For instance, to indicate that a task
207 * is to be awakened only when both Event_Id_00 and Event_Id_01 have
208 * been posted, the andMask for Event_pend() would be constructed
209 * as below:
210 *
211 * @p(code) 212 * Event_pend(event, Event_Id_00+EventId_01, Event_Id_NONE,
213 * BIOS_WAIT_FOREVER);
214 * @p 215 *
216 * As shown above, Event_Id_NONE is to be used as an empty (NULL)
217 * andMask or orMask.
218 *
219 * @a(Note) 220 * For targets where a UInt is 32 bits in length,
221 * Event_Id_00 thru Event_Id_31 can be used.
222 *
223 * For targets where a UInt is 16 bits in length,
224 * Event_Id_00 thru Event_Id_15 can be used.
225 */
226
227 const UInt Id_00 = 0x1;
228 const UInt Id_01 = 0x2; /*! @see #Id_00 Pre-defined Event IDs. */
229 const UInt Id_02 = 0x4; /*! @see #Id_00 Pre-defined Event IDs. */
230 const UInt Id_03 = 0x8; /*! @see #Id_00 Pre-defined Event IDs. */
231 const UInt Id_04 = 0x10; /*! @see #Id_00 Pre-defined Event IDs. */
232 const UInt Id_05 = 0x20; /*! @see #Id_00 Pre-defined Event IDs. */
233 const UInt Id_06 = 0x40; /*! @see #Id_00 Pre-defined Event IDs. */
234 const UInt Id_07 = 0x80; /*! @see #Id_00 Pre-defined Event IDs. */
235 const UInt Id_08 = 0x100; /*! @see #Id_00 Pre-defined Event IDs. */
236 const UInt Id_09 = 0x200; /*! @see #Id_00 Pre-defined Event IDs. */
237 const UInt Id_10 = 0x400; /*! @see #Id_00 Pre-defined Event IDs. */
238 const UInt Id_11 = 0x800; /*! @see #Id_00 Pre-defined Event IDs. */
239 const UInt Id_12 = 0x1000; /*! @see #Id_00 Pre-defined Event IDs. */
240 const UInt Id_13 = 0x2000; /*! @see #Id_00 Pre-defined Event IDs. */
241 const UInt Id_14 = 0x4000; /*! @see #Id_00 Pre-defined Event IDs. */
242 const UInt Id_15 = 0x8000; /*! @see #Id_00 Pre-defined Event IDs. */
243 const UInt Id_16 = 0x10000; /*! @see #Id_00 Pre-defined Event IDs. */
244 const UInt Id_17 = 0x20000; /*! @see #Id_00 Pre-defined Event IDs. */
245 const UInt Id_18 = 0x40000; /*! @see #Id_00 Pre-defined Event IDs. */
246 const UInt Id_19 = 0x80000; /*! @see #Id_00 Pre-defined Event IDs. */
247 const UInt Id_20 = 0x100000; /*! @see #Id_00 Pre-defined Event IDs. */
248 const UInt Id_21 = 0x200000; /*! @see #Id_00 Pre-defined Event IDs. */
249 const UInt Id_22 = 0x400000; /*! @see #Id_00 Pre-defined Event IDs. */
250 const UInt Id_23 = 0x800000; /*! @see #Id_00 Pre-defined Event IDs. */
251 const UInt Id_24 = 0x1000000; /*! @see #Id_00 Pre-defined Event IDs. */
252 const UInt Id_25 = 0x2000000; /*! @see #Id_00 Pre-defined Event IDs. */
253 const UInt Id_26 = 0x4000000; /*! @see #Id_00 Pre-defined Event IDs. */
254 const UInt Id_27 = 0x8000000; /*! @see #Id_00 Pre-defined Event IDs. */
255 const UInt Id_28 = 0x10000000; /*! @see #Id_00 Pre-defined Event IDs. */
256 const UInt Id_29 = 0x20000000; /*! @see #Id_00 Pre-defined Event IDs. */
257 const UInt Id_30 = 0x40000000; /*! @see #Id_00 Pre-defined Event IDs. */
258 const UInt Id_31 = 0x80000000; /*! @see #Id_00 Pre-defined Event IDs. */
259
260 const UInt Id_NONE = 0; /*! @see #Id_00 Pre-defined Event IDs. */
261 /*!
262 * ======== BasicView ========
263 * @_nodoc 264 */
265 metaonlystruct BasicView {
266 String label;
267 String postedEvents;
268 String pendedTask;
269 String andMask;
270 String orMask;
271 String timeout;
272 };
273
274 /*!
275 * ======== rovViewInfo ========
276 * @_nodoc 277 */
278 @Facet
279 metaonlyconfig ViewInfo.Instance rovViewInfo =
280 ViewInfo.create({
281 viewMap: [
282 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',
283 structName: 'BasicView'}]
284 ]
285 });
286
287 // -------- Module Parameters --------
288
289 // Logs
290
291 /*! Logged on calls to Event_post() */
292 config Log.Event LM_post = {
293 mask: Diags.USER1 | Diags.USER2,
294 msg: "LM_post: event: 0x%x, currEvents: 0x%x, eventId: 0x%x"
295 };
296
297 /*! Logged on calls to Event_pend() */
298 config Log.Event LM_pend = {
299 mask: Diags.USER1 | Diags.USER2,
300 msg: "LM_pend: event: 0x%x, currEvents: 0x%x, andMask: 0x%x, orMask: 0x%x, timeout: %d"
301 };
302
303 // Asserts
304
305 /*!
306 * Asserted when {@link #pend} is called with andMask and orMask == 0
307 */
308 config Assert.Id A_nullEventMasks = {
309 msg: "A_nullEventMasks: orMask and andMask are null."
310 };
311
312 /*!
313 * Asserted when {@link #post} is called with eventId == 0
314 */
315 config Assert.Id A_nullEventId = {
316 msg: "A_nullEventId: posted eventId is null."
317 };
318
319 /*!
320 * Asserted when {@link #pend} is called by multiple tasks on the same
321 * Event object.
322 */
323 config Assert.Id A_eventInUse = {
324 msg: "A_eventInUse: Event object already in use."
325 };
326
327 /*!
328 * Asserted when {@link #pend} is called with non-zero timeout from other
329 * than a Task context.
330 */
331 config Assert.Id A_badContext = {
332 msg: "A_badContext: bad calling context. Must be called from a Task."
333 };
334
335 /*!
336 * ======== A_pendTaskDisabled ========
337 * Asserted in Event_pend()
338 *
339 * Assert raised if Event_pend() is called with the Task or
340 * Swi scheduler disabled.
341 */
342 config Assert.Id A_pendTaskDisabled = {
343 msg: "A_pendTaskDisabled: Cannot call Event_pend() while the Task or Swi scheduler is disabled."
344 };
345
346 instance:
347
348 /*!
349 * ======== create ========
350 * Create an Event object.
351 *
352 * This function creates a new Event object.
353 */
354 @DirectCall
355 create();
356
357 /*!
358 * ======== pend ========
359 * Wait for events defined in 'and' OR 'or' masks.
360 *
361 * pend() is used to wait for events. The andMask and orMask determine
362 * which
363 * event(s) must occur before returning from pend(). The timeout parameter
364 * allows the task to wait until a timeout, wait indefinitely, or not wait
365 * at all. A return value of zero indicates that a timeout has occurred. A
366 * non-zero return value is the set of events that were active at the time
367 * the task was unblocked.
368 *
369 * The andMask defines a set of events that must
370 * ALL occur to allow pend() to return.
371 *
372 * The orMask defines a set of events
373 * that will cause pend() to return if ANY of them occur.
374 *
375 * All active events
376 * present in the orMask are consumed (i.e. removed from the event object)
377 * upon return from pend(). Only when all events present in the andMask
378 * are active are they consumed on return from pend().
379 *
380 * The pend conditions are satisfied when either ALL of the events
381 * in the andMask occur or ANY of the events in the orMask occur.
382 *
383 * A timeout value of
384 * {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
385 * the task to wait indefinitely for matching events to be posted.
386 *
387 * A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
388 * causes Event_pend to return immediately.
389 *
390 * @param(andMask) return from pend() when ALL of these
391 * events have occurred
392 * @param(orMask) return from pend() when ANY of these
393 * events have occurred
394 * @param(timeout) return from pend() after this many system
395 * time units
396 *
397 * @b(returns) All consumed events or zero if timeout.
398 */
399 @DirectCall
400 UInt pend(UInt andMask, UInt orMask, UInt timeout);
401
402 /*!
403 * ======== post ========
404 * Post event(s) to an event object.
405 *
406 * Event_post() is used to signal events. If a task is waiting for the
407 * event and the event conditions are met, post() unblocks the
408 * task. If no tasks are waiting, post() simply registers the event with
409 * the event object and returns.
410 *
411 * @param(eventMask) mask of eventIds to post (must be non-zero)
412 */
413 @DirectCall
414 Void post(UInt eventMask);
415
416 /*!
417 * ======== getPostedEvents ========
418 * Returns the set of events that have not been consumed by a task
419 * (ie those events that have not fully satisfied any pend() conditions).
420 * No events are consumed!
421 *
422 * @b(returns) All un-consumed events posted to the event.
423 */
424 @DirectCall
425 UInt getPostedEvents();
426
427 /*!
428 * @_nodoc 429 * ======== sync ========
430 * synchronize an eventId to the value given
431 * must call with interrupts disabled
432 *
433 * @param(eventId) eventId to sync
434 * @param(count) count
435 */
436 @DirectCall
437 Void sync(UInt eventId, UInt count);
438
439 /*!
440 * @_nodoc 441 * ======== syncMeta ========
442 * synchronize an eventId to the value given (static version)
443 *
444 * @param(eventId) eventId to sync
445 * @param(count) count
446 */
447 metaonly Void syncMeta(UInt eventId, UInt count);
448
449 internal:
450
451 /*!
452 * ======== pendTimeout ========
453 * This function is the clock event handler for pend
454 */
455 Void pendTimeout(UArg arg);
456
457 /*
458 * ======== checkEvents ========
459 * Checks postedEvents for matching event conditions.
460 * Returns matchingEvents if a match and consumes matched events,
461 * else returns 0 and consumes nothing.
462 * Called with ints disabled
463 */
464 UInt checkEvents (Object *event, UInt andMask, UInt orMask);
465
466 /*
467 * Static instance array used by Semaphore module
468 * to enable Grace to display a list of Event instances
469 * to choose from to configure a Semaphore's 'event' config
470 * parameter.
471 */
472 metaonlyconfig Any eventInstances[];
473
474 /* pendQ Element PendStates */
475 enum PendState {
476 PendState_TIMEOUT = 0, /* Clock timeout */
477 PendState_POSTED = 1, /* posted by post */
478 PendState_CLOCK_WAIT = 2, /* in Clock queue */
479 PendState_WAIT_FOREVER = 3 /* not in Clock queue */
480 };
481
482 /* Event pendQ Element */
483 struct PendElem {
484 Task.PendElem tpElem;
485 PendState pendState;
486 UInt matchingEvents;
487 UInt andMask;
488 UInt orMask;
489 };
490
491 struct Instance_State {
492 volatile UInt postedEvents; /* Current unconsumed events */
493 Queue.Object pendQ; /* queue of PendElems */
494 /* for compatibility with */
495 /* Semaphore */
496 };
497 }