75da880112ad9b7cfd3d625f7792b13c329575b1
[ipc/ipcdev.git] / packages / ti / ipc / tests / dual_transports.c
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     }
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)
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     }
323 /*
324  *  ======== main ========
325  *  Creates thread and calls BIOS_start
326  */
327 Int main(Int argc, Char* argv[])
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);