3cac50b19cc4a5cbcd79fac07e8f575ed739239f
[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 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;
81 /*
82  *  ======== App_create ========
83  */
85 Int App_create(UInt16 remoteProcId)
86 {
87     Int                 status = 0;
88     Int                 align;
89     Error_Block         eb;
90     IHeap_Handle        srHeap;
91     HeapBuf_Params      heapParams;
92     MessageQ_Params     msgqParams;
93     char                msgqName[32];
95     Log_print0(Diags_INFO, "App_create: -->");
97     /* setting default values */
98     Module.hostQue = NULL;
99     Module.slaveQue = MessageQ_INVALIDMESSAGEQ;
100     Module.heapId = App_MsgHeapId;
101     Module.msgSize = 0;
103     /* compute message size to fill entire cache lines */
104     align = SharedRegion_getCacheLineSize(0);
105     Module.msgSize = ROUNDUP(sizeof(App_Msg), align);
107     /* compute message pool size */
108     Module.poolSize = Module.msgSize * NUM_MSGS;
110     /* acquire message pool memory */
111     srHeap = (IHeap_Handle)SharedRegion_getHeap(0);
112     Module.store = Memory_alloc(srHeap, Module.poolSize, align, NULL);
114     /* create a heap in shared memory for message pool */
115     HeapBuf_Params_init(&heapParams);
116     heapParams.blockSize = Module.msgSize;
117     heapParams.numBlocks = NUM_MSGS;
118     heapParams.bufSize = Module.poolSize;
119     heapParams.align = align;
120     heapParams.buf = Module.store;
121     Error_init(&eb);
123     Module.heap = HeapBuf_create(&heapParams, &eb);
125     if (Module.heap == NULL) {
126         Log_error0("App_create: failed creating message pool");
127         status = -1;
128         goto leave;
129     }
131     /* bind message pool to heapId */
132     MessageQ_registerHeap((Ptr)(Module.heap), App_MsgHeapId);
134     /* create local message queue (inbound messages) */
135     MessageQ_Params_init(&msgqParams);
137     Module.hostQue = MessageQ_create(NULL, &msgqParams);
139     if (Module.hostQue == NULL) {
140         Log_error0("App_create: failed creating MessageQ");
141         status = -1;
142         goto leave;
143     }
145     /* open the remote message queue */
146     System_sprintf(msgqName, App_SlaveMsgQueName,
147             MultiProc_getName(remoteProcId));
149     do {
150         status = MessageQ_open(msgqName, &Module.slaveQue);
151         Task_sleep(1);
152     } while (status == MessageQ_E_NOTFOUND);
154     if (status < 0) {
155         Log_error0("App_create: failed opening MessageQ");
156         goto leave;
157     }
159     Log_print0(Diags_INFO, "App_create: Host is ready");
161 leave:
162     Log_print1(Diags_INFO, "App_create: <-- status=%d", (IArg)status);
163     return(status);
167 /*
168  *  ======== App_delete ========
169  */
170 Int App_delete(Void)
172     Int             status;
173     IHeap_Handle    srHeap;
175     Log_print0(Diags_INFO, "App_delete: -->");
177     /* close remote resources */
178     status = MessageQ_close(&Module.slaveQue);
180     if (status < 0) {
181         goto leave;
182     }
184     /* delete the host message queue */
185     status = MessageQ_delete(&Module.hostQue);
187     if (status < 0) {
188         goto leave;
189     }
191     /* unregister message pool heap */
192     MessageQ_unregisterHeap(App_MsgHeapId);
194     /* delete the message pool heap */
195     HeapBuf_delete(&Module.heap);
197     /* release message pool memory */
198     srHeap = (IHeap_Handle)SharedRegion_getHeap(0);
199     Memory_free(srHeap, Module.store, Module.poolSize);
201 leave:
202     Log_print1(Diags_INFO, "App_delete: <-- status=%d", (IArg)status);
203     return(status);
207 /*
208  *  ======== App_exec ========
209  */
210 Int App_exec(Void)
212     Int         status;
213     App_Msg *   msg;
214     Uint32 *bigDataPtr;
215     SharedRegion_SRPtr bigDataSharedPtr;
216     Int16 i,j;
217     UInt16  regionId1;
218     Memory_Stats stats;
219     HeapMemMP_ExtendedStats extStats;
220     SharedRegion_Entry *pSrEntry;
221     HeapMemMP_Params heapMemMp_params;
222     HeapMemMP_Handle sr1Heap;
223     Uint16 regionId;
224     HeapMemMP_Handle srHeap;
225     UInt32 errorCount=0;
226     
227     Log_print0(Diags_INFO, "App_exec: -->");
229     // obtain information about heap (if any) in SR_1
230     regionId1 = SharedRegion_getIdByName("SR_1");
231     Log_print1(Diags_INFO, "App_taskFxn: SR_1 region Id=%d",regionId1);
232     sr1Heap = SharedRegion_getHeap(regionId1);
233     if (sr1Heap != NULL)
234     {
235         /* SR has predefined heap */
236         HeapMemMP_getStats((HeapMemMP_Handle)sr1Heap, &stats);
237         Log_print3(Diags_INFO, "App_taskFxn: SR_1 heap, totalSize=%d,totalFreeSize=%d,largestFreeSize=%d", (IArg)stats.totalSize, (IArg)stats.totalFreeSize, (IArg)stats.largestFreeSize);
238         HeapMemMP_getExtendedStats((HeapMemMP_Handle)sr1Heap, &extStats);
239         Log_print2(Diags_INFO, "App_taskFxn: SR_1 heap, buf=0x%x,size=%d", (IArg)extStats.buf, (IArg)extStats.size);
240         Log_error0("App_taskFxn: Error: Example assumes shared region without preconfigured heap");
241         status = -1;
242         goto leave;
243     }
244     else
245     {
246         Log_print0(Diags_INFO, "App_taskFxn: SR_1, sr1Heap=NULL");
247         
248         pSrEntry = SharedRegion_getEntryPtr(regionId1);
249         Log_print1(Diags_INFO, "App_taskFxn: SR_1, len=%d", pSrEntry->len);
251         // Create HeapMP at run-time
252         HeapMemMP_Params_init(&heapMemMp_params);
253         heapMemMp_params.name = "sr1HeapMemMp";
254         heapMemMp_params.sharedAddr = pSrEntry->base;
255         heapMemMp_params.sharedBufSize = ROUNDUP(pSrEntry->len, pSrEntry->cacheLineSize); 
256         heapMemMp_params.gate = NULL;
257         sr1Heap = HeapMemMP_create(&heapMemMp_params);
258         if (!sr1Heap) {
259             Log_error0("srHeap creation failed");
260             status = -1;
261             goto leave;
262         }
263         HeapMemMP_getStats((HeapMemMP_Handle)sr1Heap, &stats);
264         Log_print3(Diags_INFO, "App_taskFxn: SR_1 heap, totalSize=%d,totalFreeSize=%d,largestFreeSize=%d", (IArg)stats.totalSize, (IArg)stats.totalFreeSize, (IArg)stats.largestFreeSize);
265         HeapMemMP_getExtendedStats((HeapMemMP_Handle)sr1Heap, &extStats);
266         Log_print2(Diags_INFO, "App_taskFxn: SR_1 heap, buf=0x%x,size=%d", (IArg)extStats.buf, (IArg)extStats.size);
267     }
269     srHeap = sr1Heap;
270     regionId = regionId1;
272     /* fill process pipeline */
273     for (i = 1; i <= 3; i++) {
274         Log_print1(Diags_INFO, "App_exec: sending message %d", (IArg)i);
276         /* allocate message */
277         msg = (App_Msg *)MessageQ_alloc(Module.heapId, Module.msgSize);
279         if (msg == NULL) {
280             status = -1;
281             goto leave;
282         }
284         /* set the return address in the message header */
285         MessageQ_setReplyQueue(Module.hostQue, (MessageQ_Msg)msg);
287         if ( i == 1) {
288             /* fill in message payload */
289             msg->cmd = App_CMD_SHARED_REGION_INIT;
290             msg->id = i;
291             msg->regionId = regionId;
292             /* Passing the local shared memory address to the remote */
293             /* Actually this can be any allocated buffer for the used for the heap */
294             msg->u.sharedRegionInitCfg.base = (intptr_t)(pSrEntry->base);
295             msg->u.sharedRegionInitCfg.size = (UInt64)(pSrEntry->len);
296         } else {
297             /* fill in message payload */
298             msg->cmd = App_CMD_NOP;
299             msg->id = i;
300         }
302         /* send message */
303         MessageQ_put(Module.slaveQue, (MessageQ_Msg)msg);
304     }
306     /* process steady state (keep pipeline full) */
307     for (i = 4; i <= 18; i++) {
309         /* wait for return message */
310         status = MessageQ_get(Module.hostQue, (MessageQ_Msg *)&msg,
311             MessageQ_FOREVER);
313         if (status < 0) {
314             goto leave;
315         }
317         /* extract message payload */
319         if ((msg->cmd == App_CMD_BIGDATA) && (msg->u.bigDataBuffer.sharedPtr) ) {
321             /* Translate to local address */
322             bigDataPtr = (Uint32 *)SharedRegion_getPtr(msg->u.bigDataBuffer.sharedPtr);
324             /* If shared region is configured for cache enabled do cache operation */
325             if (SharedRegion_isCacheEnabled(msg->regionId)) {
326                 Cache_inv(bigDataPtr,
327                     msg->u.bigDataBuffer.size, Cache_Type_ALL, TRUE);
328             }
329 #ifdef DEBUG
330             /* print data from big data buffer */
331             Log_print1(Diags_INFO, " Received back buffer %d", msg->id);
332             Log_print0(Diags_INFO, " First 8 bytes: ");
333             for ( j = 0; j < 8 && j < msg->u.bigDataBuffer.size/sizeof(uint32_t); j+=4)
334                 Log_print4(Diags_INFO, "0x%x, 0x%x, 0x%x, 0x%x",
335                     bigDataPtr[j], bigDataPtr[j+1], bigDataPtr[j+2], bigDataPtr[j+3]);
336             Log_print0(Diags_INFO, " Last 8 bytes: ");
337             for ( j = (msg->u.bigDataBuffer.size/sizeof(uint32_t))-8 ;
338                  j < msg->u.bigDataBuffer.size/sizeof(uint32_t); j+=4)
339                 Log_print4(Diags_INFO, "0x%x, 0x%x, 0x%x, 0x%x",
340                     bigDataPtr[j], bigDataPtr[j+1], bigDataPtr[j+2], bigDataPtr[j+3]);
341 #endif
342             /* Check values to see expected results */
343             for( j=0; j < msg->u.bigDataBuffer.size/sizeof(uint32_t); j++) {
344                 if ( bigDataPtr[j] != (msg->id+10+j) ) {
345                     errorCount++;
346                 }
347             }
349             /* Free big data buffer */
350             HeapMemMP_free(srHeap, bigDataPtr, msg->u.bigDataBuffer.size);
351         }
353         /* free the message */
354         MessageQ_free((MessageQ_Msg)msg);
356         Log_print1(Diags_INFO, "App_exec: message received, sending message %d",
357                 (IArg)i);
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 == 18) {
372             /* Last message will tell the slave to shutdown */
373             msg->cmd = App_CMD_SHUTDOWN;
374             msg->id = i;
375         } else if (i < 15) {
376             msg->cmd = App_CMD_BIGDATA;
377             msg->id = i;
379             /* Allocate buffer from HeapMemMP */
380             bigDataPtr = (Uint32 *)(HeapMemMP_alloc(srHeap, BIGDATA_SIZE, BIGDATA_ALIGN));
382             if ( ! bigDataPtr ) {
383                 status = -1;
384                 goto leave;
385             }
387             /* Fill Big data buffer */
388             for(j=0; j< BIGDATA_SIZE/sizeof(uint32_t); j++) {
389                bigDataPtr[j] = j+i;
390             }
392             /* Cache write back data buffer */
393             if (SharedRegion_isCacheEnabled(regionId)) {
394                 Cache_wb(bigDataPtr, BIGDATA_SIZE, Cache_Type_ALL, TRUE);
395             }
397             /* Translate Address to Shared address */
398             bigDataSharedPtr = SharedRegion_getSRPtr(bigDataPtr, regionId);
400             msg->u.bigDataBuffer.sharedPtr = bigDataSharedPtr;
401             msg->u.bigDataBuffer.size = BIGDATA_SIZE;
402             msg->regionId = regionId;
403         }
404         else {
405             msg->cmd = App_CMD_NOP;
406             msg->id = i;
407         }
409         /* send message */
410         MessageQ_put(Module.slaveQue, (MessageQ_Msg)msg);
411     }
413     /* drain process pipeline */
414     for (i = 1; i <= 3; i++) {
415         Log_print0(Diags_INFO, "App_exec: message received");
417         /* wait for return message */
418         status = MessageQ_get(Module.hostQue, (MessageQ_Msg *)&msg,
419             MessageQ_FOREVER);
421         if (status < 0) {
422             goto leave;
423         }
425         /* extract message payload */
427         /* free the message */
428         MessageQ_free((MessageQ_Msg)msg);
429     }
431 leave:
432     /* Print error count if non-zero */
433     if (errorCount) {
434         Log_print1(Diags_INFO, "App_exec: Error Count %d", errorCount);
435         status = -1;
436     }
437     else
438         Log_print0(Diags_INFO, "App_exec: Data check clean");
440     Log_print1(Diags_INFO, "App_exec: <-- status=%d", (IArg)status);
441     return(status);