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);
163 }
165 /*
166 * ======== App_delete ========
167 */
168 Int App_delete(Void)
169 {
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);
202 }
204 /*
205 * ======== App_exec ========
206 */
207 Int App_exec(Void)
208 {
209 Int status;
210 App_Msg * msg;
211 Uint32 *bigDataLocalPtr;
212 Int16 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");
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_SIZE, BIGDATA_ALIGN));
381 if (!bigDataLocalPtr) {
382 status = -1;
383 goto leave;
384 }
386 /* Fill Big data buffer */
387 for(j=0; j< BIGDATA_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_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);
450 }