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 37 38 39 40 41 42 43 44 45 46 47 48 49 50
51
52 import xdc.runtime.Error;
53 import xdc.runtime.Assert;
54 import xdc.rov.ViewInfo;
55 import ti.sdo.utils.MultiProc;
56
57 /*!
58 * ======== Ipc ========
59 * IPC Master Manager
60 *
61 * @p(html)
62 * This module has a common header that can be found in the {@link ti.ipc}
63 * package. Application code should include the common header file (not the
64 * RTSC-generated one):
65 *
66 * <PRE>#include <ti/ipc/Ipc.h></PRE>
67 *
68 * The RTSC module must be used in the application's RTSC configuration file
69 * (.cfg):
70 *
71 * <PRE>Ipc = xdc.useModule('ti.sdo.ipc.Ipc');</PRE>
72 *
73 * Documentation for all runtime APIs, instance configuration parameters,
74 * error codes macros and type definitions available to the application
75 * integrator can be found in the
76 * <A HREF="../../../../doxygen/html/files.html">Doxygen documenation</A>
77 * for the IPC product. However, the documentation presented on this page
78 * should be referred to for information specific to the RTSC module, such as
79 * module configuration, Errors, and Asserts.
80 * @p
81 *
82 * The most common static configuration that is required of the Ipc module
83 * is the {@link #procSync} configuration that affects the behavior of the
84 * Ipc_start and Ipc_attach runtime APIs.
85 *
86 * Additionally, certain subsystems of IPC (such as Notify and MessageQ) can
87 * be disabled to save resources on a per-connection basis by configuring Ipc
88 * using {@link #setEntryMeta}.
89 *
90 */
91
92 @Template ("./Ipc.xdt")
93 module Ipc
94 {
95 /*!
96 * ======== ModuleView ========
97 * @_nodoc
98 */
99 metaonly struct ModuleView {
100 UInt16 remoteProcId;
101 Bool attached;
102 Bool setupNotify;
103 Bool setupMessageQ;
104 };
105
106 /*!
107 * ======== rovViewInfo ========
108 * @_nodoc
109 */
110 @Facet
111 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
112 xdc.rov.ViewInfo.create({
113 viewMap: [
114 ['Module',
115 {
116 type: xdc.rov.ViewInfo.MODULE_DATA,
117 viewInitFxn: 'viewInitModule',
118 structName: 'ModuleView'
119 }
120 ],
121 ]
122 });
123
124 /*!
125 * Various configuration options for {@link #procSync}
126 *
127 * The values in this enum affect the behavior of the Ipc_start and
128 * Ipc_attach runtime APIs.
129 *
130 * ProcSync_ALL: Calling Ipc_start will also internally Ipc_attach to
131 * each remote processor. The application should never call Ipc_attach.
132 * This type of startup and synchronization should be used if all IPC
133 * processors on a device start up at the same time and connections should
134 * be established between every possible pair of processors.
135 *
136 * ProcSync_PAIR (default): Calling Ipc_start will perform system-wide IPC
137 * initialization required on all processor, but connections to remote
138 * processors will not be established (i.e. Ipc_attach will never be
139 * called). This configuration should be chosen if synchronization is
140 * required and some/all these conditions are true:
141 * @p(blist)
142 * - It is necessary to control when synchronization with each remote
143 * processor occurs
144 * - Useful work can be done while trying to synchronize with a remote
145 * processor by yielding a thread after each attempt to Ipc_attach
146 * to the processor.
147 * - Connections to all remote processors are unnecessary and connections
148 * should selectively be made to save memory
149 * @p
150 * NOTE: A connection should be made to the owner of region 0 (usually the
151 * processor with id = 0) before any connection to any other remote
152 * processor can be made. For example, if there are three processors
153 * configured with MultiProc, #1 should attach to #0 before it can attach
154 * to #2.
155 *
156 * ProcSync_NONE: This should be selected with caution. Ipc_start will
157 * work exactly as it does with ProcSync_PAIR. However, Ipc_attach will
158 * not synchronize with the remote processor. Callers of Ipc_attach are
159 * bound by the same restrictions imposed by using ProcSync_PAIR.
160 * Additionally, an Ipc_attach to a remote processor whose id is less than
161 * our own has to occur *after* the corresponding remote processor has
162 * called attach to the original processor. For example, processor #2
163 * can call
164 * @p(code)
165 * Ipc_attach(1);
166 * @p
167 * only after processor #1 has called:
168 * @p(code)
169 * Ipc_attach(2);
170 * @p
171 *
172 */
173 enum ProcSync {
174 ProcSync_NONE, /*! ProcSync_PAIR with no synchronization */
175 ProcSync_PAIR, /*! Ipc_start does not Ipc_attach */
176 ProcSync_ALL /*! Ipc_start attach to all remote procs */
177 };
178
179 /*!
180 * Struct used for configuration via {@link #setEntryMeta}
181 *
182 * This structure defines the fields that are to be configured
183 * between the executing processor and a remote processor.
184 */
185 struct Entry {
186 UInt16 remoteProcId; /*! Remote processor id */
187 Bool setupNotify; /*! Whether to setup Notify */
188 Bool setupMessageQ; /*! Whether to setup MessageQ */
189 };
190
191 /*! struct for attach/detach plugs. */
192 struct UserFxn {
193 Int (*attach)(UArg, UInt16);
194 Int (*detach)(UArg, UInt16);
195 };
196
197 198 199 200 201
202
203 /*!
204 * ======== A_addrNotInSharedRegion ========
205 * Assert raised when an address lies outside all known shared regions
206 */
207 config Assert.Id A_addrNotInSharedRegion = {
208 msg: "A_addrNotInSharedRegion: Address not in any shared region"
209 };
210
211 /*!
212 * ======== A_addrNotCacheAligned ========
213 * Assert raised when an address is not cache-aligned
214 */
215 config Assert.Id A_addrNotCacheAligned = {
216 msg: "A_addrNotCacheAligned: Address is not cache aligned"
217 };
218
219 /*!
220 * ======== A_nullArgument ========
221 * Assert raised when a required argument is null
222 */
223 config Assert.Id A_nullArgument = {
224 msg: "A_nullArgument: Required argument is null"
225 };
226
227 /*!
228 * ======== A_nullPointer ========
229 * Assert raised when a pointer is null
230 */
231 config Assert.Id A_nullPointer = {
232 msg: "A_nullPointer: Pointer is null"
233 };
234
235 /*!
236 * ======== A_invArgument ========
237 * Assert raised when an argument is invalid
238 */
239 config Assert.Id A_invArgument = {
240 msg: "A_invArgument: Invalid argument supplied"
241 };
242
243 /*!
244 * ======== A_invParam ========
245 * Assert raised when a parameter is invalid
246 */
247 config Assert.Id A_invParam = {
248 msg: "A_invParam: Invalid configuration parameter supplied"
249 };
250
251 /*!
252 * ======== A_internal ========
253 * Assert raised when an internal error is encountered
254 */
255 config Assert.Id A_internal = {
256 msg: "A_internal: An internal error has occurred"
257 };
258
259 /*!
260 * ======== E_nameFailed ========
261 * Error raised when a name failed to be added to the NameServer
262 *
263 * Error raised in a create call when a name fails to be added
264 * to the NameServer table. This can be because the name already
265 * exists, the table has reached its max length, or out of memory.
266 */
267 config Error.Id E_nameFailed = {
268 msg: "E_nameFailed: '%s' name failed to be added to NameServer"
269 };
270
271 /*!
272 * ======== E_internal ========
273 * Error raised when an internal error occured
274 */
275 config Error.Id E_internal = {
276 msg: "E_internal: An internal error occurred"
277 };
278
279 /*!
280 * ======== E_versionMismatch ========
281 * Error raised when a version mismatch occurs
282 *
283 * Error raised in an open call because there is
284 * a version mismatch between the opener and the creator
285 */
286 config Error.Id E_versionMismatch = {
287 msg: "E_versionMismatch: IPC Module version mismatch: creator: %d, opener: %d"
288 };
289
290 291 292 293 294
295
296 /*!
297 * ======== sr0MemorySetup ========
298 * Whether Shared Region 0 memory is accessible
299 *
300 * Certain devices have a slave MMU that needs to be configured by the
301 * host core before the slave core can access shared region 0. If
302 * the host core is also running BIOS, it is necessary to set this
303 * configuration to 'true', otherwise {@link #start} will always fail.
304 *
305 * This configuration should not be used for devices that don't have
306 * a slave MMU and don't run Linux.
307 */
308 metaonly config Bool sr0MemorySetup;
309
310 /*! @_nodoc
311 * ======== hostProcId ========
312 * Host processor identifier.
313 *
314 * Used to specify the host processor's id. This parameter is only used
315 * in a Syslink system.
316 */
317 metaonly config UInt16 hostProcId = MultiProc.INVALIDID;
318
319 /*!
320 * ======== procSync ========
321 * Affects how Ipc_start and Ipc_attach behave
322 *
323 * Refer to the documentation for the {@link #ProcSync} enum for
324 * information about the various ProcSync options.
325 */
326 config ProcSync procSync = Ipc.ProcSync_PAIR;
327
328 /*! @_nodoc
329 * ======== generateSlaveDataForHost ========
330 * generates the slave's data into a section for the host.
331 */
332 config Bool generateSlaveDataForHost;
333
334 /*!@_nodoc
335 * ======== userFxn ========
336 * Attach and Detach hooks.
337 */
338 config UserFxn userFxn;
339
340 341 342 343 344
345
346 /*!
347 * ======== addUserFxn ========
348 * Add a function that gets called during Ipc_attach/detach.
349 *
350 * The user added functions must be non-blocking and must run
351 * to completion. The functions need to check to make sure it
352 * is not called multiple times when more than one thread calls
353 * Ipc_attach() for the same processor. It is safe to use IPC
354 * APIs in a user function as long as the IPC APIs satisfy these
355 * requirements.
356 *
357 * @p(code)
358 * var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
359 * var fxn = new Ipc.UserFxn;
360 * fxn.attach = '&userAttachFxn';
361 * fxn.detach = '&userDetachFxn';
362 * Ipc.addUserFxn(fxn, arg);
363 * @p
364 *
365 * @param(fxn) The user function to call during attach/detach.
366 * @param(arg) The argument to the function.
367 */
368 metaonly Void addUserFxn(UserFxn fxn, UArg arg);
369
370 /*!
371 * ======== getEntry ========
372 * Gets the properties for attaching to a remote processor.
373 *
374 * This function must be called before Ipc_attach(). The
375 * parameter entry->remoteProcId field must be set prior to calling
376 * the function.
377 *
378 * @param(entry) Properties between a pair of processors.
379 */
380 Void getEntry(Entry *entry);
381
382 /*!
383 * ======== setEntryMeta ========
384 * Statically sets the properties for attaching to a remote processor.
385 *
386 * This function allows the user to configure whether Notify and/or
387 * MessageQ is setup during Ipc_attach(). If 'setupNotify' is set
388 * to 'false', neither the Notify or NameServerRemoteNotify instances
389 * are created. If 'setupMessageQ' is set to 'false', the MessageQ
390 * transport instances are not created. By default, both flags are
391 * set to 'true'.
392 *
393 * Note: For any pair of processors, the flags must be the same
394 *
395 * @param(entry) Properties between a pair of processors.
396 */
397 metaonly Void setEntryMeta(Entry entry);
398
399 /*!
400 * ======== setEntry ========
401 * Sets the properties for attaching to a remote processor.
402 *
403 * This function must be called before Ipc_attach(). It allows
404 * the user to configure whether Notify and/or MessageQ is setup
405 * during Ipc_attach(). If 'setupNotify' is set to 'FALSE',
406 * neither the Notify or NameServerRemoteNotify instances are
407 * created. If 'setupMessageQ' is set to 'FALSE', the MessageQ
408 * transport instances are not created. By default, both flags are
409 * set to 'TRUE'.
410 *
411 * Note: For any pair of processors, the flags must be the same
412 *
413 * @param(entry) Properties between a pair of processors.
414 */
415 Void setEntry(Entry *entry);
416
417 /*! @_nodoc
418 * This is needed to prevent the Ipc module from being optimized away
419 * during the whole_program[_debug] partial link.
420 */
421 Void dummy();
422
423
424 internal:
425
426
427 const UInt32 PROCSYNCSTART = 1;
428
429
430 const UInt32 PROCSYNCFINISH = 2;
431
432
433 const UInt32 PROCSYNCDETACH = 3;
434
435
436 enum ObjType {
437 ObjType_CREATESTATIC = 0x1,
438 ObjType_CREATESTATIC_REGION = 0x2,
439 ObjType_CREATEDYNAMIC = 0x4,
440 ObjType_CREATEDYNAMIC_REGION = 0x8,
441 ObjType_OPENDYNAMIC = 0x10,
442 ObjType_LOCAL = 0x20
443 };
444
445 446 447 448
449 struct ConfigEntry {
450 Bits32 remoteProcId;
451 Bits32 localProcId;
452 Bits32 tag;
453 Bits32 size;
454 Bits32 next;
455 };
456
457 /*!
458 * head of the config list
459 */
460 struct ConfigHead {
461 volatile Bits32 first;
462 };
463
464 struct ProcEntry {
465 Ptr localConfigList;
466 Ptr remoteConfigList;
467 UInt attached;
468 Entry entry;
469 };
470
471
472 struct Reserved {
473 volatile Bits32 startedKey;
474 SharedRegion.SRPtr notifySRPtr;
475 SharedRegion.SRPtr nsrnSRPtr;
476 SharedRegion.SRPtr transportSRPtr;
477 SharedRegion.SRPtr configListHead;
478 };
479
480
481 struct UserFxnAndArg {
482 UserFxn userFxn;
483 UArg arg;
484 };
485
486
487 metaonly config Entry entry[];
488
489 config UInt numUserFxns = 0;
490
491 /*!
492 * ======== userFxns ========
493 * Attach and Detach hooks.
494 */
495 config UserFxnAndArg userFxns[] = [];
496
497 /*!
498 * ======== getMasterAddr() ========
499 */
500 Ptr getMasterAddr(UInt16 remoteProcId, Ptr sharedAddr);
501
502 /*!
503 * ======== getRegion0ReservedSize ========
504 * Returns the amount of memory to be reserved for Ipc in SharedRegion 0.
505 *
506 * This is used for synchronizing processors.
507 */
508 SizeT getRegion0ReservedSize();
509
510 /*!
511 * ======== getSlaveAddr() ========
512 */
513 Ptr getSlaveAddr(UInt16 remoteProcId, Ptr sharedAddr);
514
515 /*!
516 * ======== procSyncStart ========
517 * Starts the process of synchronizing processors.
518 *
519 * Shared memory in region 0 will be used. The processor which owns
520 * SharedRegion 0 writes its reserve memory address in region 0
521 * to let the other processors know it has started. It then spins
522 * until the other processors start. The other processors write their
523 * reserve memory address in region 0 to let the owner processor
524 * know they've started. The other processors then spin until the
525 * owner processor writes to let them know its finished the process
526 * of synchronization before continuing.
527 */
528 Int procSyncStart(UInt16 remoteProcId, Ptr sharedAddr);
529
530 /*!
531 * ======== procSyncFinish ========
532 * Finishes the process of synchronizing processors.
533 *
534 * Each processor writes its reserve memory address in SharedRegion 0
535 * to let the other processors know its finished the process of
536 * synchronization.
537 */
538 Int procSyncFinish(UInt16 remoteProcId, Ptr sharedAddr);
539
540 /*!
541 * ======== reservedSizePerProc ========
542 * The amount of memory required to be reserved per processor.
543 */
544 SizeT reservedSizePerProc();
545
546 /*! Used for populated the 'objType' field in ROV views*/
547 metaonly String getObjTypeStr$view(ObjType type);
548
549
550 struct Module_State {
551 Ptr ipcSharedAddr;
552 Ptr gateMPSharedAddr;
553 ProcEntry procEntry[];
554 };
555 }