b6c302de23bd08c88ee07a1e4b25eb091a8526e1
[processor-sdk/big-data-ipc-examples.git] / host_bios / simple_buffer_example / host / App.c
1 /*
2  * Copyright (c) 2017 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  */
33 /*
34  *  ======== App.c ========
35  */
37 /* package header files */
38 #include <xdc/std.h>
39 #include <xdc/runtime/Diags.h>
40 #include <xdc/runtime/Error.h>
41 #include <xdc/runtime/IHeap.h>
42 #include <xdc/runtime/Log.h>
43 #include <xdc/runtime/Memory.h>
44 #include <xdc/runtime/System.h>
46 #include <ti/ipc/Ipc.h>
47 #include <ti/ipc/MessageQ.h>
48 #include <ti/ipc/MultiProc.h>
49 #include <ti/ipc/SharedRegion.h>
51 #include <ti/sysbios/heaps/HeapBuf.h>
52 #include <ti/sysbios/knl/Task.h>
53 #include <ti/ipc/HeapMemMP.h>
54 #include <ti/sysbios/hal/Cache.h>
56 /* local header files */
57 #include "../shared/AppCommon.h"
58 #include "App.h"
60 /* round up the value 'size' to the next 'align' boundary */
61 #define ROUNDUP(size, align) \
62     (UInt32)(((UInt32)(size) + ((UInt32)(align) - 1)) & ~((UInt32)(align) - 1))
64 #define MAX_NUM_MSGS 4
66 /* module structure */
67 typedef struct {
68     MessageQ_Handle     hostQue;    // created locally
69     MessageQ_QueueId    slaveQue;   // opened remotely
70     UInt16              heapId;     // MessageQ heapId
71     HeapBuf_Handle      heap;       // message heap
72     Int                 msgSize;    // aligned size of message
73     Int                 poolSize;   // size of message pool
74     Ptr                 store;      // memory store for message pool
75 } App_Module;
77 /* private data */
78 static App_Module Module;
80 /*
81  *  ======== App_create ========
82  */
84 Int App_create(UInt16 remoteProcId)
85 {
86     Int                 status = 0;
87     Int                 align;
88     Error_Block         eb;
89     IHeap_Handle        srHeap;
90     HeapBuf_Params      heapParams;
91     MessageQ_Params     msgqParams;
92     char                msgqName[32];
94     Log_print0(Diags_INFO, "App_create: -->");
96     /* setting default values */
97     Module.hostQue = NULL;
98     Module.slaveQue = MessageQ_INVALIDMESSAGEQ;
99     Module.heapId = App_MsgHeapId;
100     Module.msgSize = 0;
102     /* compute message size to fill entire cache lines */
103     align = SharedRegion_getCacheLineSize(0);
104     Module.msgSize = ROUNDUP(sizeof(App_Msg), align);
106     /* compute message pool size */
107     Module.poolSize = Module.msgSize * MAX_NUM_MSGS;
109     /* acquire message pool memory */
110     srHeap = (IHeap_Handle)SharedRegion_getHeap(0);
111     Module.store = Memory_alloc(srHeap, Module.poolSize, align, NULL);
113     /* create a heap in shared memory for message pool */
114     HeapBuf_Params_init(&heapParams);
115     heapParams.blockSize = Module.msgSize;
116     heapParams.numBlocks = MAX_NUM_MSGS;
117     heapParams.bufSize = Module.poolSize;
118     heapParams.align = align;
119     heapParams.buf = Module.store;
120     Error_init(&eb);
122     Module.heap = HeapBuf_create(&heapParams, &eb);
124     if (Module.heap == NULL) {
125         Log_error0("App_create: failed creating message pool");
126         status = -1;
127         goto leave;
128     }
130     /* bind message pool to heapId */
131     MessageQ_registerHeap((Ptr)(Module.heap), App_MsgHeapId);
133     /* create local message queue (inbound messages) */
134     MessageQ_Params_init(&msgqParams);
136     Module.hostQue = MessageQ_create(NULL, &msgqParams);
138     if (Module.hostQue == NULL) {
139         Log_error0("App_create: failed creating MessageQ");
140         status = -1;
141         goto leave;
142     }
144     /* open the remote message queue */
145     System_sprintf(msgqName, App_SlaveMsgQueName,
146             MultiProc_getName(remoteProcId));
148     do {
149         status = MessageQ_open(msgqName, &Module.slaveQue);
150         Task_sleep(1);
151     } while (status == MessageQ_E_NOTFOUND);
153     if (status < 0) {
154         Log_error0("App_create: failed opening MessageQ");
155         goto leave;
156     }
158     Log_print0(Diags_INFO, "App_create: Host is ready");
160 leave:
161     Log_print1(Diags_INFO, "App_create: <-- status=%d", (IArg)status);
162     return(status);
165 /*
166  *  ======== App_delete ========
167  */
168 Int App_delete(Void)
170     Int             status;
171     IHeap_Handle    srHeap;
173     Log_print0(Diags_INFO, "App_delete: -->");
175     /* close remote resources */
176     status = MessageQ_close(&Module.slaveQue);
178     if (status < 0) {
179         goto leave;
180     }
182     /* delete the host message queue */
183     status = MessageQ_delete(&Module.hostQue);
185     if (status < 0) {
186         goto leave;
187     }
189     /* unregister message pool heap */
190     MessageQ_unregisterHeap(App_MsgHeapId);
192     /* delete the message pool heap */
193     HeapBuf_delete(&Module.heap);
195     /* release message pool memory */
196     srHeap = (IHeap_Handle)SharedRegion_getHeap(0);
197     Memory_free(srHeap, Module.store, Module.poolSize);
199 leave:
200     Log_print1(Diags_INFO, "App_delete: <-- status=%d", (IArg)status);
201     return(status);
204 /*
205  *  ======== App_exec ========
206  */
207 Int App_exec(Void)
209     Int         status;
210     App_Msg *   msg;
211     UInt32 *bigDataLocalPtr;
212     Int         i,j;
213     UInt16  regionId1;
214     Memory_Stats stats;
215     HeapMemMP_ExtendedStats extStats;
216     SharedRegion_Entry *pSrEntry;
217     HeapMemMP_Params heapMemMp_params;
218     HeapMemMP_Handle sr1Heap;
219     UInt16 regionId;
220     HeapMemMP_Handle srHeap;
221     UInt32 errorCount=0;
222     Int retVal;
223     bigDataLocalDesc_t bigDataLocalDesc;
225     Log_print0(Diags_INFO, "App_exec: -->");
227     /* obtain information about heap (if any) in SR_1 */
228     regionId1 = SharedRegion_getIdByName("SR_1");
229     Log_print1(Diags_INFO, "App_taskFxn: SR_1 region Id=%d",regionId1);
230     sr1Heap = SharedRegion_getHeap(regionId1);
231     if (sr1Heap != NULL)
232     {
233         Log_error0("App_taskFxn: Error: Example assumes shared region without preconfigured heap");
234         status = -1;
235         goto leave;
236     }
237     else
238     {
239         Log_print0(Diags_INFO, "App_taskFxn: SR_1, sr1Heap=NULL");
240         
241         pSrEntry = SharedRegion_getEntryPtr(regionId1);
242         Log_print1(Diags_INFO, "App_taskFxn: SR_1, len=%d", pSrEntry->len);
244         /* Create HeapMP at run-time:
245            This heap is intended to be used for big data ipc */
246         HeapMemMP_Params_init(&heapMemMp_params);
247         heapMemMp_params.name = "sr1HeapMemMp";
248         heapMemMp_params.sharedAddr = pSrEntry->base;
249         heapMemMp_params.sharedBufSize = ROUNDUP(pSrEntry->len, pSrEntry->cacheLineSize); 
250         heapMemMp_params.gate = NULL;
251         sr1Heap = HeapMemMP_create(&heapMemMp_params);
252         if (!sr1Heap) {
253             Log_error0("srHeap creation failed");
254             status = -1;
255             goto leave;
256         }
257         HeapMemMP_getStats((HeapMemMP_Handle)sr1Heap, &stats);
258         Log_print3(Diags_INFO, "App_taskFxn: SR_1 heap, totalSize=%d,totalFreeSize=%d,largestFreeSize=%d", (IArg)stats.totalSize, (IArg)stats.totalFreeSize, (IArg)stats.largestFreeSize);
259         HeapMemMP_getExtendedStats((HeapMemMP_Handle)sr1Heap, &extStats);
260         Log_print2(Diags_INFO, "App_taskFxn: SR_1 heap, buf=0x%x,size=%d", (IArg)extStats.buf, (IArg)extStats.size);
261     }
263     srHeap = sr1Heap;
264     regionId = regionId1;
266     /* fill process pipeline */
267     for (i = 1; i <= 3; i++) {
268         Log_print1(Diags_INFO, "App_exec: sending message %d", (IArg)i);
270         /* allocate message */
271         msg = (App_Msg *)MessageQ_alloc(Module.heapId, Module.msgSize);
273         if (msg == NULL) {
274             status = -1;
275             goto leave;
276         }
278         /* set the return address in the message header */
279         MessageQ_setReplyQueue(Module.hostQue, (MessageQ_Msg)msg);
281         if ( i == 1) {
282             /* fill in message payload for Shared region init*/
283             msg->cmd = App_CMD_SHARED_REGION_INIT;
284             msg->id = i;
285             msg->regionId = regionId;
286             /* Passing the local shared memory address to the remote */
287             /* Actually this can be any allocated buffer for the used for the heap */
288             msg->u.sharedRegionInitCfg.base = (intptr_t)(pSrEntry->base);
289             msg->u.sharedRegionInitCfg.size = (UInt64)(pSrEntry->len);
290         } else {
291             /* fill in message payload */
292             msg->cmd = App_CMD_NOP;
293             msg->id = i;
294         }
296         /* send message */
297         MessageQ_put(Module.slaveQue, (MessageQ_Msg)msg);
298     }
300     /* process steady state (keep pipeline full) */
301     for (i = 4; i <= 16; i++) {
303         /* Now this section of code starts receiving messages
304            See the next section for the code for sending further messages */
305         /* Receive messages: Start <======================================= */
307         /* wait for return message */
308         status = MessageQ_get(Module.hostQue, (MessageQ_Msg *)&msg,
309             MessageQ_FOREVER);
311         if (status < 0) {
312             goto leave;
313         }
315         /* extract message payload */
317         if (msg->cmd == App_CMD_BIGDATA) {
319             retVal = bigDataXlatetoLocalAndSync(msg->regionId,
320                 &msg->u.bigDataSharedDesc, &bigDataLocalDesc);
321             if (retVal) {
322                 status = -1;
323                 goto leave;
324             }
325             bigDataLocalPtr = (UInt32 *)bigDataLocalDesc.localPtr;
326 #ifdef DEBUG
327             /* print data from big data buffer */
328             Log_print1(Diags_INFO, " Received back buffer %d", msg->id);
329             Log_print0(Diags_INFO, " First 8 bytes: ");
330             for ( j = 0; j < 8 && j < bigDataLocalDesc.size/sizeof(uint32_t); j+=4)
331                 Log_print4(Diags_INFO, "0x%x, 0x%x, 0x%x, 0x%x",
332                     bigDataLocalPtr[j], bigDataLocalPtr[j+1], bigDataLocalPtr[j+2], bigDataLocalPtr[j+3]);
333             Log_print0(Diags_INFO, " Last 8 bytes: ");
334             for ( j = (bigDataLocalDesc.size/sizeof(uint32_t))-8 ;
335                  j < bigDataLocalDesc.size/sizeof(uint32_t); j+=4)
336                 Log_print4(Diags_INFO, "0x%x, 0x%x, 0x%x, 0x%x",
337                     bigDataLocalPtr[j], bigDataLocalPtr[j+1], bigDataLocalPtr[j+2], bigDataLocalPtr[j+3]);
338 #endif
339             /* Check values to see expected results */
340             for( j=0; j < bigDataLocalDesc.size/sizeof(uint32_t); j++) {
341                 if ( bigDataLocalPtr[j] != (msg->id+10+j) ) {
342                     errorCount++;
343                 }
344             }
346             /* Free big data buffer */
347             HeapMemMP_free(srHeap, bigDataLocalPtr, bigDataLocalDesc.size);
348         }
350         /* free the message */
351         MessageQ_free((MessageQ_Msg)msg);
353         Log_print1(Diags_INFO, "App_exec: message received, sending message %d",
354                 (IArg)i);
355         /* Receive messages: End =======================================> */
357         /* Send messages: Start  <======================================= */
359         /* allocate message */
360         msg = (App_Msg *)MessageQ_alloc(Module.heapId, Module.msgSize);
362         if (msg == NULL) {
363             status = -1;
364             goto leave;
365         }
367         /* set the return address in the message header */
368         MessageQ_setReplyQueue(Module.hostQue, (MessageQ_Msg)msg);
370         /* fill in message payload */
371         if (i < 14) {
373             /* Send Big data messages */
375             msg->cmd = App_CMD_BIGDATA;
376             msg->id = i;
378             /* Allocate buffer from HeapMemMP */
379             bigDataLocalPtr = (UInt32 *)(HeapMemMP_alloc(srHeap, BIGDATA_BUF_SIZE, BIGDATA_ALIGN));
381             if (!bigDataLocalPtr) {
382                 status = -1;
383                 goto leave;
384             }
386             /* Fill Big data buffer */
387             for(j=0; j< BIGDATA_BUF_SIZE/sizeof(uint32_t); j++) {
388                bigDataLocalPtr[j] = j+i;
389             }
391             /* Populate the Local descriptor */
392             bigDataLocalDesc.localPtr = (Ptr)bigDataLocalPtr;
393             bigDataLocalDesc.size = BIGDATA_BUF_SIZE;
395             retVal = bigDataXlatetoGlobalAndSync(regionId,
396                 &bigDataLocalDesc, &msg->u.bigDataSharedDesc);
397             if (retVal) {
398                 status = -1;
399                 goto leave;
400             }
401             msg->regionId = regionId;
402         } else {
403             if (i == 16) {
404                 /* Last message will tell the slave to shutdown */
405                 msg->cmd = App_CMD_SHUTDOWN;
406                 msg->id = i;
407             } else {
408                 /* Send dummy NOP messages before shutdown */
409                 msg->cmd = App_CMD_NOP;
410                 msg->id = i;
411             }
412         }
414         /* send message */
415         MessageQ_put(Module.slaveQue, (MessageQ_Msg)msg);
417         /* Send messages: End  =======================================> */
419     }
421     /* drain process pipeline */
422     for (i = 1; i <= 3; i++) {
423         Log_print0(Diags_INFO, "App_exec: message received");
425         /* wait for return message */
426         status = MessageQ_get(Module.hostQue, (MessageQ_Msg *)&msg,
427             MessageQ_FOREVER);
429         if (status < 0) {
430             goto leave;
431         }
433         /* extract message payload */
435         /* free the message */
436         MessageQ_free((MessageQ_Msg)msg);
437     }
439 leave:
440     /* Print error count if non-zero */
441     if (errorCount) {
442         Log_print1(Diags_INFO, "App_exec: Error Count %d", errorCount);
443         status = -1;
444     }
445     else
446         Log_print0(Diags_INFO, "App_exec: Data check clean");
448     Log_print1(Diags_INFO, "App_exec: <-- status=%d", (IArg)status);
449     return(status);