1 //###########################################################################
2 //
3 // FILE:   F2837xD_Ipc_Driver.c
4 //
5 // TITLE:  F2837xD Inter-Processor Communication (IPC) API Driver Functions.
6 //
7 // DESCRIPTION:
8 //         28x API functions for inter-processor communications between the
9 //         two CPUs. The IPC functions require the usage of the CPU1 to CPU2
10 //         and CPU2 to CPU1 MSG RAM's to store the circular ring
11 //         buffer and indexes. Commands can be queued up in order on a single
12 //         IPC interrupt channel.  For those IPC commands which are not
13 //         interdependent, multiple IPC interrupt channels may be used.
14 //         The driver functions in this file are available only as
15 //         sample functions for application development.  Due to the generic
16 //         nature of these functions and the cycle overhead inherent to a
17 //         function call, the code is not intended to be used in cases where
18 //         maximum efficiency is required in a system.
19 // NOTE:   This source code is used by both CPUs. That is both CPU1 and CPU2
20 //         Cores use this code.
21 //         The active debug CPU will be referred to as Local CPU.
22 //         When using this source code in CPU1, the term "local"
23 //         will mean CPU1 and the term "remote" CPU will be mean CPU2.
24 //         When using this source code in CPU2, the term "local"
25 //         will mean CPU2 and the term "remote" CPU will be mean CPU1.
26 //
27 //         The abbreviations LtoR and RtoL  within the function names mean
28 //         Local to Remote and Remote to Local respectively.
29 //
30 //###########################################################################
31 // $TI Release: F2837xD Support Library v3.05.00.00 $
32 // $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
33 // $Copyright:
34 // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
35 //
36 // Redistribution and use in source and binary forms, with or without
37 // modification, are permitted provided that the following conditions
38 // are met:
39 //
40 //   Redistributions of source code must retain the above copyright
41 //   notice, this list of conditions and the following disclaimer.
42 //
43 //   Redistributions in binary form must reproduce the above copyright
44 //   notice, this list of conditions and the following disclaimer in the
45 //   documentation and/or other materials provided with the
46 //   distribution.
47 //
48 //   Neither the name of Texas Instruments Incorporated nor the names of
49 //   its contributors may be used to endorse or promote products derived
50 //   from this software without specific prior written permission.
51 //
52 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 // $
64 //###########################################################################
65 
66 //*****************************************************************************
67 //! \addtogroup ipc_driver_api
68 //! @{
69 //*****************************************************************************
70 #include "F2837xD_device.h"
71 #include "F2837xD_Ipc_drivers.h"
72 
73 #if defined(CPU1)
74 #pragma DATA_SECTION(g_asIPCCPU1toCPU2Buffers, "PUTBUFFER");
75 #pragma DATA_SECTION(g_usPutWriteIndexes, "PUTWRITEIDX");
76 #pragma DATA_SECTION(g_usGetReadIndexes, "GETREADIDX");
77 
78 #pragma DATA_SECTION(g_asIPCCPU2toCPU1Buffers, "GETBUFFER");
79 #pragma DATA_SECTION(g_usGetWriteIndexes, "GETWRITEIDX");
80 #pragma DATA_SECTION(g_usPutReadIndexes, "PUTREADIDX");
81 
82 #elif defined(CPU2)
83 
84 #pragma DATA_SECTION(g_asIPCCPU2toCPU1Buffers, "PUTBUFFER");
85 #pragma DATA_SECTION(g_usPutWriteIndexes, "PUTWRITEIDX");
86 #pragma DATA_SECTION(g_usGetReadIndexes, "GETREADIDX");
87 
88 #pragma DATA_SECTION(g_asIPCCPU1toCPU2Buffers, "GETBUFFER");
89 #pragma DATA_SECTION(g_usGetWriteIndexes, "GETWRITEIDX");
90 #pragma DATA_SECTION(g_usPutReadIndexes, "PUTREADIDX");
91 
92 #endif
93 
94 //
95 // Global Circular Buffer Definitions
96 //
97 tIpcMessage g_asIPCCPU1toCPU2Buffers[NUM_IPC_INTERRUPTS][IPC_BUFFER_SIZE];
98 tIpcMessage g_asIPCCPU2toCPU1Buffers[NUM_IPC_INTERRUPTS][IPC_BUFFER_SIZE];
99 
100 //
101 // Global Circular Buffer Index Definitions
102 //
103 uint16_t g_usPutWriteIndexes[NUM_IPC_INTERRUPTS];
104 uint16_t g_usPutReadIndexes[NUM_IPC_INTERRUPTS];
105 uint16_t g_usGetWriteIndexes[NUM_IPC_INTERRUPTS];
106 uint16_t g_usGetReadIndexes[NUM_IPC_INTERRUPTS];
107 
108 //*****************************************************************************
109 //
110 //! Initializes System IPC driver controller
111 //!
112 //! \param psController specifies the address of a \e tIpcController instance
113 //! used to store information about the "Put" and "Get" circular buffers and
114 //! their respective indexes.
115 //! \param usCPU2IpcInterrupt specifies the CPU2 IPC interrupt number used by
116 //! psController.
117 //! \param usCPU1IpcInterrupt specifies the CPU1 IPC interrupt number used by
118 //! psController.
119 //!
120 //! This function initializes the IPC driver controller with circular buffer
121 //! and index addresses for an IPC interrupt pair. The
122 //! \e usCPU2IpcInterrupt and \e usCPU1IpcInterrupt parameters can be one of
123 //! the following values:
124 //! \b IPC_INT0, \b IPC_INT1, \b IPC_INT2, \b IPC_INT3.
125 //!
126 //! \note If an interrupt is currently in use by an \e tIpcController instance,
127 //! that particular interrupt should not be tied to a second \e tIpcController
128 //! instance.
129 //!
130 //! \note For a particular usCPU2IpcInterrupt - usCPU1IpcInterrupt pair, there
131 //! must be an instance of tIpcController defined and initialized on both the
132 //! CPU1 and CPU2 systems.
133 //!
134 //! \return None.
135 //
136 //*****************************************************************************
137 void
IPCInitialize(volatile tIpcController * psController,uint16_t usCPU2IpcInterrupt,uint16_t usCPU1IpcInterrupt)138 IPCInitialize (volatile tIpcController *psController,
139                uint16_t usCPU2IpcInterrupt, uint16_t usCPU1IpcInterrupt)
140 {
141 #if defined(CPU1)
142     // CPU1toCPU2PutBuffer and Index Initialization
143     psController->psPutBuffer = &g_asIPCCPU1toCPU2Buffers[usCPU2IpcInterrupt-1][0];
144     psController->pusPutWriteIndex = &g_usPutWriteIndexes[usCPU2IpcInterrupt-1];
145     psController->pusGetReadIndex = &g_usGetReadIndexes[usCPU1IpcInterrupt-1];
146     psController->ulPutFlag = (uint32_t)(1 << (usCPU2IpcInterrupt - 1));
147 
148     // CPU1toCPU2GetBuffer and Index Initialization
149     psController->psGetBuffer = &g_asIPCCPU2toCPU1Buffers[usCPU1IpcInterrupt-1][0];
150     psController->pusGetWriteIndex = &g_usGetWriteIndexes[usCPU1IpcInterrupt-1];
151     psController->pusPutReadIndex = &g_usPutReadIndexes[usCPU2IpcInterrupt-1];
152 #elif defined(CPU2)
153     // CPU2toCPU1PutBuffer and Index Initialization
154     psController->psPutBuffer = &g_asIPCCPU2toCPU1Buffers[usCPU1IpcInterrupt-1][0];
155     psController->pusPutWriteIndex = &g_usPutWriteIndexes[usCPU1IpcInterrupt-1];
156     psController->pusGetReadIndex = &g_usGetReadIndexes[usCPU2IpcInterrupt-1];
157     psController->ulPutFlag = (uint32_t)(1 << (usCPU1IpcInterrupt - 1));
158 
159     // CPU1toCPU2GetBuffer and Index Initialization
160     psController->psGetBuffer = &g_asIPCCPU1toCPU2Buffers[usCPU2IpcInterrupt-1][0];
161     psController->pusGetWriteIndex = &g_usGetWriteIndexes[usCPU2IpcInterrupt-1];
162     psController->pusPutReadIndex = &g_usPutReadIndexes[usCPU1IpcInterrupt-1];
163 #endif
164     // Initialize PutBuffer WriteIndex = 0 and GetBuffer ReadIndex = 0
165     *(psController->pusPutWriteIndex) = 0;
166     *(psController->pusGetReadIndex) = 0;
167 }
168 
169 //*****************************************************************************
170 //
171 //! Writes a message into the PutBuffer.
172 //!
173 //! \param psController specifies the address of a \e tIpcController instance
174 //! used to store information about the "Put" and "Get" circular buffers and
175 //! their respective indexes.
176 //! \param psMessage specifies the address of the \e tIpcMessage instance to be
177 //! written to PutBuffer.
178 //! \param bBlock specifies whether to allow function to block until PutBuffer
179 //! has a free slot (1= wait until free spot available, 0 = exit with
180 //! STATUS_FAIL if no free slot).
181 //!
182 //! This function checks if there is a free slot in the PutBuffer. If so, it
183 //! puts the message pointed to by \e psMessage into the free slot and
184 //! increments the WriteIndex. Then it sets the appropriate IPC interrupt flag
185 //! specified by \e psController->usPutFlag.  The \e bBlock parameter can be
186 //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
187 //!
188 //! \return \b STATUS_FAIL if PutBuffer is full. \b STATUS_PASS if Put occurs
189 //! successfully.
190 //
191 //*****************************************************************************
192 uint16_t
IpcPut(volatile tIpcController * psController,tIpcMessage * psMessage,uint16_t bBlock)193 IpcPut (volatile tIpcController *psController, tIpcMessage *psMessage,
194         uint16_t bBlock)
195 {
196     uint16_t writeIndex;
197     uint16_t readIndex;
198     uint16_t returnStatus = STATUS_PASS;
199 
200     writeIndex = *(psController->pusPutWriteIndex);
201     readIndex = *(psController->pusPutReadIndex);
202 
203     //
204     // Wait until Put Buffer slot is free
205     //
206     while (((writeIndex + 1) & MAX_BUFFER_INDEX) == readIndex)
207     {
208         //
209         // If designated as a "Blocking" function, and Put buffer is full,
210         // return immediately with fail status.
211         //
212         if (!bBlock)
213         {
214             returnStatus = STATUS_FAIL;
215             break;
216         }
217 
218         readIndex = *(psController->pusPutReadIndex);
219     }
220 
221     if (returnStatus != STATUS_FAIL)
222     {
223         //
224         // When slot is free, Write Message to PutBuffer, update PutWriteIndex,
225         // and set the CPU IPC INT Flag
226         //
227         psController->psPutBuffer[writeIndex] = *psMessage;
228 
229         writeIndex = (writeIndex + 1) & MAX_BUFFER_INDEX;
230         *(psController->pusPutWriteIndex) = writeIndex;
231 
232         IpcRegs.IPCSET.all |= psController->ulPutFlag;
233     }
234 
235     return returnStatus;
236 }
237 
238 //*****************************************************************************
239 //
240 //! Reads a message from the GetBuffer.
241 //!
242 //! \param psController specifies the address of a \e tIpcController instance
243 //! used to store information about the "Put" and "Get" circular buffers and
244 //! their respective indexes.
245 //! \param psMessage specifies the address of the \e tIpcMessage instance where
246 //! the message from GetBuffer should be written to.
247 //! \param bBlock specifies whether to allow function to block until GetBuffer
248 //! has a message (1= wait until message available, 0 = exit with STATUS_FAIL
249 //! if no message).
250 //!
251 //! This function checks if there is a message in the GetBuffer. If so, it gets
252 //! the message in the GetBuffer pointed to by the ReadIndex and writes it to
253 //! the address pointed to by \e psMessage. The \e bBlock parameter can be one
254 //! of the following
255 //! values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
256 //!
257 //! \return \b STATUS_PASS if GetBuffer is empty. \b STATUS_FAIL if Get occurs
258 //! successfully.
259 //
260 //*****************************************************************************
261 uint16_t
IpcGet(volatile tIpcController * psController,tIpcMessage * psMessage,uint16_t bBlock)262 IpcGet (volatile tIpcController *psController, tIpcMessage *psMessage,
263         uint16_t bBlock)
264 {
265     uint16_t writeIndex;
266     uint16_t readIndex;
267     uint16_t returnStatus = STATUS_PASS;
268 
269     writeIndex = *(psController->pusGetWriteIndex);
270     readIndex = *(psController->pusGetReadIndex);
271 
272     //
273     // Loop while GetBuffer is empty
274     //
275     while (writeIndex == readIndex)
276     {
277         //
278         // If designated as a "Blocking" function, and Get buffer is empty,
279         // return immediately with fail status.
280         //
281         if (!bBlock)
282         {
283             returnStatus = STATUS_FAIL;
284             break;
285         }
286 
287         writeIndex = *(psController->pusGetWriteIndex);
288     }
289 
290     if (returnStatus != STATUS_FAIL)
291     {
292         //
293         // If there is a message in GetBuffer, Read Message and update
294         // the ReadIndex
295         //
296         *psMessage = psController->psGetBuffer[readIndex];
297 
298         readIndex = (readIndex + 1) & MAX_BUFFER_INDEX;
299         *(psController->pusGetReadIndex) = readIndex;
300     }
301 
302     return returnStatus;
303 }
304 
305 //*****************************************************************************
306 //
307 //! Sends a command to read either a 16- or 32-bit data word from the remote
308 //! CPU
309 //!
310 //! \param psController specifies the address of a \e tIpcController instance
311 //! used to store information about the "Put" and "Get" circular buffers and
312 //! their respective indexes.
313 //! \param ulAddress specifies the remote CPU address to read from
314 //! \param pvData is a pointer to the 16/32-bit variable where read data will
315 //! be stored.
316 //! \param usLength designates 16- or 32-bit read (1 = 16-bit, 2 = 32-bit)
317 //! \param bBlock specifies whether to allow function to block until PutBuffer
318 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
319 //! \param ulResponseFlag indicates the remote CPU to the local CPU Flag
320 //! number mask used to report when the read data is available at pvData.
321 //! (\e ulResponseFlag MUST use IPC flags 17-32, and not 1-16)
322 //!
323 //! This function will allow the local CPU system to send a 16/32-bit data
324 //! read command to the remote CPU system and set a ResponseFlag to track the
325 //! status of the read.
326 //! The remote CPU will respond with a DataWrite command which will place
327 //! the data in the local CPU address pointed to by \e pvData. When the local
328 //! CPU receives the DataWrite command and writes the read data into \e *pvData location,
329 //! it will clear the ResponseFlag, indicating to the rest of the system that
330 //! the data is ready. The \e usLength parameter can be one of the
331 //! following values: \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e
332 //! bBlock parameter can be one of the following values: \b ENABLE_BLOCKING or
333 //! \b DISABLE_BLOCKING.
334 //! The \e ulResponseFlag parameter can be any single one of the flags \b
335 //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
336 //!
337 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
338 //! because PutBuffer was full, command was not sent)
339 //
340 //*****************************************************************************
341 uint16_t
IPCLtoRDataRead(volatile tIpcController * psController,uint32_t ulAddress,void * pvData,uint16_t usLength,uint16_t bBlock,uint32_t ulResponseFlag)342 IPCLtoRDataRead (volatile tIpcController *psController, uint32_t ulAddress,
343                  void *pvData, uint16_t usLength, uint16_t bBlock,
344                  uint32_t ulResponseFlag)
345 {
346 
347     uint16_t status;
348     tIpcMessage sMessage;
349 
350     //
351     // Set up read command, address, dataw1 = ResponseFlag | word length,
352     // dataw2 = address where word
353     // should be written to when returned.
354     //
355     sMessage.ulcommand = IPC_DATA_READ;
356     sMessage.uladdress = ulAddress;
357     sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000)|(uint32_t)usLength;
358     sMessage.uldataw2 = (uint32_t)pvData;
359 
360     //
361     // Set ResponseFlag (cleared once data is read into address at pvData)
362     // Put Message into PutBuffer and set IPC INT flag
363     //
364     IpcRegs.IPCSET.all |= (ulResponseFlag & 0xFFFF0000);
365     status = IpcPut (psController, &sMessage, bBlock);
366 
367     return status;
368 
369     //
370     //Note: Read Response will have sMessage.ulcommand = IPC_DATA_WRITE
371     //                              sMessage.uladdress = (uint32_t) pvData
372     //                              sMessage.uldataw1  = ulStatusFlag |
373     //                                                   (uint32_t) usLength;
374     //                              sMessage.uldataw2  = word to be read into
375     //                                                   pvData address.
376     //
377 }
378 
379 //*****************************************************************************
380 //
381 //! Sends the command to read either a 16- or 32-bit data word from remote
382 //! CPU system address to a write-protected local CPU address.
383 //!
384 //! \param psController specifies the address of a \e tIpcController instance
385 //! used to store information about the "Put" and "Get" circular buffers and
386 //! their respective indexes.
387 //! \param ulAddress specifies the remote CPU address to read from
388 //! \param pvData is a pointer to the 16/32-bit variable where read data will
389 //! be stored.
390 //! \param usLength designates 16- or 32-bit read (1 = 16-bit, 2 = 32-bit)
391 //! \param bBlock specifies whether to allow function to block until PutBuffer
392 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
393 //! \param ulResponseFlag indicates the local CPU to remote CPU Flag number
394 //! mask used to report when the read data is available at pvData.
395 //! (\e ulResponseFlag MUST use IPC flags 17-32, and not 1-16)
396 //!
397 //! This function will allow the local CPU system to send a 16/32-bit data
398 //! read command to the remote CPU system and set a ResponseFlag to track the
399 //! status of the read.
400 //! The remote CPU system will respond with a DataWrite command which will
401 //! place the data in the local CPU address pointed to by \e pvData.
402 //! When the local CPU receives the DataWrite command and writes the read data
403 //! into \e *pvData location, it will clear the ResponseFlag, indicating to
404 //! the rest of the system that the data is ready. The \e usLength parameter
405 //! can be one of the following values: \b IPC_LENGTH_16_BITS or
406 //! \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be one of the following
407 //! values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
408 //! The \e ulResponseFlag parameter can be any single one of the flags \b
409 //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
410 //!
411 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
412 //! because PutBuffer was full, command was not sent)
413 //
414 //*****************************************************************************
415 uint16_t
IPCLtoRDataRead_Protected(volatile tIpcController * psController,uint32_t ulAddress,void * pvData,uint16_t usLength,uint16_t bBlock,uint32_t ulResponseFlag)416 IPCLtoRDataRead_Protected (volatile tIpcController *psController,
417                            uint32_t ulAddress, void *pvData, uint16_t usLength,
418                            uint16_t bBlock,
419                            uint32_t ulResponseFlag)
420 {
421     uint16_t status;
422     tIpcMessage sMessage;
423 
424     //
425     // Set up read command, address, dataw1 = ResponseFlag | word length, dataw2
426     // = address where word should be written to when returned.
427     //
428     sMessage.ulcommand = IPC_DATA_READ_PROTECTED;
429     sMessage.uladdress = ulAddress;
430     sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000)|(uint32_t)usLength;
431     sMessage.uldataw2 = (uint32_t)pvData;
432 
433     //
434     // Set ResponseFlag (cleared once data is read into address at pvData)
435     // Put Message into PutBuffer and set IPC INT flag
436     //
437     IpcRegs.IPCSET.all |= (ulResponseFlag & 0xFFFF0000);
438     status = IpcPut (psController, &sMessage, bBlock);
439 
440     return status;
441     //
442     // Note: Read Response will have sMessage.ulcommand = IPC_DATA_WRITE
443     //                               sMessage.uladdress = (uint32_t) pvData
444     //                               sMessage.uldataw1  = ulStatusFlag |
445     //                                                    (uint32_t) usLength;
446     //                               sMessage.uldataw2  = word to be read into
447     //                                                    pvData address.
448     //
449 }
450 
451 //*****************************************************************************
452 //
453 //! Sets the designated bits in a 16-bit data word at the remote CPU system
454 //! address
455 //!
456 //! \param psController specifies the address of a \e tIpcController instance
457 //! used to store information about the "Put" and "Get" circular buffers and
458 //! their respective indexes.
459 //! \param ulAddress specifies the remote CPU address to write to
460 //! \param ulMask specifies the 16/32-bit mask for bits which should be set at
461 //! \e ulAddress.
462 //! 16-bit masks should fill the lower 16-bits (upper 16-bits will be all
463 //! 0x0000).
464 //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits)
465 //! \param bBlock specifies whether to allow function to block until PutBuffer
466 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
467 //!
468 //! This function will allow the local CPU system to set bits specified by the
469 //! \e ulMask variable in a 16/32-bit word on the remote CPU system. The \e
470 //! usLength parameter can be one of the following values: \b IPC_LENGTH_16_BITS
471 //! or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be one of the
472 //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
473 //!
474 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
475 //! because PutBuffer was full, command was not sent)
476 //
477 //*****************************************************************************
478 uint16_t
IPCLtoRSetBits(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulMask,uint16_t usLength,uint16_t bBlock)479 IPCLtoRSetBits(volatile tIpcController *psController, uint32_t ulAddress,
480                uint32_t ulMask, uint16_t usLength,
481                uint16_t bBlock)
482 {
483     uint16_t status;
484     tIpcMessage sMessage;
485 
486     //
487     // Set up set bits command, address, dataw1 = word length, dataw2 =
488     // 16/32-bit mask
489     //
490     sMessage.ulcommand = IPC_SET_BITS;
491     sMessage.uladdress = ulAddress;
492     sMessage.uldataw1 = (uint32_t)usLength;
493     sMessage.uldataw2 = ulMask;
494 
495     //
496     // Put Message into PutBuffer and set IPC INT flag
497     //
498     status = IpcPut (psController, &sMessage, bBlock);
499     return status;
500 }
501 //*****************************************************************************
502 //
503 //! Sets the designated bits in a 16-bit write-protected data word at the
504 //! remote CPU system address
505 //!
506 //! \param psController specifies the address of a \e tIpcController instance
507 //! used to store information about the "Put" and "Get" circular buffers and
508 //! their respective indexes.
509 //! \param ulAddress specifies the remote CPU address to write to
510 //! \param ulMask specifies the 16/32-bit mask for bits which should be set at
511 //! \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits
512 //! will be all 0x0000).
513 //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits)
514 //! \param bBlock specifies whether to allow function to block until PutBuffer
515 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
516 //!
517 //! This function will allow the local CPU system to set bits specified by the
518 //! \e ulMask variable in a write-protected 16/32-bit word on the remote CPU
519 //! system. The \e usLength parameter can be one of the  following values: \b
520 //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be
521 //! one of the following values:
522 //! \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
523 //!
524 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
525 //! because PutBuffer was full, command was not sent)
526 //
527 //*****************************************************************************
528 uint16_t
IPCLtoRSetBits_Protected(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulMask,uint16_t usLength,uint16_t bBlock)529 IPCLtoRSetBits_Protected(volatile tIpcController *psController,
530                          uint32_t ulAddress, uint32_t ulMask, uint16_t usLength,
531                          uint16_t bBlock)
532 {
533     uint16_t status;
534     tIpcMessage sMessage;
535 
536     //
537     // Set up set bits command, address, dataw1 = word length, dataw2 =
538     // 16/32-bit mask
539     //
540     sMessage.ulcommand = IPC_SET_BITS_PROTECTED;
541     sMessage.uladdress = ulAddress;
542     sMessage.uldataw1 = (uint32_t)usLength;
543     sMessage.uldataw2 = ulMask;
544 
545     //
546     // Put Message into PutBuffer and set IPC INT flag
547     //
548     status = IpcPut (psController, &sMessage, bBlock);
549     return status;
550 }
551 
552 //*****************************************************************************
553 //
554 //! Clears the designated bits in a 16-bit data word at the remote CPU system
555 //! address
556 //!
557 //! \param psController specifies the address of a \e tIpcController instance
558 //! used to store information about the "Put" and "Get" circular buffers and
559 //! their respective indexes.
560 //! \param ulAddress specifies the remote CPU address to write to
561 //! \param ulMask specifies the 16/32-bit mask for bits which should be cleared
562 //! at \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits
563 //! will be all 0x0000).
564 //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits)
565 //! \param bBlock specifies whether to allow function to block until PutBuffer
566 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
567 //!
568 //! This function will allow the local CPU system to clear bits specified by
569 //! the \e ulMask variable in a 16/32-bit word on the remote CPU system. The \e
570 //! usLength parameter can be one of the following values: \b
571 //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be
572 //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
573 //!
574 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
575 //! because PutBuffer was full, command was not sent)
576 //
577 //*****************************************************************************
578 uint16_t
IPCLtoRClearBits(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulMask,uint16_t usLength,uint16_t bBlock)579 IPCLtoRClearBits(volatile tIpcController *psController, uint32_t ulAddress,
580                  uint32_t ulMask, uint16_t usLength,
581                  uint16_t bBlock)
582 {
583     uint16_t status;
584     tIpcMessage sMessage;
585 
586     //
587     // Set up clear bits command, address, dataw1 = word length, dataw2 =
588     // 16/32-bit mask
589     //
590     sMessage.ulcommand = IPC_CLEAR_BITS;
591     sMessage.uladdress = ulAddress;
592     sMessage.uldataw1 = (uint32_t)usLength;
593     sMessage.uldataw2 = ulMask;
594 
595     //
596     // Put Message into PutBuffer and set IPC INT flag
597     //
598     status = IpcPut (psController, &sMessage, bBlock);
599     return status;
600 }
601 
602 //*****************************************************************************
603 //
604 //! Clears the designated bits in a 16-bit write-protected data word at
605 //! remote CPU system address
606 //!
607 //! \param psController specifies the address of a \e tIpcController instance
608 //! used to store information about the "Put" and "Get" circular buffers and
609 //! their respective indexes.
610 //! \param ulAddress specifies the secondary CPU address to write to
611 //! \param ulMask specifies the 16/32-bit mask for bits which should be cleared
612 //! at \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits
613 //! will be all 0x0000).
614 //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits)
615 //! \param bBlock specifies whether to allow function to block until PutBuffer
616 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
617 //!
618 //! This function will allow the local CPU system to set bits specified by the
619 //! \e ulMask variable in a write-protected 16/32-bit word on the remote CPU
620 //! system. The \e usLength parameter can be  one of the following values: \b
621 //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be
622 //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
623 //!
624 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
625 //! because PutBuffer was full, command was not sent)
626 //
627 //*****************************************************************************
628 uint16_t
IPCLtoRClearBits_Protected(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulMask,uint16_t usLength,uint16_t bBlock)629 IPCLtoRClearBits_Protected(volatile tIpcController *psController,
630                            uint32_t ulAddress, uint32_t ulMask,
631                            uint16_t usLength, uint16_t bBlock)
632 {
633     uint16_t status;
634     tIpcMessage sMessage;
635 
636     //
637     // Set up clear bits command, address, dataw1 = word length, dataw2 =
638     // 16/32-bit mask
639     //
640     sMessage.ulcommand = IPC_CLEAR_BITS_PROTECTED;
641     sMessage.uladdress = ulAddress;
642     sMessage.uldataw1 = (uint32_t)usLength;
643     sMessage.uldataw2 = ulMask;
644 
645     //
646     // Put Message into PutBuffer and set IPC INT flag
647     //
648     status = IpcPut (psController, &sMessage, bBlock);
649     return status;
650 }
651 
652 //*****************************************************************************
653 //
654 //! Writes a 16/32-bit data word to the remote CPU system address
655 //!
656 //! \param psController specifies the address of a \e tIpcController instance
657 //! used to store information about the "Put" and "Get" circular buffers and
658 //! their respective indexes.
659 //! \param ulAddress specifies the remote cpu address to write to
660 //! \param ulData specifies the 16/32-bit word which will be written.
661 //! For 16-bit words, only the lower 16-bits of ulData will be considered by
662 //! the master system.
663 //! \param usLength is the length of the word to write (1 = 16-bits, 2 =
664 //! 32-bits)
665 //! \param bBlock specifies whether to allow function to block until PutBuffer
666 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
667 //! \param ulResponseFlag is used to pass the \e ulResponseFlag back to the
668 //! remote cpu only when this function is called in response to \e
669 //! IPCMtoCDataRead(). Otherwise, set to 0.
670 //!
671 //! This function will allow the local CPU system to write a 16/32-bit word
672 //! via the \e ulData variable to an address on the remote CPU system.
673 //! The \e usLength parameter can be one of the following values:
674 //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter
675 //! can be one of the following values: \b ENABLE_BLOCKING or \b
676 //! DISABLE_BLOCKING.
677 //! The \e ulResponseFlag parameter can be any single one of the flags \b
678 //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
679 //!
680 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
681 //! because PutBuffer was full, command was not sent)
682 //
683 //*****************************************************************************
684 uint16_t
IPCLtoRDataWrite(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulData,uint16_t usLength,uint16_t bBlock,uint32_t ulResponseFlag)685 IPCLtoRDataWrite(volatile tIpcController *psController, uint32_t ulAddress,
686                  uint32_t ulData, uint16_t usLength, uint16_t bBlock,
687                  uint32_t ulResponseFlag)
688 {
689     uint16_t status;
690     tIpcMessage sMessage;
691 
692     //
693     // Set up write command, address, dataw1 = ResponseFlag | word length,
694     // dataw2 = data to write
695     //
696     sMessage.ulcommand = IPC_DATA_WRITE;
697     sMessage.uladdress = ulAddress;
698     sMessage.uldataw1 = ulResponseFlag |(uint32_t)usLength;
699     sMessage.uldataw2 = ulData;
700 
701     //
702     // Put Message into PutBuffer and set IPC INT flag
703     //
704     status = IpcPut (psController, &sMessage, bBlock);
705     return status;
706 }
707 
708 //*****************************************************************************
709 //
710 //! Writes a 16/32-bit data word to a write-protected remote CPU system address
711 //!
712 //! \param psController specifies the address of a \e tIpcController instance
713 //! used to store information about the "Put" and "Get" circular buffers and
714 //! their respective indexes.
715 //! \param ulAddress specifies the write-protected remote CPU address to
716 //! write to
717 //! \param ulData specifies the 16/32-bit word which will be written. For
718 //! 16-bit words, only the lower 16-bits of ulData will be considered by the
719 //! master system.
720 //! \param usLength is the length of the word to write (1 = 16-bits, 2 =
721 //! 32-bits)
722 //! \param bBlock specifies whether to allow function to block until PutBuffer
723 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
724 //! \param ulResponseFlag is used to pass the \e ulResponseFlag back to the
725 //! remote CPU only when this function is called in response to \e
726 //! IPCMtoCDataRead(). Otherwise, set to 0.
727 //!
728 //! This function will allow the local CPU system to write a 16/32-bit word
729 //! via the \e ulData variable to a write-protected address on the remote CPU
730 //! system. The \e usLength parameter can be one of the following values:
731 //!  \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter
732 //! can be one of the following values: \b ENABLE_BLOCKING or \b
733 //! DISABLE_BLOCKING.
734 //! The \e ulResponseFlag parameter can be any single one of the flags \b
735 //! IPC_FLAG16 -
736 //! \b IPC_FLAG31 or \b NO_FLAG.
737 //!
738 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
739 //! because PutBuffer was full, command was not sent)
740 //
741 //*****************************************************************************
742 uint16_t
IPCLtoRDataWrite_Protected(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulData,uint16_t usLength,uint16_t bBlock,uint32_t ulResponseFlag)743 IPCLtoRDataWrite_Protected(volatile tIpcController *psController,
744                            uint32_t ulAddress, uint32_t ulData,
745                            uint16_t usLength, uint16_t bBlock,
746                            uint32_t ulResponseFlag)
747 {
748     uint16_t status;
749     tIpcMessage sMessage;
750 
751     //
752     // Set up write command, address, dataw1 = ResponseFlag | word length,
753     // dataw2 = data to write
754     //
755     sMessage.ulcommand = IPC_DATA_WRITE_PROTECTED;
756     sMessage.uladdress = ulAddress;
757     sMessage.uldataw1 = ulResponseFlag |(uint32_t)usLength;
758     sMessage.uldataw2 = ulData;
759 
760     //
761     // Put Message into PutBuffer and set IPC INT flag
762     //
763     status = IpcPut (psController, &sMessage, bBlock);
764     return status;
765 }
766 
767 //*****************************************************************************
768 //
769 //! Sends the command to read a block of data from remote CPU system address
770 //!
771 //! \param psController specifies the address of a \e tIpcController instance
772 //! used to store information about the "Put" and "Get" circular buffers and
773 //! their respective indexes.
774 //! \param ulAddress specifies the remote CPU memory block starting address
775 //! to read from.
776 //! \param ulShareAddress specifies the local CPU shared memory address the
777 //! read block will read to.
778 //! \param usLength designates the block size in 16-bit words.
779 //! \param bBlock specifies whether to allow function to block until PutBuffer
780 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
781 //! \param ulResponseFlag indicates the local CPU to remote CPU Flag number
782 //!  mask used to report when the read block data is available starting at
783 //!  /e ulShareAddress. (\e ulResponseFlag MUST use IPC flags 17-32, and not
784 //! 1-16)
785 //!
786 //! This function will allow the local CPU system to send a read block
787 //! command to the remote CPU system and set a ResponseFlag to track the status
788 //! of the read. The remote CPU system will process the read and place the data
789 //! in shared memory at the location specified in the \e ulShareAddress
790 //! parameter and then clear the ResponseFlag, indicating that the block is
791 //! ready. The \e bBlock parameter can be one of the following values: \b
792 //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. The \e ulResponseFlag parameter can
793 //! be any single one of the flags \b IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
794 //!
795 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
796 //! because PutBuffer was full, command was not sent)
797 //
798 //*****************************************************************************
799 uint16_t
IPCLtoRBlockRead(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulShareAddress,uint16_t usLength,uint16_t bBlock,uint32_t ulResponseFlag)800 IPCLtoRBlockRead(volatile tIpcController *psController, uint32_t ulAddress,
801                  uint32_t ulShareAddress, uint16_t usLength, uint16_t bBlock,
802                  uint32_t ulResponseFlag)
803 {
804     uint16_t status;
805     tIpcMessage sMessage;
806 
807     //
808     // Set up block read command, address, dataw1 = ResponseFlag | block length,
809     // dataw2 = remote CPU address in shared memory
810     // where block data should be read to
811     // (corresponding to local CPU ulShareAddress).
812     //
813     sMessage.ulcommand = IPC_BLOCK_READ;
814     sMessage.uladdress = ulAddress;
815     sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000) |(uint32_t)usLength;
816     sMessage.uldataw2 = ulShareAddress;
817 
818     //
819     // Set ResponseFlag (cleared once data is read into Share Address location)
820     // Put Message into PutBuffer and set IPC INT flag
821     //
822     IpcRegs.IPCSET.all |= (ulResponseFlag & 0xFFFF0000);
823     status = IpcPut (psController, &sMessage, bBlock);
824 
825     return status;
826     //
827     // Note: Read Block Response will occur in processing of ReadBlock (since
828     // remote CPU has access to shared memory)
829     //
830 }
831 
832 //*****************************************************************************
833 //
834 //! Writes a block of data to remote CPU system address
835 //!
836 //! \param psController specifies the address of a \e tIpcController instance
837 //! used to store information about the "Put" and "Get" circular buffers and
838 //! their respective indexes.
839 //! \param ulAddress specifies the remote CPU memory block starting address
840 //!  to write to.
841 //! \param ulShareAddress specifies the local CPU shared memory address where
842 //! data to write from resides.
843 //! \param usLength designates the block size in 16- or 32-bit words (depends
844 //! on \e usWordLength).
845 //! \param usWordLength designates the word size (16-bits = 1 or 32-bits = 2).
846 //! \param bBlock specifies whether to allow function to block until PutBuffer
847 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
848 //!
849 //! This function will allow the local CPU system to write a block of data to
850 //! the remote CPU system starting from the location specified by the
851 //! \e ulAdress parameter. Prior to calling this function, the local CPU
852 //! system code should place the data to write in shared memory starting at /e
853 //! ulShareAddress.
854 //! The \e usWordLength parameter can be one of the following values:
855 //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter
856 //! can be one of the following values: \b ENABLE_BLOCKING or \b
857 //! DISABLE_BLOCKING.
858 //! The \e ulResponseFlag parameter can be any single one of the flags \b
859 //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
860 //!
861 //! \note If the shared SARAM blocks are used to pass the RAM block between the
862 //! processors, the IPCReqMemAccess() function must be called first in order to
863 //! give the slave CPU write access to the shared memory block(s).
864 //!
865 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
866 //! because PutBuffer was full, command was not sent)
867 //
868 //*****************************************************************************
869 uint16_t
IPCLtoRBlockWrite(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulShareAddress,uint16_t usLength,uint16_t usWordLength,uint16_t bBlock)870 IPCLtoRBlockWrite(volatile tIpcController *psController, uint32_t ulAddress,
871                   uint32_t ulShareAddress, uint16_t usLength,
872                   uint16_t usWordLength, uint16_t bBlock)
873 {
874     uint16_t status;
875     tIpcMessage sMessage;
876 
877     //
878     // Set up block write command, address, dataw1 = block length,
879     // dataw2 = remote CPU shared mem address
880     // where write data resides
881     //
882     sMessage.ulcommand = IPC_BLOCK_WRITE;
883     sMessage.uladdress = ulAddress;
884     sMessage.uldataw1 = ((uint32_t)(usWordLength)<<16) + (uint32_t)usLength;
885     sMessage.uldataw2 = ulShareAddress;
886 
887     //
888     // Put Message into PutBuffer and set IPC INT flag
889     //
890     status = IpcPut (psController, &sMessage, bBlock);
891     return status;
892 }
893 
894 //*****************************************************************************
895 //
896 //! Writes a block of data to a write-protected remote CPU system address
897 //!
898 //! \param psController specifies the address of a \e tIpcController instance
899 //! used to store information about the "Put" and "Get" circular buffers and
900 //! their respective indexes.
901 //! \param ulAddress specifies the write-protected remote CPU block starting
902 //! address to write to.
903 //! \param ulShareAddress specifies the local CPU shared memory address where
904 //!  data to write from resides.
905 //! \param usLength designates the block size in 16- or 32-bit words (depends
906 //! on \e usWordLength).
907 //! \param usWordLength designates the word size (16-bits = 1 or 32-bits = 2).
908 //! \param bBlock specifies whether to allow function to block until PutBuffer
909 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
910 //!
911 //! This function will allow the local CPU system to write a block of data to
912 //! a write-protected region on the remote CPU system starting from the
913 //! location specified by the \e ulAdress parameter. Prior to calling this
914 //! function, the local CPU system code should place the data to write in
915 //! shared memory starting at /e ulShareAddress.
916 //! The \e usWordLength parameter can be one of the following values:
917 //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter
918 //! can be one of the following values: \b ENABLE_BLOCKING or \b
919 //! DISABLE_BLOCKING.
920 //! The \e ulResponseFlag parameter can be any single one of the flags \b
921 //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG.
922 //!
923 //! \note If the shared SARAM blocks are used to pass the RAM block between the
924 //! processors, the IPCReqMemAccess() function must be called first in order to
925 //! give the the slave CPU write access to the shared memory block(s).
926 //!
927 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
928 //! because PutBuffer was full, command was not sent)
929 //
930 //*****************************************************************************
931 uint16_t
IPCLtoRBlockWrite_Protected(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulShareAddress,uint16_t usLength,uint16_t usWordLength,uint16_t bBlock)932 IPCLtoRBlockWrite_Protected(volatile tIpcController *psController,
933                             uint32_t ulAddress, uint32_t ulShareAddress,
934                             uint16_t usLength, uint16_t usWordLength,
935                             uint16_t bBlock)
936 {
937     uint16_t status;
938     tIpcMessage sMessage;
939 
940     //
941     // Set up block write command, address, dataw1 = block length,
942     // dataw2 = remote CPU shared mem address
943     // where write data resides
944     //
945     sMessage.ulcommand = IPC_BLOCK_WRITE_PROTECTED;
946     sMessage.uladdress = ulAddress;
947     sMessage.uldataw1 = ((uint32_t)(usWordLength)<<16) + (uint32_t)usLength;
948     sMessage.uldataw2 = ulShareAddress;
949 
950     //
951     // Put Message into PutBuffer and set IPC INT flag
952     //
953     status = IpcPut (psController, &sMessage, bBlock);
954     return status;
955 }
956 
957 //*****************************************************************************
958 //
959 //! Calls remote CPU function with 1 optional parameter .
960 //!
961 //! \param psController specifies the address of a \e tIpcController instance
962 //! used to store information about the "Put" and "Get" circular buffers and
963 //! their respective indexes.
964 //! \param ulAddress specifies the remote CPU function address
965 //! \param ulParam specifies the 32-bit optional parameter value. If not used,
966 //! this can be a dummy value.
967 //! \param bBlock specifies whether to allow function to block until PutBuffer
968 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
969 //!
970 //! This function will allow the local CPU system to call a function on the
971 //! remote CPU. The \e ulParam variable is a single optional 32-bit parameter
972 //! to pass to the function. The \e bBlock parameter can be one of the
973 //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
974 //!
975 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
976 //! because PutBuffer was full, command was not sent)
977 //
978 //*****************************************************************************
979 uint16_t
IPCLtoRFunctionCall(volatile tIpcController * psController,uint32_t ulAddress,uint32_t ulParam,uint16_t bBlock)980 IPCLtoRFunctionCall(volatile tIpcController *psController, uint32_t ulAddress,
981                     uint32_t ulParam,
982                     uint16_t bBlock)
983 {
984     uint16_t status;
985     tIpcMessage sMessage;
986 
987     //
988     // Set up function call command, address, dataw1 = 32-bit parameter
989     //
990     sMessage.ulcommand = IPC_FUNC_CALL;
991     sMessage.uladdress = ulAddress;
992     sMessage.uldataw1 = ulParam;
993 
994     //
995     // Put Message into PutBuffer and set IPC INT flag
996     //
997     status = IpcPut (psController, &sMessage, bBlock);
998     return status;
999 }
1000 
1001 //*****************************************************************************
1002 //
1003 //! Sends generic message to remote CPU system
1004 //!
1005 //! \param psController specifies the address of a \e tIpcController instance
1006 //! used to store information about the "Put" and "Get" circular buffers and
1007 //! their respective indexes.
1008 //! \param ulCommand specifies 32-bit command word to insert into message.
1009 //! \param ulAddress specifies 32-bit address word to insert into message.
1010 //! \param ulDataW1 specifies 1st 32-bit data word to insert into message.
1011 //! \param ulDataW2 specifies 2nd 32-bit data word to insert into message.
1012 //! \param bBlock specifies whether to allow function to block until PutBuffer
1013 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
1014 //!
1015 //! This function will allow the local CPU system to send a generic message to
1016 //! the remote CPU system. Note that the user should create a corresponding
1017 //! function on the remote CPU side to interpret/use the message or fill
1018 //! parameters in such a way that the existing IPC drivers can recognize the
1019 //! command and properly process the message.
1020 //! The \e bBlock parameter can be one of the following values: \b
1021 //! ENABLE_BLOCKING or \b DISABLE_BLOCKING.
1022 //!
1023 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
1024 //! because PutBuffer was full, command was not sent)
1025 //
1026 //*****************************************************************************
1027 uint16_t
IPCLtoRSendMessage(volatile tIpcController * psController,uint32_t ulCommand,uint32_t ulAddress,uint32_t ulDataW1,uint32_t ulDataW2,uint16_t bBlock)1028 IPCLtoRSendMessage(volatile tIpcController *psController, uint32_t ulCommand,
1029                    uint32_t ulAddress, uint32_t ulDataW1, uint32_t ulDataW2,
1030                    uint16_t bBlock)
1031 {
1032     uint16_t status;
1033     tIpcMessage sMessage;
1034 
1035     //
1036     // Package message to send
1037     //
1038     sMessage.ulcommand = ulCommand;
1039     sMessage.uladdress = ulAddress;
1040     sMessage.uldataw1 = ulDataW1;
1041     sMessage.uldataw2 = ulDataW2;
1042 
1043     //
1044     // Put Message into PutBuffer and set IPC INT flag
1045     //
1046     status = IpcPut (psController, &sMessage, bBlock);
1047     return status;
1048 }
1049 
1050 #if defined (CPU2)
1051 //*****************************************************************************
1052 //
1053 //! Slave CPU Configures master R/W/Exe Access to Shared SARAM.
1054 //!
1055 //! \param psController specifies the address of a \e tIpcController instance
1056 //! used to store information about the "Put" and "Get" circular buffers and
1057 //! their respective indexes.
1058 //! \param ulMask specifies the 32-bit mask for the GSxMSEL RAM control
1059 //! register to indicate which GSx SARAM blocks the slave CPU is requesting
1060 //! master access to.
1061 //! \param usMaster specifies whether the CPU1 or CPU2 are given
1062 //!  master access to the GSx blocks.
1063 //! \param bBlock specifies whether to allow function to block until PutBuffer
1064 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
1065 //!
1066 //! This function will allow the slave CPU system to configure master R/W/Exe
1067 //! access to the GSx SARAM blocks specified by the /e ulMask parameter.  The
1068 //! function calls the \e IPCSetBits_Protected() or \e
1069 //! IPCClearBits_Protected() functions, and therefore in the master CPU
1070 //! application code, the corresponding functions should be called.
1071 //! The \e bBlock parameter can be one of the following values: \b
1072 //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. The \e usMaster parameter can be
1073 //! either: \b IPC_GSX_CPU2_MASTER or \b IPC_GSX_CPU1_MASTER. The \e ulMask
1074 //! parameter can be any of the options: \b S0_ACCESS - \b S7_ACCESS.
1075 //!
1076 //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error
1077 //! because PutBuffer was full, command was not sent)
1078 //
1079 //*****************************************************************************
1080 uint16_t
IPCReqMemAccess(volatile tIpcController * psController,uint32_t ulMask,uint16_t usMaster,uint16_t bBlock)1081 IPCReqMemAccess (volatile tIpcController *psController, uint32_t ulMask,
1082                      uint16_t usMaster, uint16_t bBlock)
1083 {
1084     uint16_t status = STATUS_PASS;
1085     uint32_t GSxMSEL_REGaddress = (uint32_t)(&MemCfgRegs.GSxMSEL.all);
1086 
1087     if (usMaster == IPC_GSX_CPU2_MASTER)
1088     {
1089         if ((MemCfgRegs.GSxMSEL.all & ulMask) != ulMask)
1090         {
1091             status =
1092                 IPCLtoRSetBits_Protected (psController, GSxMSEL_REGaddress,
1093                                           ulMask, IPC_LENGTH_32_BITS,
1094                                           bBlock);
1095         }
1096     }
1097     else if (usMaster == IPC_GSX_CPU1_MASTER)
1098     {
1099         if ((MemCfgRegs.GSxMSEL.all & ulMask) != 0)
1100         {
1101             status =
1102                 IPCLtoRClearBits_Protected (psController, GSxMSEL_REGaddress,
1103                                             ulMask, IPC_LENGTH_32_BITS,
1104                                             bBlock);
1105         }
1106     }
1107 
1108     return status;
1109 }
1110 #endif
1111 
1112 //*****************************************************************************
1113 //
1114 //! Responds to 16/32-bit data word write command the remote CPU system
1115 //!
1116 //! \param psMessage specifies the pointer to the message received from remote
1117 //! CPU system which includes the 16/32-bit data word to write to the local CPU
1118 //! address.
1119 //!
1120 //! This function will allow the local CPU system to write a 16/32-bit word
1121 //! received from the remote CPU system to the address indicated in \e
1122 //! *psMessage. In the event that the IPC_DATA_WRITE command was received as a
1123 //! result of an IPC_DATA_READ command, this function will also clear the IPC
1124 //! response flag tracking the read so other threads in the local CPU system
1125 //! will be aware that the data is ready.
1126 //!
1127 //! \return None.
1128 //
1129 //*****************************************************************************
1130 void
IPCRtoLDataWrite(tIpcMessage * psMessage)1131 IPCRtoLDataWrite(tIpcMessage *psMessage)
1132 {
1133     //
1134     // Data word length = dataw1 (15:0), responseFlag = valid only for IPC
1135     // flags 17-32
1136     //
1137     uint16_t length = (uint16_t) psMessage->uldataw1;
1138     uint32_t responseFlag = (psMessage->uldataw1) & 0xFFFF0000;
1139 
1140     //
1141     // Write 16/32-bit word to address
1142     //
1143     if (length == IPC_LENGTH_16_BITS)
1144     {
1145         *(uint16_t *)(psMessage->uladdress) = (uint16_t)psMessage->uldataw2;
1146     }
1147     else if (length == IPC_LENGTH_32_BITS)
1148     {
1149         *(uint32_t *)(psMessage->uladdress) = psMessage->uldataw2;
1150     }
1151 
1152     //
1153     // If data write command is in response to a data read command from remote
1154     // CPU to local CPU clear ResponseFlag, indicating read data from remote
1155     // CPU is ready.
1156     //
1157     IpcRegs.IPCCLR.all |= responseFlag;
1158 }
1159 
1160 //*****************************************************************************
1161 //
1162 //! Responds to 16/32-bit write-protected data word write command from
1163 //! secondary CPU system
1164 //!
1165 //! \param psMessage specifies the pointer to the message received from the
1166 //! secondary CPU system which includes the 16/32-bit data word to write to the
1167 //! local CPU address.
1168 //!
1169 //! This function will allow the local CPU system to write a 16/32-bit word
1170 //! received from the secondary CPU system to the write-protected address
1171 //! indicated in \e *psMessage.
1172 //! In the event that the IPC_DATA_WRITE_PROTECTED command was received as a
1173 //! result of an IPC_DATA_READ_PROTECTED command, this function will also clear
1174 //! the IPC response flag tracking the read so other threads in the local CPU
1175 //! will be aware that the data is ready.
1176 //!
1177 //! \return None.
1178 //
1179 //*****************************************************************************
1180 void
IPCRtoLDataWrite_Protected(tIpcMessage * psMessage)1181 IPCRtoLDataWrite_Protected(tIpcMessage *psMessage)
1182 {
1183     //
1184     // Data word length = dataw1 (15:0), responseFlag = valid only for IPC
1185     // flags 17-32
1186     //
1187     uint16_t length = (uint16_t) psMessage->uldataw1;
1188     uint32_t responseFlag = (psMessage->uldataw1) & 0xFFFF0000;
1189 
1190     //
1191     // Allow access to EALLOW-protected registers.
1192     //
1193     EALLOW;
1194 
1195     //
1196     // Write 16/32-bit word to EALLOW-protected address
1197     //
1198     if (length == IPC_LENGTH_16_BITS)
1199     {
1200         *(uint16_t *)(psMessage->uladdress) = (uint16_t)psMessage->uldataw2;
1201     }
1202     else if (length == IPC_LENGTH_32_BITS)
1203     {
1204         *(uint32_t *)(psMessage->uladdress) = psMessage->uldataw2;
1205     }
1206 
1207     //
1208     // Disable access to EALLOW-protected registers.
1209     //
1210     EDIS;
1211 
1212     //
1213     // If data write command is in response to a data read command from local
1214     // CPU to remote CPU, clear ResponseFlag, indicating read data from
1215     // secondary CPU is ready
1216     //
1217     IpcRegs.IPCCLR.all |= responseFlag;
1218 }
1219 
1220 //*****************************************************************************
1221 //
1222 //! Responds to 16/32-bit data word read command from remote CPU system.
1223 //!
1224 //! \param psController specifies the address of a \e tIpcController instance
1225 //! used to store information about the "Put" and "Get" circular buffers and
1226 //! their respective indexes.
1227 //! \param psMessage specifies the pointer to the message received from the
1228 //! remote CPU system.
1229 //! \param bBlock specifies whether to allow function to block until PutBuffer
1230 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
1231 //!
1232 //! This function will allow the remote CPU system to read a 16/32-bit data
1233 //! word at the local CPU address specified in /e psMessage, and send a Write
1234 //! command with the read data back to the local CPU system. It will also send
1235 //! the Response Flag used to track the read back to the remote CPU.
1236 //! The \e bBlock parameter can be one of the following values: \b
1237 //! ENABLE_BLOCKING or \b DISABLE_BLOCKING.
1238 //!
1239 //! \return None.
1240 //
1241 //*****************************************************************************
1242 void
IPCRtoLDataRead(volatile tIpcController * psController,tIpcMessage * psMessage,uint16_t bBlock)1243 IPCRtoLDataRead(volatile tIpcController *psController, tIpcMessage *psMessage,
1244                 uint16_t bBlock)
1245 {
1246     unsigned long ulReaddata;
1247     uint16_t usLength;
1248 
1249     //
1250     // If data word length = 16-bits, read the 16-bit value at the given
1251     // address and cast as 32-bit word to send back to remote CPU.
1252     // If data word length = 32-bits, read the 32-bit value at the given
1253     // address.
1254     //
1255     usLength = (uint16_t)psMessage->uldataw1;
1256 
1257     if (usLength == IPC_LENGTH_16_BITS)
1258     {
1259         ulReaddata = (unsigned long)(*(volatile uint16_t *)psMessage->uladdress);
1260     }
1261     else if (usLength == IPC_LENGTH_32_BITS)
1262     {
1263         ulReaddata = *(unsigned long *)psMessage->uladdress;
1264     }
1265 
1266     //
1267     // Send a Write command to write the requested data to the remote CPU read
1268     // into address.
1269     // psMessage->uldataw2 contains remote CPU address where readdata will be
1270     // written.
1271     // psMessage->uldataw1 contains the read response flag in IPC flag 17-32.
1272     //
1273     IPCLtoRDataWrite(psController, psMessage->uldataw2, ulReaddata, usLength,
1274                      bBlock,(psMessage->uldataw1 & 0xFFFF0000));
1275 }
1276 
1277 //*****************************************************************************
1278 //
1279 //! Responds to 16/32-bit data word read command from remote CPU system.
1280 //! to read into a write-protected word on the remote CPU system.
1281 //!
1282 //! \param psController specifies the address of a \e tIpcController instance
1283 //! used to store information about the "Put" and "Get" circular buffers and
1284 //! their respective indexes.
1285 //! \param psMessage specifies the pointer to the message received from the
1286 //! remote CPU system.
1287 //! \param bBlock specifies whether to allow function to block until PutBuffer
1288 //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot).
1289 //!
1290 //! This function will allow the remote CPU system to read a 16/32-bit data
1291 //! word at the local CPU address specified in /e psMessage, and send a Write
1292 //! Protected command with the read data back to the remote CPU system at a
1293 //! write protected address. It will also send the Response Flag used to track
1294 //! the read back to the remote CPU. The \e bBlock parameter can be one of the
1295 //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING.
1296 //!
1297 //! \return None.
1298 //
1299 //*****************************************************************************
1300 void
IPCRtoLDataRead_Protected(volatile tIpcController * psController,tIpcMessage * psMessage,uint16_t bBlock)1301 IPCRtoLDataRead_Protected(volatile tIpcController *psController,
1302                           tIpcMessage *psMessage, uint16_t bBlock)
1303 {
1304     unsigned long ulReaddata;
1305     uint16_t usLength;
1306 
1307     //
1308     // If data word length = 16-bits, read the 16-bit value at the given
1309     // address and cast as 32-bit word to send back to remote CPU.
1310     // If data word length = 32-bits, read the 32-bit value at the given
1311     // address.
1312     //
1313     usLength = (uint16_t)psMessage->uldataw1;
1314 
1315     if (usLength == IPC_LENGTH_16_BITS)
1316     {
1317         ulReaddata = (unsigned long)(*(volatile uint16_t *)psMessage->uladdress);
1318     }
1319     else if (usLength == IPC_LENGTH_32_BITS)
1320     {
1321         ulReaddata = *(unsigned long *)psMessage->uladdress;
1322     }
1323 
1324     //
1325     // Send a Write command to write the requested data to the remote CPU read
1326     // into address.
1327     // psMessage->uldataw2 contains remote CPU address where readdata will be
1328     // written.
1329     // psMessage->uldataw1 contains the read response flag in IPC flag 17-32.
1330     //
1331     IPCLtoRDataWrite_Protected(psController, psMessage->uldataw2, ulReaddata,
1332                                usLength, bBlock,
1333                                (psMessage->uldataw1 & 0xFFFF0000));
1334 }
1335 
1336 //*****************************************************************************
1337 //
1338 //! Sets the designated bits in a 16/32-bit data word at a local CPU system
1339 //! address
1340 //!
1341 //! \param psMessage specifies the pointer to the message received from the
1342 //! remote CPU system.
1343 //!
1344 //! This function will allow the remote CPU system to set the bits in a
1345 //! 16/32-bit word on the local CPU system via a local CPU address and mask
1346 //! passed in via the \e psMessage.
1347 //!
1348 //! \return None.
1349 //
1350 //*****************************************************************************
1351 void
IPCRtoLSetBits(tIpcMessage * psMessage)1352 IPCRtoLSetBits(tIpcMessage *psMessage)
1353 {
1354     uint16_t usLength;
1355 
1356     //
1357     // Determine length of word at psMessage->uladdress and then set bits based
1358     // on either the 16-bit or 32-bit bit-mask in psMessage->uldataw2.
1359     // (16-bit length ignores upper 16-bits of psMessage->uldataw2)
1360     //
1361     usLength = (uint16_t)psMessage->uldataw1;
1362 
1363     if (usLength == IPC_LENGTH_16_BITS)
1364     {
1365         *(volatile uint16_t*)psMessage->uladdress |=
1366                                                 (uint16_t) psMessage->uldataw2;
1367     }
1368     else if (usLength == IPC_LENGTH_32_BITS)
1369     {
1370         *(volatile unsigned long *)psMessage->uladdress |=  psMessage->uldataw2;
1371     }
1372 }
1373 
1374 //*****************************************************************************
1375 //
1376 //! Sets the designated bits in a 16/32-bit write-protected data word at a
1377 //! local CPU system address
1378 //!
1379 //! \param psMessage specifies the pointer to the message received from the
1380 //! remote CPU system.
1381 //!
1382 //! This function will allow the remote CPU system to set the bits in a write-
1383 //! protected 16/32-bit word on the local CPU system via a local CPU address
1384 //! and mask passed in via the \e psMessage.
1385 //!
1386 //! \return None
1387 //
1388 //*****************************************************************************
1389 void
IPCRtoLSetBits_Protected(tIpcMessage * psMessage)1390 IPCRtoLSetBits_Protected(tIpcMessage *psMessage)
1391 {
1392     uint16_t usLength;
1393 
1394     //
1395     // Allow access to EALLOW-protected registers.
1396     //
1397     EALLOW;
1398 
1399     //
1400     // Determine length of word at psMessage->uladdress and then set bits based
1401     // on either the 16-bit or 32-bit bit-mask in psMessage->uldataw2.
1402     // (16-bit length ignores upper 16-bits of psMessage->uldataw2)
1403     //
1404     usLength = (uint16_t)psMessage->uldataw1;
1405 
1406     if (usLength == IPC_LENGTH_16_BITS)
1407     {
1408         *(volatile uint16_t*)psMessage->uladdress |=
1409                                                 (uint16_t) psMessage->uldataw2;
1410     }
1411     else if (usLength == IPC_LENGTH_32_BITS)
1412     {
1413         *(volatile unsigned long *)psMessage->uladdress |= psMessage->uldataw2;
1414     }
1415 
1416     //
1417     // Disable access to EALLOW-protected registers.
1418     //
1419     EDIS;
1420 }
1421 
1422 //*****************************************************************************
1423 //
1424 //! Clears the designated bits in a 32-bit data word at a local CPU system
1425 //! address
1426 //!
1427 //! \param psMessage specifies the pointer to the message received from the
1428 //! remote CPU system.
1429 //!
1430 //! This function will allow the remote CPU system to clear the bits in a
1431 //! 16/32-bit word on the local CPU system via a local CPU address and mask
1432 //! passed in via the \e psMessage.
1433 //!
1434 //! \return None.
1435 //
1436 //*****************************************************************************
1437 void
IPCRtoLClearBits(tIpcMessage * psMessage)1438 IPCRtoLClearBits(tIpcMessage *psMessage)
1439 {
1440     uint16_t usLength;
1441 
1442     //
1443     // Determine length of word at psMessage->uladdress and then clear bits
1444     // based on
1445     // either the 16-bit or 32-bit bit-mask in psMessage->uldataw2.
1446     // (16-bit length ignores upper 16-bits of psMessage->uldataw2)
1447     //
1448     usLength = (uint16_t)psMessage->uldataw1;
1449 
1450     if (usLength == IPC_LENGTH_16_BITS)
1451     {
1452         *(volatile uint16_t*)psMessage->uladdress &=
1453             ~((uint16_t) psMessage->uldataw2);
1454     }
1455     else if (usLength == IPC_LENGTH_32_BITS)
1456     {
1457         *(volatile unsigned long *)psMessage->uladdress &=
1458             ~(psMessage->uldataw2);
1459     }
1460 }
1461 
1462 //*****************************************************************************
1463 //
1464 //! Clears the designated bits in a write-protected 16/32-bit data word at a
1465 //! local CPU system address
1466 //!
1467 //! \param psMessage specifies the pointer to the message received from the
1468 //! remote CPU system.
1469 //!
1470 //! This function will allow the secondary CPU system to clear the bits in a
1471 //! 16/32-bit write-protected  word on the local CPU system via a local
1472 //! CPU address and mask passed in via the \e psMessage.
1473 //!
1474 //! \return None.
1475 //
1476 //*****************************************************************************
1477 void
IPCRtoLClearBits_Protected(tIpcMessage * psMessage)1478 IPCRtoLClearBits_Protected(tIpcMessage *psMessage)
1479 {
1480     uint16_t usLength;
1481 
1482     //
1483     // Allow access to EALLOW-protected registers.
1484     //
1485     EALLOW;
1486 
1487     //
1488     // Determine length of word at psMessage->uladdress and then clear bits
1489     // based on
1490     // either the 16-bit or 32-bit bit-mask in psMessage->uldataw2.
1491     // (16-bit length ignores upper 16-bits of psMessage->uldataw2)
1492     //
1493     usLength = (uint16_t)psMessage->uldataw1;
1494 
1495     if (usLength == IPC_LENGTH_16_BITS)
1496     {
1497         *(volatile uint16_t*)psMessage->uladdress &=
1498             ~((uint16_t) psMessage->uldataw2);
1499     }
1500     else if (usLength == IPC_LENGTH_32_BITS)
1501     {
1502         *(volatile unsigned long *)psMessage->uladdress &=
1503             ~(psMessage->uldataw2);
1504     }
1505 
1506     //
1507     // Disable access to EALLOW-protected registers.
1508     //
1509     EDIS;
1510 }
1511 
1512 //*****************************************************************************
1513 //
1514 //! Reads a block of data from a remote CPU system address and stores into
1515 //! shared RAM
1516 //!
1517 //! \param psMessage specifies the pointer to the message received from the
1518 //! remote CPU system.
1519 //!
1520 //! This function will respond to the remote CPU system request to read a block
1521 //! of data from the local control system, by reading the data and placing that
1522 //! data into the shared RAM location specified in \e psMessage.
1523 //!
1524 //! \return None.
1525 //
1526 //*****************************************************************************
1527 void
IPCRtoLBlockRead(tIpcMessage * psMessage)1528 IPCRtoLBlockRead(tIpcMessage *psMessage)
1529 {
1530 
1531     uint16_t usLength;
1532     volatile uint16_t* pusRAddress;
1533     volatile uint16_t* pusWAddress;
1534     uint16_t usIndex;
1535 
1536     pusRAddress = (volatile uint16_t *)psMessage->uladdress;
1537     pusWAddress = (volatile uint16_t *)psMessage->uldataw2;
1538     usLength = (uint16_t)psMessage->uldataw1;
1539 
1540     for (usIndex=0; usIndex<usLength; usIndex++)
1541     {
1542         *pusWAddress = *pusRAddress;
1543         pusWAddress += 1;
1544         pusRAddress += 1;
1545     }
1546 
1547     IpcRegs.IPCACK.all |= (psMessage->uldataw1 & 0xFFFF0000);
1548 }
1549 
1550 //*****************************************************************************
1551 //
1552 //! Writes a block of data to a local CPU system address from shared RAM
1553 //!
1554 //! \param psMessage specifies the pointer to the message received from the
1555 //! remote CPU system.
1556 //!
1557 //! This function will write a block of data to an address on the local CPU
1558 //! system.
1559 //! The data is first written by the remote CPU to shared RAM. This function
1560 //! reads the shared RAM location, word size (16- or 32-bit), and block size
1561 //! from \e psMessage and writes the block to the local address specified
1562 //! in \e psMessage.
1563 //!
1564 //! \return None.
1565 //
1566 //*****************************************************************************
1567 void
IPCRtoLBlockWrite(tIpcMessage * psMessage)1568 IPCRtoLBlockWrite(tIpcMessage *psMessage)
1569 {
1570     uint16_t usLength;
1571     uint16_t usWLength;
1572     uint16_t usIndex;
1573 
1574     usLength = (uint16_t)psMessage->uldataw1;
1575     usWLength = (uint16_t)((psMessage->uldataw1)>>16);
1576 
1577     //
1578     // Determine data word access size to write to data block.
1579     //
1580     if (usWLength == IPC_LENGTH_16_BITS)
1581     {
1582         volatile uint16_t *pusWAddress = (volatile uint16_t *)psMessage->uladdress;
1583         volatile uint16_t *pusRAddress = (volatile uint16_t *)psMessage->uldataw2;
1584         for (usIndex=0; usIndex<usLength; usIndex++)
1585         {
1586             *pusWAddress = *pusRAddress;
1587             pusWAddress += 1;
1588             pusRAddress += 1;
1589         }
1590     } else if (usWLength == IPC_LENGTH_32_BITS)
1591     {
1592         volatile unsigned long *pulWAddress =
1593             (volatile unsigned long *)psMessage->uladdress;
1594         volatile unsigned long *pulRAddress =
1595             (volatile unsigned long *)psMessage->uldataw2;
1596 
1597         for (usIndex=0; usIndex<usLength; usIndex++)
1598         {
1599             *pulWAddress = *pulRAddress;
1600             pulWAddress += 1;
1601             pulRAddress += 1;
1602         }
1603     }
1604 }
1605 
1606 //*****************************************************************************
1607 //
1608 //! Writes a block of data to a local CPU system write-protected address from
1609 //! shared RAM
1610 //!
1611 //! \param psMessage specifies the pointer to the message received from the
1612 //! remote CPU system.
1613 //!
1614 //! This function will write a block of data to a write-protected group of
1615 //! addresses on the local CPU system. The data is first written by the
1616 //! remote CPU to shared RAM. This function reads the shared RAM location,
1617 //! word size (16- or 32-bit), and block size from \e psMessage  and writes the
1618 //! block to the local address specified in \e psMessage.
1619 //!
1620 //! \return None.
1621 //
1622 //*****************************************************************************
1623 void
IPCRtoLBlockWrite_Protected(tIpcMessage * psMessage)1624 IPCRtoLBlockWrite_Protected(tIpcMessage *psMessage)
1625 {
1626     uint16_t usLength;
1627     uint16_t usWLength;
1628     uint16_t usIndex;
1629 
1630     //
1631     // Allow access to EALLOW-protected registers.
1632     //
1633     EALLOW;
1634 
1635     usLength = (uint16_t)psMessage->uldataw1;
1636     usWLength = (uint16_t)((psMessage->uldataw1)>>16);
1637 
1638     //
1639     // Determine data word access size to write to data block.
1640     // (Writes registers accessible via APB bus must be 32-bits wide)
1641     //
1642     if (usWLength == IPC_LENGTH_16_BITS)
1643     {
1644         volatile uint16_t *pusWAddress = (volatile uint16_t *)psMessage->uladdress;
1645         volatile uint16_t *pusRAddress = (volatile uint16_t *)psMessage->uldataw2;
1646         for (usIndex=0; usIndex<usLength; usIndex++)
1647         {
1648             *pusWAddress = *pusRAddress;
1649             pusWAddress += 1;
1650             pusRAddress += 1;
1651         }
1652     } else if (usWLength == IPC_LENGTH_32_BITS)
1653     {
1654         volatile unsigned long *pulWAddress =
1655             (volatile unsigned long *)psMessage->uladdress;
1656         volatile unsigned long *pulRAddress =
1657             (volatile unsigned long *)psMessage->uldataw2;
1658 
1659         for (usIndex=0; usIndex<usLength; usIndex++)
1660         {
1661             *pulWAddress = *pulRAddress;
1662             pulWAddress += 1;
1663             pulRAddress += 1;
1664         }
1665     }
1666 
1667     //
1668     // Disable access to EALLOW-protected registers.
1669     //
1670     EDIS;
1671 }
1672 
1673 //*****************************************************************************
1674 //
1675 //! Calls a local function with a single optional parameter.
1676 //!
1677 //! \param psMessage specifies the pointer to the message received from the
1678 //! remote CPU system.
1679 //!
1680 //! This function will allow the remote CPU system to call a local CPU function
1681 //! with a single optional parameter. There is no return value from the
1682 //! executed function.
1683 //!
1684 //! \return None.
1685 //
1686 //*****************************************************************************
1687 void
IPCRtoLFunctionCall(tIpcMessage * psMessage)1688 IPCRtoLFunctionCall(tIpcMessage *psMessage)
1689 {
1690     //
1691     // Executes function call with parameter at given address.
1692     //
1693     tfIpcFuncCall func_call = (tfIpcFuncCall)psMessage->uladdress;
1694     func_call(psMessage->uldataw1);
1695 }
1696 
1697 //*****************************************************************************
1698 // Close the Doxygen group.
1699 //! @}
1700 //*****************************************************************************
1701 
1702 
1703