1 /*
2 * Copyright (c) 2013-2014, 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 * ======== dual_transports.c ========
34 * Multiprocessor MessageQ example, demonstrating TransportRpmsg and
35 * TransportShm coexistence.
36 *
37 * Task1 uses MessageQ to pass a message in a ring between DSP CORES.
38 *
39 * Task2 responds the the Host MessageQApp or MessageQBench.
40 *
41 * A semaphore synchronizes Task1 to wait until Task2 starts it, which
42 * is initiated by a sync message from the host.
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>
51 #include <xdc/runtime/Assert.h>
53 /* ----------------------------------- IPC module Headers */
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/knl/Semaphore.h>
63 #include <ti/sysbios/family/c66/Cache.h>
65 /* ----------------------------------- To get globals from .cfg Header */
66 #include <xdc/cfg/global.h>
68 /* Used by multicoreMsgqFxn: */
69 #define HEAP_NAME "myHeapBuf"
70 #define HEAPID 1
71 #define NUMLOOPS 10
73 /* Used by hostMsgqFxn: */
74 #define SLAVE_MESSAGEQNAME "SLAVE"
75 #define MessageQ_payload(m) ((void *)((char *)(m) + sizeof(MessageQ_MsgHeader)))
77 extern volatile cregister UInt DNUM;
79 /*
80 * ======== hostMsgqFxn ========
81 * Receive and return messages to HOST.
82 *
83 * When sync received from host, signal multicoreMesgqFxn to proceed.
84 */
85 Void hostMsgqFxn(UArg arg0, UArg arg1)
86 {
87 MessageQ_Msg msg;
88 MessageQ_Handle messageQ;
89 MessageQ_QueueId remoteQueueId;
90 Char localQueueName[64];
91 UInt16 procId;
92 Int status;
93 UInt16 msgId;
94 UInt32 start;
95 UInt32 end;
96 UInt32 numLoops;
97 UInt32 print;
98 UInt32 *params;
100 /* Construct a MessageQ name adorned with core name: */
101 System_sprintf(localQueueName, "%s_%s", SLAVE_MESSAGEQNAME,
102 MultiProc_getName(MultiProc_self()));
104 messageQ = MessageQ_create(localQueueName, NULL);
105 if (messageQ == NULL) {
106 System_abort("MessageQ_create failed\n" );
107 }
109 System_printf("hostMsgqFxn: created MessageQ: %s; QueueID: 0x%x\n",
110 localQueueName, MessageQ_getQueueId(messageQ));
112 while (1) {
113 /* handshake with host to get starting parameters */
114 System_printf("Awaiting sync message from host...\n");
115 MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
117 params = MessageQ_payload(msg);
118 numLoops = params[0];
119 print = params[1];
121 remoteQueueId = MessageQ_getReplyQueue(msg);
122 procId = MessageQ_getProcId(remoteQueueId);
124 System_printf("Received msg from (procId:remoteQueueId): 0x%x:0x%x\n"
125 "\tpayload: %d bytes; loops: %d %s printing.\n",
126 procId, remoteQueueId,
127 (MessageQ_getMsgSize(msg) - sizeof(MessageQ_MsgHeader)),
128 numLoops, print ? "with" : "without");
130 MessageQ_put(remoteQueueId, msg);
132 /* ==> If CORE0, Kick multicoreMsgqFxn to start running */
133 if (DNUM == 0) {
134 Semaphore_post(semStartMultiCoreTest);
135 }
137 start = Clock_getTicks();
138 for (msgId = 0; msgId < numLoops; msgId++) {
139 status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
140 Assert_isTrue(status == MessageQ_S_SUCCESS, NULL);
142 if (print) {
143 System_printf("Got msg #%d (%d bytes) from procId %d\n",
144 MessageQ_getMsgId(msg), MessageQ_getMsgSize(msg), procId);
145 }
147 Assert_isTrue(MessageQ_getMsgId(msg) == msgId, NULL);
149 if (print) {
150 System_printf("Sending msg Id #%d to procId %d\n", msgId,
151 procId);
152 }
154 status = MessageQ_put(remoteQueueId, msg);
155 Assert_isTrue(status == MessageQ_S_SUCCESS, NULL);
156 }
157 end = Clock_getTicks();
159 if (!print) {
160 System_printf("%d iterations took %d ticks or %d usecs/msg\n",
161 numLoops,
162 end - start, ((end - start) * Clock_tickPeriod) / numLoops);
163 }
164 }
165 }
167 /*
168 * ======== multicoreFxn ========
169 * Allocates a message and ping-pongs the message around the processors.
170 * A local message queue is created and a remote message queue is opened.
171 * Messages are sent to the remote message queue and retrieved from the
172 * local MessageQ.
173 */
174 Void multicoreFxn(UArg arg0, UArg arg1)
175 {
176 MessageQ_Msg msg;
177 MessageQ_Handle messageQ;
178 MessageQ_QueueId remoteQueueId;
179 Int status;
180 UInt16 msgId = 0;
181 HeapBufMP_Handle heapHandle;
182 HeapBufMP_Params heapBufParams;
183 Char localQueueName[10];
184 Char nextQueueName[10];
185 UInt16 nextProcId;
187 System_printf("multicoreFxn: Entered...\n");
189 nextProcId = (MultiProc_self() + 1) % MultiProc_getNumProcessors();
190 if (nextProcId == MultiProc_getId("HOST")) {
191 nextProcId = 1; /* Skip the host: Assumes host id is 0. */
192 }
194 /* Generate queue names based on own proc ID and total number of procs */
195 System_sprintf(localQueueName, "%s", MultiProc_getName(MultiProc_self()));
196 System_sprintf(nextQueueName, "%s", MultiProc_getName(nextProcId));
198 if (MultiProc_self() == MultiProc_getId("CORE0")) {
199 /*
200 * Create the heap that will be used to allocate messages.
201 */
202 System_printf("multicoreFxn: Creating HeapBufMP...\n");
203 HeapBufMP_Params_init(&heapBufParams);
204 heapBufParams.regionId = 0;
205 heapBufParams.name = HEAP_NAME;
206 heapBufParams.numBlocks = 1;
207 heapBufParams.blockSize = sizeof(MessageQ_MsgHeader);
208 heapHandle = HeapBufMP_create(&heapBufParams);
209 if (heapHandle == NULL) {
210 System_abort("HeapBufMP_create failed\n" );
211 }
212 }
213 else {
214 System_printf("multicoreFxn: Opening HeapBufMP...\n");
215 /* Open the heap created by the other processor. Loop until opened. */
216 do {
217 status = HeapBufMP_open(HEAP_NAME, &heapHandle);
218 /*
219 * Sleep for 1 clock tick to avoid inundating remote processor
220 * with interrupts if open failed
221 */
222 if (status < 0) {
223 Task_sleep(1);
224 }
225 } while (status < 0);
226 }
228 /* Register this heap with MessageQ */
229 MessageQ_registerHeap((IHeap_Handle)heapHandle, HEAPID);
231 /* Create the local message queue */
232 messageQ = MessageQ_create(localQueueName, NULL);
233 if (messageQ == NULL) {
234 System_abort("MessageQ_create failed\n" );
235 }
237 /* Open the remote message queue. Spin until it is ready. */
238 System_printf("multicoreFxn: Opening Remote Queue: %s...\n", nextQueueName);
239 do {
240 status = MessageQ_open(nextQueueName, &remoteQueueId);
241 /*
242 * Sleep for 1 clock tick to avoid inundating remote processor
243 * with interrupts if open failed
244 */
245 if (status < 0) {
246 Task_sleep(1);
247 }
248 } while (status < 0);
250 if (MultiProc_self() == MultiProc_getId("CORE0")) {
251 /* Allocate a message to be ping-ponged around the processors */
252 msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
253 if (msg == NULL) {
254 System_abort("MessageQ_alloc failed\n" );
255 }
257 while (1) {
259 /* ==> If CORE0, wait for signal from hostMsgqFxn to start loop: */
260 if (DNUM == 0) {
261 Semaphore_pend(semStartMultiCoreTest, BIOS_WAIT_FOREVER);
262 }
264 /*
265 * Send the message to the next processor and wait for a message
266 * from the previous processor.
267 */
268 System_printf("multicoreFxn: Sender: Start the main loop\n");
269 for (msgId = 0; msgId < NUMLOOPS; msgId++) {
270 /* Increment...the remote side will check this */
271 MessageQ_setMsgId(msg, msgId);
273 System_printf("Sending message #%d to %s\n", msgId, nextQueueName);
275 /* send the message to the next processor */
276 status = MessageQ_put(remoteQueueId, msg);
277 if (status < 0) {
278 System_abort("MessageQ_put had a failure/error\n");
279 }
281 /* Get a message */
282 status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
283 if (status < 0) {
284 System_abort("This should not happen as timeout is forever\n");
285 }
286 }
287 }
288 }
289 else {
291 /*
292 * Wait for a message from the previous processor and
293 * send it to the next processor
294 */
295 System_printf("multicoreFxn: Receiver: Start the main loop\n");
296 while (TRUE) {
297 /* Get a message */
298 status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
299 if (status < 0) {
300 System_abort("This should not happen since timeout is forever\n");
301 }
303 /* Get the message id */
304 msgId = MessageQ_getMsgId(msg);
306 System_printf("Sending a message #%d to %s\n", msgId,
307 nextQueueName);
309 /* send the message to the remote processor */
310 status = MessageQ_put(remoteQueueId, msg);
311 if (status < 0) {
312 System_abort("MessageQ_put had a failure/error\n");
313 }
315 /* test done */
316 if (msgId >= NUMLOOPS) {
317 System_printf("multicore loop test is complete\n");
318 }
319 }
320 }
321 }
323 /*
324 * ======== main ========
325 * Creates thread and calls BIOS_start
326 */
327 Int main(Int argc, Char* argv[])
328 {
329 /* Put CCS breakpoint for CORE0 */
330 #if 0
331 if (DNUM == 0) {
332 /* Wait until we connect CCS; write 1 to var spin to continue: */
333 volatile int spin = 1;
334 while(spin);
335 }
336 #endif
338 System_printf("main: MultiProc id: %d\n", MultiProc_self());
340 Task_create(multicoreFxn, NULL, NULL);
341 Task_create(hostMsgqFxn, NULL, NULL);
343 BIOS_start();
345 return (0);
346 }