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 * ======== message_multicore.c ========
34 * Multiprocessor MessageQ example
35 *
36 * This is an example program that uses MessageQ to pass a message
37 * from one processor to another.
38 *
39 * Each processor creates its own MessageQ first and then will try to open
40 * a remote processor's MessageQ.
41 *
42 * See message_multicore.k file for expected output.
43 */
45 #include <xdc/std.h>
46 #include <string.h>
48 /* -----------------------------------XDC.RUNTIME module Headers */
49 #include <xdc/runtime/System.h>
50 #include <xdc/runtime/IHeap.h>
52 /* ----------------------------------- IPC module Headers */
53 #include <ti/ipc/Ipc.h>
54 #include <ti/ipc/MessageQ.h>
55 #include <ti/ipc/HeapBufMP.h>
56 #include <ti/ipc/MultiProc.h>
58 /* ----------------------------------- BIOS6 module Headers */
59 #include <ti/sysbios/BIOS.h>
60 #include <ti/sysbios/knl/Task.h>
61 #include <ti/sysbios/knl/Clock.h>
62 #include <ti/sysbios/family/c66/Cache.h>
64 /* ----------------------------------- To get globals from .cfg Header */
65 #include <xdc/cfg/global.h>
67 /* Define this to eliminate VIRTIO DEV and VRINGS from rsc_table: */
68 #define TRACE_RESOURCE_ONLY 1
69 extern char * xdc_runtime_SysMin_Module_State_0_outbuf__A;
70 #if defined(TCI6614)
71 #include <ti/ipc/remoteproc/rsc_table_tci6614.h>
72 #elif defined(TCI6614_v33)
73 #include <ti/ipc/remoteproc/rsc_table_tci6614_v3.3.h>
74 #elif defined(TCI6638)
75 #include <ti/ipc/remoteproc/rsc_table_tci6638.h>
76 #endif
78 #define HEAP_NAME "myHeapBuf"
79 #define HEAPID 0
80 #define NUMLOOPS 10
82 Char localQueueName[10];
83 Char nextQueueName[10];
84 UInt16 nextProcId;
86 /*
87 * ======== tsk0_func ========
88 * Allocates a message and ping-pongs the message around the processors.
89 * A local message queue is created and a remote message queue is opened.
90 * Messages are sent to the remote message queue and retrieved from the
91 * local MessageQ.
92 */
93 Void tsk0_func(UArg arg0, UArg arg1)
94 {
95 MessageQ_Msg msg;
96 MessageQ_Handle messageQ;
97 MessageQ_QueueId remoteQueueId;
98 Int status;
99 UInt16 msgId = 0;
100 HeapBufMP_Handle heapHandle;
101 HeapBufMP_Params heapBufParams;
103 if (MultiProc_self() == 0) {
104 /*
105 * Create the heap that will be used to allocate messages.
106 */
107 HeapBufMP_Params_init(&heapBufParams);
108 heapBufParams.regionId = 0;
109 heapBufParams.name = HEAP_NAME;
110 heapBufParams.numBlocks = 1;
111 heapBufParams.blockSize = sizeof(MessageQ_MsgHeader);
112 heapHandle = HeapBufMP_create(&heapBufParams);
113 if (heapHandle == NULL) {
114 System_abort("HeapBufMP_create failed\n" );
115 }
116 }
117 else {
118 /* Open the heap created by the other processor. Loop until opened. */
119 do {
120 status = HeapBufMP_open(HEAP_NAME, &heapHandle);
121 /*
122 * Sleep for 1 clock tick to avoid inundating remote processor
123 * with interrupts if open failed
124 */
125 if (status < 0) {
126 Task_sleep(1);
127 }
128 } while (status < 0);
129 }
131 /* Register this heap with MessageQ */
132 MessageQ_registerHeap((IHeap_Handle)heapHandle, HEAPID);
134 /* Create the local message queue */
135 messageQ = MessageQ_create(localQueueName, NULL);
136 if (messageQ == NULL) {
137 System_abort("MessageQ_create failed\n" );
138 }
140 /* Open the remote message queue. Spin until it is ready. */
141 do {
142 status = MessageQ_open(nextQueueName, &remoteQueueId);
143 /*
144 * Sleep for 1 clock tick to avoid inundating remote processor
145 * with interrupts if open failed
146 */
147 if (status < 0) {
148 Task_sleep(1);
149 }
150 } while (status < 0);
152 if (MultiProc_self() == 0) {
153 /* Allocate a message to be ping-ponged around the processors */
154 msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
155 if (msg == NULL) {
156 System_abort("MessageQ_alloc failed\n" );
157 }
159 /*
160 * Send the message to the next processor and wait for a message
161 * from the previous processor.
162 */
163 System_printf("Start the main loop\n");
164 while (msgId < NUMLOOPS) {
165 /* Increment...the remote side will check this */
166 msgId++;
167 MessageQ_setMsgId(msg, msgId);
169 System_printf("Sending a message #%d to %s\n", msgId, nextQueueName);
171 /* send the message to the remote processor */
172 status = MessageQ_put(remoteQueueId, msg);
173 if (status < 0) {
174 System_abort("MessageQ_put had a failure/error\n");
175 }
177 /* Get a message */
178 status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
179 if (status < 0) {
180 System_abort("This should not happen since timeout is forever\n");
181 }
182 }
183 }
184 else {
185 /*
186 * Wait for a message from the previous processor and
187 * send it to the next processor
188 */
189 System_printf("Start the main loop\n");
190 while (TRUE) {
191 /* Get a message */
192 status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
193 if (status < 0) {
194 System_abort("This should not happen since timeout is forever\n");
195 }
197 System_printf("Sending a message #%d to %s\n", MessageQ_getMsgId(msg),
198 nextQueueName);
200 /* Get the message id */
201 msgId = MessageQ_getMsgId(msg);
203 /* send the message to the remote processor */
204 status = MessageQ_put(remoteQueueId, msg);
205 if (status < 0) {
206 System_abort("MessageQ_put had a failure/error\n");
207 }
209 /* test done */
210 if (msgId >= NUMLOOPS) {
211 break;
212 }
213 }
214 }
216 System_printf("The test is complete\n");
217 BIOS_exit(0);
218 }
220 #define CACHE_WB_TICK_PERIOD 5
222 /*
223 * ======== VirtQueue_cacheWb ========
224 *
225 * Used for flushing SysMin trace buffer.
226 */
227 Void traceBuf_cacheWb()
228 {
229 static UInt32 oldticks = 0;
230 UInt32 newticks;
232 newticks = Clock_getTicks();
233 if (newticks - oldticks < (UInt32)CACHE_WB_TICK_PERIOD) {
234 /* Don't keep flushing cache */
235 return;
236 }
238 oldticks = newticks;
240 Cache_wbAll();
242 }
244 /*
245 * ======== main ========
246 * Synchronizes all processors (in Ipc_start) and calls BIOS_start
247 */
248 Int main(Int argc, Char* argv[])
249 {
250 Int status;
252 #if defined(TCI6614_v33)
253 /* Reference resource table, until IpcMemory.xdt is enabled for TCI66xx */
254 System_printf("Resource Table: 0x%lx\n", resources);
255 #elif defined (TCI6614) || defined(TCI6638)
256 System_printf("%d Resource Table entries at 0x%x\n",
257 ti_ipc_remoteproc_ResourceTable.num,
258 &ti_ipc_remoteproc_ResourceTable);
259 #endif
261 nextProcId = (MultiProc_self() + 1) % MultiProc_getNumProcessors();
263 /* Generate queue names based on own proc ID and total number of procs */
264 System_sprintf(localQueueName, "%s", MultiProc_getName(MultiProc_self()));
265 System_sprintf(nextQueueName, "%s", MultiProc_getName(nextProcId));
267 /*
268 * Ipc_start() calls Ipc_attach() to synchronize all remote processors
269 * because 'Ipc.procSync' is set to 'Ipc.ProcSync_ALL' in *.cfg
270 */
271 status = Ipc_start();
272 if (status < 0) {
273 System_abort("Ipc_start failed\n");
274 }
276 BIOS_start();
278 return (0);
279 }
280 /*
281 * @(#) ti.sdo.ipc.examples.multicore.evm667x; 1, 0, 0, 0,2; 10-19-2011 10:53:19; /db/vtree/library/trees/ipc/ipc.git/src/ null
282 */