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