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