bbbc7fd626ceaec66e7233e8a49043fa22df061c
1 /*
2 * Copyright (c) 2012-2013, Texas Instruments Incorporated
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 * ======== TransportCirc.c ========
34 */
36 #include <string.h> /* for memcpy() */
38 #include <xdc/std.h>
39 #include <xdc/runtime/Assert.h>
40 #include <xdc/runtime/Error.h>
41 #include <xdc/runtime/Memory.h>
43 #include <ti/sysbios/hal/Hwi.h>
44 #include <ti/sysbios/knl/Swi.h>
46 #include <ti/sdo/ipc/family/f28m35x/IpcMgr.h>
48 #include "package/internal/TransportCirc.xdc.h"
50 #include <ti/sdo/utils/_MultiProc.h>
51 #include <ti/sdo/ipc/_Notify.h>
52 #include <ti/sdo/ipc/_MessageQ.h>
54 /* Need to use reserved notify events */
55 #undef TransportCirc_notifyEventId
56 #define TransportCirc_notifyEventId \
57 ti_sdo_ipc_family_f28m35x_TransportCirc_notifyEventId + \
58 (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
60 /*
61 *************************************************************************
62 * Instance functions
63 *************************************************************************
64 */
66 /*
67 * ======== TransportCirc_Instance_init ========
68 */
69 Int TransportCirc_Instance_init(TransportCirc_Object *obj,
70 UInt16 remoteProcId, const TransportCirc_Params *params,
71 Error_Block *eb)
72 {
73 Int status;
74 Bool flag;
75 Swi_Handle swiHandle;
76 Swi_Params swiParams;
77 SizeT circBufSize;
79 swiHandle = TransportCirc_Instance_State_swiObj(obj);
81 /* init the object fields */
82 obj->priority = params->priority;
83 obj->remoteProcId = remoteProcId;
85 /* construct the swi with lowest priority */
86 Swi_Params_init(&swiParams);
87 swiParams.arg0 = (UArg)obj;
88 Swi_construct(Swi_struct(swiHandle),
89 (Swi_FuncPtr)TransportCirc_swiFxn,
90 &swiParams, eb);
92 /* calculate the circular buffer size one-way */
93 circBufSize = TransportCirc_msgSize * TransportCirc_numMsgs;
95 /* Init put/get buffer and index pointers. */
96 obj->putBuffer = params->writeAddr;
98 obj->putWriteIndex = (Bits32 *)((UInt32)obj->putBuffer + circBufSize);
100 obj->getBuffer = params->readAddr;
102 obj->getWriteIndex = (Bits32 *)((UInt32)obj->getBuffer + circBufSize);
104 obj->putReadIndex = (Bits32 *)((UInt32)obj->getWriteIndex + sizeof(Bits32));
106 obj->getReadIndex = (Bits32 *)((UInt32)obj->putWriteIndex + sizeof(Bits32));
108 /* init the putWrite and getRead Index to 0 */
109 obj->putWriteIndex[0] = 0;
110 obj->getReadIndex[0] = 0;
112 /* register the event with Notify */
113 status = Notify_registerEventSingle(
114 remoteProcId, /* remoteProcId */
115 0, /* lineId */
116 TransportCirc_notifyEventId,
117 (Notify_FnNotifyCbck)TransportCirc_notifyFxn,
118 (UArg)swiHandle);
120 if (status < 0) {
121 Error_raise(eb, IpcMgr_E_internal, 0, 0);
122 return (1);
123 }
125 /* Register the transport with MessageQ */
126 flag = ti_sdo_ipc_MessageQ_registerTransport(
127 TransportCirc_Handle_upCast(obj), remoteProcId, params->priority);
129 if (flag == FALSE) {
130 Error_raise(eb, IpcMgr_E_internal, 0, 0);
131 return (2);
132 }
134 return (0);
135 }
137 /*
138 * ======== TransportCirc_Instance_finalize ========
139 */
140 Void TransportCirc_Instance_finalize(TransportCirc_Object* obj, Int status)
141 {
142 Swi_Handle swiHandle;
144 switch(status) {
145 case 0:
146 /* MessageQ_registerTransport succeeded */
147 ti_sdo_ipc_MessageQ_unregisterTransport(obj->remoteProcId,
148 obj->priority);
150 /* OK to fall thru */
152 case 1: /* Notify_registerEventSingle failed */
154 /* OK to fall thru */
156 case 2: /* MessageQ_registerTransport failed */
157 Notify_unregisterEventSingle(
158 obj->remoteProcId,
159 0,
160 TransportCirc_notifyEventId);
161 break;
162 }
164 /* Destruct the swi */
165 swiHandle = TransportCirc_Instance_State_swiObj(obj);
166 if (swiHandle != NULL) {
167 Swi_destruct(Swi_struct(swiHandle));
168 }
169 }
171 /*
172 * ======== TransportCirc_put ========
173 * Assuming MessageQ_put is making sure that the arguments are ok
174 */
175 Bool TransportCirc_put(TransportCirc_Object *obj, Ptr msg)
176 {
177 Int status;
178 UInt msgSize;
179 UInt hwiKey;
180 Ptr writeAddr;
181 UInt writeIndex, readIndex;
183 do {
184 /* disable interrupts */
185 hwiKey = Hwi_disable();
187 /* get the writeIndex and readIndex */
188 readIndex = obj->putReadIndex[0];
189 writeIndex = obj->putWriteIndex[0];
191 /* if slot available 'break' out of loop */
192 if (((writeIndex + 1) & TransportCirc_maxIndex) != readIndex) {
193 break;
194 }
196 /* restore interrupts */
197 Hwi_restore(hwiKey);
199 } while (1);
201 /* interrupts are disabled at this point */
203 /* get a free buffer and copy the message into it */
204 writeAddr = (Ptr)((UInt32)obj->putBuffer +
205 (writeIndex * TransportCirc_msgSize));
207 /* get the size of the message */
208 msgSize = MessageQ_getMsgSize(msg);
210 Assert_isTrue(msgSize <= TransportCirc_msgSize, IpcMgr_A_internal);
212 /* copy message to the write buffer */
213 memcpy(writeAddr, (Ptr)msg, msgSize);
215 /* update the writeIndex */
216 obj->putWriteIndex[0] = (writeIndex + 1) & TransportCirc_maxIndex;
218 /* restore interrupts */
219 Hwi_restore(hwiKey);
221 /* free the app's message */
222 if (((MessageQ_Msg)msg)->heapId != ti_sdo_ipc_MessageQ_STATICMSG) {
223 MessageQ_free(msg);
224 }
226 /* Notify the remote processor */
227 status = Notify_sendEvent(
228 obj->remoteProcId,
229 0,
230 TransportCirc_notifyEventId,
231 (UInt32)NULL,
232 FALSE);
234 /* check the status of the sendEvent */
235 if (status < 0) {
236 return (FALSE);
237 }
239 return (TRUE);
240 }
242 /*
243 * ======== TransportCirc_control ========
244 */
245 Bool TransportCirc_control(TransportCirc_Object *obj, UInt cmd,
246 UArg cmdArg)
247 {
248 return (FALSE);
249 }
251 /*
252 * ======== TransportCirc_getStatus ========
253 */
254 Int TransportCirc_getStatus(TransportCirc_Object *obj)
255 {
256 return (0);
257 }
259 /*
260 *************************************************************************
261 * Module functions
262 *************************************************************************
263 */
265 /*
266 * ======== TransportCirc_notifyFxn ========
267 */
268 Void TransportCirc_notifyFxn(UInt16 procId,
269 UInt16 lineId,
270 UInt32 eventId,
271 UArg arg,
272 UInt32 payload)
273 {
274 Swi_Handle swiHandle;
276 /* Swi_Handle was passed as arg in register */
277 swiHandle = (Swi_Handle)arg;
279 /* post the Swi */
280 Swi_post(swiHandle);
281 }
283 /*
284 * ======== TransportCirc_swiFxn ========
285 */
286 Void TransportCirc_swiFxn(UArg arg)
287 {
288 UInt32 queueId;
289 TransportCirc_Object *obj = (TransportCirc_Object *)arg;
290 MessageQ_Msg msg = NULL;
291 MessageQ_Msg buf = NULL;
292 SizeT msgSize;
293 UInt writeIndex, readIndex;
294 UInt offset;
296 /* Make sure the TransportCirc_Object is not NULL */
297 Assert_isTrue(obj != NULL, IpcMgr_A_internal);
299 /* get the writeIndex and readIndex */
300 writeIndex = obj->getWriteIndex[0];
301 readIndex = obj->getReadIndex[0];
303 while (writeIndex != readIndex) {
304 /* determine where the message from remote core is */
305 offset = (readIndex * TransportCirc_msgSize);
307 /* get the message */
308 msg = (MessageQ_Msg)((UInt32)obj->getBuffer + offset);
310 #ifdef xdc_target__isaCompatible_28
311 /*
312 * The message size needs to be halved because it was
313 * specified in bytes and the units on the c28 is 16-bit
314 * words.
315 */
316 msgSize = MessageQ_getMsgSize(msg) >> 1;
317 #else
318 /*
319 * The message size needs to be doubled because it was
320 * specified in 16-bit words and the units on the m3 is
321 * in bytes.
322 */
323 msgSize = MessageQ_getMsgSize(msg) << 1;
324 #endif
326 /* alloc a message from msg->heapId to copy the msg to */
327 buf = MessageQ_alloc(msg->heapId, msgSize);
329 /* Make sure buf is not NULL */
330 Assert_isTrue(buf != NULL, IpcMgr_A_internal);
332 /* copy the message to the buffer allocated, set the heap id */
333 memcpy((Ptr)buf, (Ptr)msg, msgSize);
335 /* overwrite the msgSize in the msg */
336 buf->msgSize = msgSize;
338 /* retrieve the detination queue id */
339 queueId = MessageQ_getDstQueue(msg);
341 /* put the message to the destination queue */
342 MessageQ_put(queueId, buf);
344 /* update the local readIndex. */
345 readIndex = ((readIndex + 1) & TransportCirc_maxIndex);
347 /* set the readIndex */
348 obj->getReadIndex[0] = readIndex;
349 }
350 }
352 /*
353 *************************************************************************
354 * Module functions
355 *************************************************************************
356 */
358 /*
359 * ======== TransportCirc_close ========
360 */
361 Void TransportCirc_close(TransportCirc_Handle *handle)
362 {
363 TransportCirc_delete(handle);
364 }
366 /*
367 * ======== TransportCirc_sharedMemReq ========
368 */
369 SizeT TransportCirc_sharedMemReq(const TransportCirc_Params *params)
370 {
371 SizeT memReq;
373 /* Ensure that params is non-NULL */
374 Assert_isTrue(params != NULL, IpcMgr_A_internal);
376 /*
377 * Amount of shared memory:
378 * 1 putBuffer (msgSize * numMsgs) +
379 * 1 putWriteIndex ptr +
380 * 1 putReadIndex ptr +
381 */
382 memReq = (TransportCirc_msgSize * TransportCirc_numMsgs) +
383 (2 * sizeof(Bits32));
385 return (memReq);
386 }
388 /*
389 * ======== TransportCirc_setErrFxn ========
390 */
391 Void TransportCirc_setErrFxn(TransportCirc_ErrFxn errFxn)
392 {
393 /* Ignore the errFxn */
394 }