Synced K2E and K2L DSP+ARM policy file with latest kernel
[keystone-rtos/rm-lld.git] / test / rm_transport_setup.c
1 /*
2  *   rm_transport_setup.c
3  *
4  *   RM test application IPC transport setup code
5  *
6  *  ============================================================================
7  *
8  * Copyright (c) 2013, Texas Instruments Incorporated
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * *  Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  * *  Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * *  Neither the name of Texas Instruments Incorporated nor the names of
23  *    its contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
33  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  */
40 /* XDC includes */ 
41 #include <xdc/std.h>
42 #include <xdc/runtime/IHeap.h>
43 #include <xdc/runtime/System.h>
45 /* IPC includes */ 
46 #include <ti/ipc/Ipc.h>
47 #include <ti/ipc/MessageQ.h>
48 #include <ti/ipc/HeapBufMP.h>
50 /* BIOS Includes */
51 #include <ti/sysbios/knl/Task.h>
53 /* RM Includes */
54 #include <ti/drv/rm/rm_transport.h>
56 /* CSL RL includes */
57 #include <ti/csl/csl_chip.h>
59 #define MAX_TEST_CORES              4
61 /* IPC MessageQ heap name */
62 #define MSGQ_HEAP_NAME              "msgQHeapBuf"
63 /* IPC MessageQ heap ID */
64 #define MSGQ_HEAP_ID                0
66 /* RM packet heap name */
67 #define RM_PKT_HEAP_NAME            "rmHeapBuf"
69 /* IPC MessageQ RM packet encapsulation structure */
70 typedef struct {
71     /* IPC MessageQ header (must be first element in structure) */
72     MessageQ_MsgHeader  msgQHeader;
73     /* Pointer to RM packet */
74     Rm_Packet          *rmPkt;
75 } MsgQ_RmPacket;
77 /* RM registered transport map.  Maps a remote RM instance's transport
78  * handle to the receive MsgQ that packets from this RM instance will be
79  * received on. */
80 typedef struct {
81     /* Registered destintation RM transport handle */
82     Rm_TransportHandle transportHandle;
83     /* MessageQ receive queue tied to the transport handle */
84     MessageQ_Handle    receiveMsgQ;
85 } Transport_MapEntry;
87 /************************ GLOBAL VARIABLES ********************/
88 /* Numer of cores used by the test */
89 uint32_t            testCores = 0;
90 /* Test application's initialization core */
91 uint32_t            initCore = 0;
92 /* Application test task pointer */
93 Task_FuncPtr        appTestTask = NULL;
94 /* Receive task handle */
95 Task_Handle         rcvTask = NULL;
97 /* Handle for heap that RM packets will be allocated from */
98 HeapBufMP_Handle    rmPktHeapHandle = NULL;
100 /* Transport map stores the RM transport handle to IPC MessageQ queue mapping */
101 Transport_MapEntry  rmTransportMap[MAX_TEST_CORES];
103 /************************ EXTERN VARIABLES ********************/
104 extern Rm_Handle rmHandle;
106 extern void Osal_rmBeginMemAccess(void *ptr, uint32_t size);
107 extern void Osal_rmEndMemAccess(void *ptr, uint32_t size);
109 /*************************** FUNCTIONS ************************/
111 Rm_Packet *rmTransPktAlloc(Rm_AppTransportHandle appTransport, uint32_t pktSize, Rm_PacketHandle *pktHandle)
113     Rm_Packet     *rmPkt = NULL;
114     MsgQ_RmPacket *rmMsg = NULL;
115     uint32_t       corenum = CSL_chipReadReg(CSL_CHIP_DNUM);      
117     /* Allocate a messageQ message for containing the RM packet */
118     rmMsg = (MsgQ_RmPacket *)MessageQ_alloc(MSGQ_HEAP_ID, sizeof(MsgQ_RmPacket));
119     if (rmMsg == NULL) {
120         System_printf("Error Core %d : MessageQ_alloc failed to allocate RM packet\n", corenum);
121         *pktHandle = NULL;
122         return(NULL);
123     }
124     else {
125         /* Create and attach RM packet to MessageQ message.  All transports will allocate from the same heap */
126         rmPkt = HeapBufMP_alloc(rmPktHeapHandle, pktSize, 0);
127         rmPkt->pktLenBytes = pktSize;
128         Osal_rmEndMemAccess((void *)rmPkt, rmPkt->pktLenBytes);
129         rmMsg->rmPkt = rmPkt;
130         *pktHandle = (Rm_PacketHandle)rmMsg;
131     }
132     return (rmPkt);
135 void rmTransPktFree (MessageQ_Msg rmMsgQMsg, Rm_Packet *pkt)
137     uint32_t pktSize = pkt->pktLenBytes;
138     uint32_t corenum = CSL_chipReadReg(CSL_CHIP_DNUM);      
139     int32_t  status;
141     /* All transports will free rmPkts to the same heap */
142     HeapBufMP_free(rmPktHeapHandle, pkt, pktSize);
144     status = MessageQ_free(rmMsgQMsg);
145     if (status < 0) { 
146         System_printf("Error Core %d : MessageQ_free of RM packet\n", corenum);
147     }     
150 int32_t rmTransPktSend (Rm_AppTransportHandle appTransport, Rm_PacketHandle pktHandle)
152     MessageQ_QueueId  remoteQueueId = (MessageQ_QueueId)appTransport;
153     MsgQ_RmPacket    *rmMsg = pktHandle;
154     uint32_t          corenum = CSL_chipReadReg(CSL_CHIP_DNUM);      
155     int32_t           status;    
157     /* Write back data that was written by RM after alloc */
158     Osal_rmEndMemAccess((void *)rmMsg->rmPkt, rmMsg->rmPkt->pktLenBytes);
160     /* Send the message to the remote side */
161     status = MessageQ_put(remoteQueueId, (MessageQ_Msg)rmMsg);
162     if (status < 0) {
163         rmTransPktFree((MessageQ_Msg)rmMsg, rmMsg->rmPkt);
164         System_printf("Error Core %d : MessageQ_put sending RM packet : %d\n", corenum, status);
165     }
166     return (status);
169 void rmTransPktRcv (uint32_t transportMapEntry)
171     MessageQ_Handle  receiveQ;
172     int32_t          numPkts;
173     MessageQ_Msg     rmMsg = NULL;
174     Rm_Packet       *rmPkt = NULL;
175     uint32_t         corenum = CSL_chipReadReg(CSL_CHIP_DNUM);  
176     int32_t          status;
177     uint32_t         i;  
179     /* Check if any packets available */
180     receiveQ = rmTransportMap[transportMapEntry].receiveMsgQ;
181     numPkts = (int32_t) MessageQ_count(receiveQ);
183     /* Process all available packets */
184     for (i = 0; i < numPkts; i++) {
185         status = (int32_t) MessageQ_get(receiveQ, &rmMsg, MessageQ_FOREVER);
186         if (rmMsg == NULL) {
187             System_printf("Error Core %d : NULL msg returned by MessageQ\n", corenum);
188         }
190         /* Extract the Rm_Packet from the RM msg */
191         rmPkt = ((MsgQ_RmPacket *)rmMsg)->rmPkt;
192         Osal_rmBeginMemAccess((void *) rmPkt, rmPkt->pktLenBytes);
194         /* Provide packet to RM for processing */
195         if (status = Rm_receivePacket(rmTransportMap[transportMapEntry].transportHandle, rmPkt)) {
196             System_printf("Error Core %d : Receiving RM packet : %d\n", corenum, status);
197         }
199         /* Free RM packet buffer and messageQ message */
200         rmTransPktFree(rmMsg, rmPkt);
201     }
204 void rmReceiveTsk(UArg arg0, UArg arg1)
206     uint32_t corenum = CSL_chipReadReg(CSL_CHIP_DNUM);
207     int      i;
209     while(1) {
210         /* Check the receive MessageQs for received RM packets */
211         for (i = 0; i < testCores; i++) {
212             if (((corenum == initCore) && (i != initCore)) ||
213                 ((corenum != initCore) && (i == initCore))) {
214                 rmTransPktRcv(i);
215             }
216         }
217         /* Sleep for 1ms so that usageTsk can run */
218         Task_sleep(1);
219     }
222 void configRmTransportTsk(UArg arg0, UArg arg1)
224     int32_t           result;
225     uint32_t          corenum = 0;
226     uint32_t          i;
227     HeapBufMP_Params  heapBufParams;
228     HeapBufMP_Handle  msgQHeapHandle;
229     int               status;
230     char              name[RM_NAME_MAX_CHARS];
231     MessageQ_QueueId  remoteRcvQId;
232     Rm_TransportCfg   rmTransportCfg;
233     Task_Params       taskParams;    
234     
235     /* Get the core number. */
236     corenum = CSL_chipReadReg(CSL_CHIP_DNUM);
238     /* Initialize the transport map */
239     for (i = 0; i < testCores; i++) {
240         rmTransportMap[i].transportHandle = NULL;
241     } 
243     /* Configure IPC as the application transport used by RM to communicate between instances
244      * on different cores. */
245     if (corenum == initCore) {
246         /* Create the heap that will be used to allocate RM messages. This
247          * heap is a multi-processor heap.  It will be shared amongst
248          * all RM instances. */     
249         HeapBufMP_Params_init(&heapBufParams);
250         heapBufParams.regionId       = 0;
251         heapBufParams.name           = RM_PKT_HEAP_NAME;
252         heapBufParams.numBlocks      = 16;
253         heapBufParams.blockSize      = sizeof(Rm_Packet);
254         rmPktHeapHandle = HeapBufMP_create(&heapBufParams);
255         if (rmPktHeapHandle == NULL) {
256             System_printf("Error Core %d : RM packet HeapBufMP_create failed \n", corenum);
257         }
258         else {
259             System_printf("Core %d : Created RM packet heap\n", corenum);
260         }
262         /* Create the heap that will be used to allocate messageQ messages. */     
263         HeapBufMP_Params_init(&heapBufParams);
264         heapBufParams.regionId       = 0;
265         heapBufParams.name           = MSGQ_HEAP_NAME;
266         heapBufParams.numBlocks      = 16;
267         heapBufParams.blockSize      = sizeof(MsgQ_RmPacket);
268         msgQHeapHandle = HeapBufMP_create(&heapBufParams);
269         if (msgQHeapHandle == NULL) {
270             System_printf("Error Core %d : IPC MessageQ HeapBufMP_create failed \n", corenum);
271         }
272         else {
273             System_printf("Core %d : Created IPC MessageQ heap\n", corenum);
274         }
275     }
276     else {
277         /* Open the heaps created by initCore core. Loop until opened. */
278         do {
279             status = HeapBufMP_open(RM_PKT_HEAP_NAME, &rmPktHeapHandle);
280             /* 
281              *  Sleep for 1 clock tick to avoid inundating remote processor
282              *  with interrupts if open failed
283              */
284             if (status < 0) { 
285                 Task_sleep(1);
286             }
287         } while (status < 0);
288         System_printf("Core %d : Opened RM packet heap\n", corenum);
289         
290         do {
291             status = HeapBufMP_open(MSGQ_HEAP_NAME, &msgQHeapHandle);
292             /* 
293              *  Sleep for 1 clock tick to avoid inundating remote processor
294              *  with interrupts if open failed
295              */
296             if (status < 0) { 
297                 Task_sleep(1);
298             }
299         } while (status < 0);
300         System_printf("Core %d : Opened IPC MessageQ heap\n", corenum);
301     }
303     /* Register the MessageQ heap with MessageQ */
304     MessageQ_registerHeap(msgQHeapHandle, MSGQ_HEAP_ID); 
306     /* Setup the MessageQs required for RM instances to communicate */
307     for (i = 0; i < testCores; i++) {
308         if ((corenum == initCore) && (i != initCore)) {
309             /* RM Server core transport registration (Should run testCores-1 times) */
310             
311             /* Create a queue to receive messages from a RM client core */
312             System_sprintf(name, "serverRcvQForClient%d", i);
313             rmTransportMap[i].receiveMsgQ = MessageQ_create(name, NULL);
314             if (rmTransportMap[i].receiveMsgQ == NULL) {
315                 System_printf("Error Core %d : Failed to create receive Q for Client%d\n", corenum, i);
316             }
317             else {
318                 System_printf("Core %d : Created receive Q for Client%d\n", corenum, i);
319             }
321             /* Open the RM Client core's receive MessageQ */
322             System_sprintf(name, "client%dRcvQForServer", i);
323             do {
324                 status = MessageQ_open(name, &remoteRcvQId); 
325                 /* 
326                  *  Sleep for 1 clock tick to avoid inundating remote processor
327                  *  with interrupts if open failed
328                  */
329                 if (status < 0) { 
330                     Task_sleep(1);
331                 }
332             } while (status < 0);
333             System_printf("Core %d : Opened Client%d's receive Q for Server\n", corenum, i);
335             /* Register Client receive Q with Server */
336             rmTransportCfg.rmHandle = rmHandle;
337             rmTransportCfg.appTransportHandle = (Rm_AppTransportHandle) remoteRcvQId;
338             rmTransportCfg.remoteInstType = Rm_instType_CLIENT;
339             rmTransportCfg.transportCallouts.rmAllocPkt = rmTransPktAlloc;
340             rmTransportCfg.transportCallouts.rmSendPkt = rmTransPktSend;
341             rmTransportMap[i].transportHandle = Rm_transportRegister(&rmTransportCfg, &result);  
342         }
343         else if ((corenum != initCore) && (i == initCore)) {
344             /* RM Client core transport registration (Should only run once) */
345             
346             /* Create queue to receive messages from Server */
347             System_sprintf(name, "client%dRcvQForServer", corenum);
348             rmTransportMap[i].receiveMsgQ = MessageQ_create(name, NULL);
349             if (rmTransportMap[i].receiveMsgQ == NULL) {
350                 System_printf("Error Core %d : Failed to create receive Q for Server\n", corenum);
351             }
352             else {
353                 System_printf("Core %d : Created receive Q for Server\n", corenum);
354             }
355             
356             /* Open the RM Server core's receive MessageQ for this core */
357             System_sprintf(name, "serverRcvQForClient%d", corenum);
358             do {
359                 status = MessageQ_open(name, &remoteRcvQId); 
360                 /* 
361                  *  Sleep for 1 clock tick to avoid inundating remote processor
362                  *  with interrupts if open failed
363                  */
364                 if (status < 0) { 
365                     Task_sleep(1);
366                 }
367             } while (status < 0);
368             System_printf("Core %d : Opened Server's receive Q\n", corenum);
369             
370             /* Register the Server receive Q */
371             rmTransportCfg.rmHandle = rmHandle;
372             rmTransportCfg.appTransportHandle = (Rm_AppTransportHandle) remoteRcvQId;
373             rmTransportCfg.remoteInstType = Rm_instType_SERVER;
374             rmTransportCfg.transportCallouts.rmAllocPkt = rmTransPktAlloc;
375             rmTransportCfg.transportCallouts.rmSendPkt = rmTransPktSend;
376             rmTransportMap[i].transportHandle = Rm_transportRegister(&rmTransportCfg, &result);   
377         }
378     }
380     /* Create the RM receive task.  Receive task has priority of 2 so that it pre-empts the appTestTask */
381     Task_Params_init (&taskParams);
382     taskParams.priority = 2;
383     rcvTask = Task_create (rmReceiveTsk, &taskParams, NULL);   
385     /* Create the application test task */
386     Task_Params_init (&taskParams);
387     taskParams.priority = 1;
388     Task_create (appTestTask, &taskParams, NULL);     
391 int setupRmTransConfig(uint32_t numTestCores, uint32_t systemInitCore, Task_FuncPtr testTask)
393     Task_Params taskParams;
395     if (numTestCores > MAX_TEST_CORES) {
396         return (-1);
397     }
399     /* Store application core parameters */
400     testCores = numTestCores;
401     initCore = systemInitCore;
403     /* Store the applications testTask for creation after the configRmTransportTsk
404      * runs */
405     appTestTask = testTask;
407     /* Create the RM transport configuration task */
408     Task_Params_init (&taskParams);
409     taskParams.priority = 1;
410     Task_create (configRmTransportTsk, &taskParams, NULL);
412     return(0);
415 int deleteRmTrans(void)
417     uint32_t corenum = 0;
418     uint32_t i;
419     int32_t  rmResult = RM_OK;
420     
421     /* Get the core number. */
422     corenum = CSL_chipReadReg(CSL_CHIP_DNUM);
424     /* Delete the RM receive task */
425     System_printf("Core %d: Deleting RM receive task...\n", corenum);
426     if (rcvTask) {
427         Task_delete(&rcvTask);
428         rcvTask = NULL;
429     }
431     /* Cleanup transport objects */
432     for (i = 0; i < testCores; i++) {
433          if ((corenum == initCore) && (i != initCore)) {
434              if (rmResult = Rm_transportUnregister(rmTransportMap[i].transportHandle) < 0) {
435                 break;
436              }
437          }
438          else if ((corenum != initCore) && (i == initCore)) {
439              if (rmResult = Rm_transportUnregister(rmTransportMap[i].transportHandle) < 0) {
440                 break;
441              }
442          }
443     }
445     return (rmResult);