Fix test dual_transports to comply with MessageQApp
[ipc/ipcdev.git] / packages / ti / ipc / tests / dual_transports.c
1 /*
2  * Copyright (c) 2013-2015 Texas Instruments Incorporated - http://www.ti.com
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 typedef struct SyncMsg {
80     MessageQ_MsgHeader header;
81     UInt32 numLoops;  /* also used for msgId */
82     UInt32 print;
83 } SyncMsg;
86 /*
87  *  ======== hostMsgqFxn ========
88  *  Receive and return messages to HOST.
89  *
90  *  When sync received from host, signal multicoreMesgqFxn to proceed.
91  */
92 Void hostMsgqFxn(UArg arg0, UArg arg1)
93 {
94     MessageQ_Msg msg;
95     MessageQ_Handle  messageQ;
96     MessageQ_QueueId remoteQueueId;
97     Char             localQueueName[64];
98     UInt16 procId;
99     Int status;
100     UInt16 msgId;
101     UInt32 start;
102     UInt32 end;
103     UInt32 numLoops;
104     UInt32 print;
105     UInt32 msgNum;
107     /* Construct a MessageQ name adorned with core name: */
108     System_sprintf(localQueueName, "%s_%s", SLAVE_MESSAGEQNAME,
109                    MultiProc_getName(MultiProc_self()));
111     messageQ = MessageQ_create(localQueueName, NULL);
112     if (messageQ == NULL) {
113         System_abort("MessageQ_create failed\n" );
114     }
116     System_printf("hostMsgqFxn: created MessageQ: %s; QueueID: 0x%x\n",
117         localQueueName, MessageQ_getQueueId(messageQ));
119     while (1) {
120         /* handshake with host to get starting parameters */
121         System_printf("Awaiting sync message from host...\n");
122         MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
124         numLoops = ((SyncMsg *)msg)->numLoops;
125         print = ((SyncMsg *)msg)->print;
127         remoteQueueId = MessageQ_getReplyQueue(msg);
128         procId = MessageQ_getProcId(remoteQueueId);
130         System_printf("Received msg from (procId:remoteQueueId): 0x%x:0x%x\n"
131             "\tpayload: %d bytes; loops: %d %s printing.\n",
132             procId, remoteQueueId,
133             (MessageQ_getMsgSize(msg) - sizeof(MessageQ_MsgHeader)),
134             numLoops, print ? "with" : "without");
136         MessageQ_put(remoteQueueId, msg);
138         /* ==> If CORE0, Kick multicoreMsgqFxn to start running */
139         if (DNUM == 0) {
140             Semaphore_post(semStartMultiCoreTest);
141         }
143         start = Clock_getTicks();
144         for (msgId = 1; msgId <= numLoops; msgId++) {
145             status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
146             Assert_isTrue(status == MessageQ_S_SUCCESS, NULL);
148             msgNum = ((SyncMsg *)msg)->numLoops;
150             if (print) {
151                 System_printf("Got msg #%d (%d bytes) from procId %d\n",
152                     msgNum, MessageQ_getMsgSize(msg), procId);
153             }
155             Assert_isTrue(msgNum == msgId, NULL);
157             if (print) {
158                 System_printf("Sending msg Id #%d to procId %d\n", msgId,
159                               procId);
160             }
162             status = MessageQ_put(remoteQueueId, msg);
163             Assert_isTrue(status == MessageQ_S_SUCCESS, NULL);
164         }
165         end = Clock_getTicks();
167         if (!print) {
168             System_printf("%d iterations took %d ticks or %d usecs/msg\n",
169                           numLoops,
170             end - start, ((end - start) * Clock_tickPeriod) / numLoops);
171         }
172     }
175 /*
176  *  ======== multicoreFxn ========
177  *  Allocates a message and ping-pongs the message around the processors.
178  *  A local message queue is created and a remote message queue is opened.
179  *  Messages are sent to the remote message queue and retrieved from the
180  *  local MessageQ.
181  */
182 Void multicoreFxn(UArg arg0, UArg arg1)
184     MessageQ_Msg     msg;
185     MessageQ_Handle  messageQ;
186     MessageQ_QueueId remoteQueueId;
187     Int              status;
188     UInt16           msgId = 0;
189     HeapBufMP_Handle              heapHandle;
190     HeapBufMP_Params              heapBufParams;
191     Char localQueueName[10];
192     Char nextQueueName[10];
193     UInt16 nextProcId;
195     System_printf("multicoreFxn: Entered...\n");
197     nextProcId = (MultiProc_self() + 1) % MultiProc_getNumProcessors();
198     if (nextProcId == MultiProc_getId("HOST")) {
199         nextProcId = 1;  /* Skip the host: Assumes host id is 0. */
200     }
202     /* Generate queue names based on own proc ID and total number of procs */
203     System_sprintf(localQueueName, "%s", MultiProc_getName(MultiProc_self()));
204     System_sprintf(nextQueueName, "%s",  MultiProc_getName(nextProcId));
206     if (MultiProc_self() == MultiProc_getId("CORE0")) {
207         /*
208          *  Create the heap that will be used to allocate messages.
209          */
210         System_printf("multicoreFxn: Creating HeapBufMP...\n");
211         HeapBufMP_Params_init(&heapBufParams);
212         heapBufParams.regionId       = 0;
213         heapBufParams.name           = HEAP_NAME;
214         heapBufParams.numBlocks      = 1;
215         heapBufParams.blockSize      = sizeof(MessageQ_MsgHeader);
216         heapHandle = HeapBufMP_create(&heapBufParams);
217         if (heapHandle == NULL) {
218             System_abort("HeapBufMP_create failed\n" );
219         }
220     }
221     else {
222         System_printf("multicoreFxn: Opening HeapBufMP...\n");
223         /* Open the heap created by the other processor. Loop until opened. */
224         do {
225             status = HeapBufMP_open(HEAP_NAME, &heapHandle);
226             /*
227              *  Sleep for 1 clock tick to avoid inundating remote processor
228              *  with interrupts if open failed
229              */
230             if (status < 0) {
231                 Task_sleep(1);
232             }
233         } while (status < 0);
234     }
236     /* Register this heap with MessageQ */
237     MessageQ_registerHeap((IHeap_Handle)heapHandle, HEAPID);
239     /* Create the local message queue */
240     messageQ = MessageQ_create(localQueueName, NULL);
241     if (messageQ == NULL) {
242         System_abort("MessageQ_create failed\n" );
243     }
245     /* Open the remote message queue. Spin until it is ready. */
246     System_printf("multicoreFxn: Opening Remote Queue: %s...\n", nextQueueName);
247     do {
248         status = MessageQ_open(nextQueueName, &remoteQueueId);
249         /*
250          *  Sleep for 1 clock tick to avoid inundating remote processor
251          *  with interrupts if open failed
252          */
253         if (status < 0) {
254             Task_sleep(1);
255         }
256     } while (status < 0);
258     if (MultiProc_self() == MultiProc_getId("CORE0")) {
259         /* Allocate a message to be ping-ponged around the processors */
260         msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
261         if (msg == NULL) {
262            System_abort("MessageQ_alloc failed\n" );
263         }
265         while (1) {
267         /* ==> If CORE0, wait for signal from hostMsgqFxn to start loop: */
268         if (DNUM == 0) {
269             Semaphore_pend(semStartMultiCoreTest, BIOS_WAIT_FOREVER);
270         }
272         /*
273          *  Send the message to the next processor and wait for a message
274          *  from the previous processor.
275          */
276         System_printf("multicoreFxn: Sender: Start the main loop\n");
277         for (msgId = 0; msgId < NUMLOOPS; msgId++) {
278             /* Increment...the remote side will check this */
279             MessageQ_setMsgId(msg, msgId);
281             System_printf("Sending message #%d to %s\n", msgId, nextQueueName);
283             /* send the message to the next processor */
284             status = MessageQ_put(remoteQueueId, msg);
285             if (status < 0) {
286                System_abort("MessageQ_put had a failure/error\n");
287             }
289             /* Get a message */
290             status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
291             if (status < 0) {
292                System_abort("This should not happen as timeout is forever\n");
293             }
294         }
295         }
296     }
297     else {
299         /*
300          *  Wait for a message from the previous processor and
301          *  send it to the next processor
302          */
303         System_printf("multicoreFxn: Receiver: Start the main loop\n");
304         while (TRUE) {
305             /* Get a message */
306             status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
307             if (status < 0) {
308                System_abort("This should not happen since timeout is forever\n");
309             }
311             /* Get the message id */
312             msgId = MessageQ_getMsgId(msg);
314             System_printf("Sending a message #%d to %s\n", msgId,
315                 nextQueueName);
317             /* send the message to the remote processor */
318             status = MessageQ_put(remoteQueueId, msg);
319             if (status < 0) {
320                System_abort("MessageQ_put had a failure/error\n");
321             }
323             /* test done */
324             if (msgId >= NUMLOOPS) {
325                 System_printf("multicore loop test is complete\n");
326             }
327         }
328     }
331 /*
332  *  ======== main ========
333  *  Creates thread and calls BIOS_start
334  */
335 Int main(Int argc, Char* argv[])
337     /* Put CCS breakpoint for CORE0 */
338 #if 0
339     if (DNUM == 0) {
340        /* Wait until we connect CCS; write 1 to var spin to continue: */
341        volatile int spin = 1;
342        while(spin);
343     }
344 #endif
346     System_printf("main: MultiProc id: %d\n", MultiProc_self());
348     Task_create(multicoreFxn, NULL, NULL);
349     Task_create(hostMsgqFxn, NULL, NULL);
351     BIOS_start();
353     return (0);