1 //###########################################################################
2 //
3 // FILE:    F2837xD_Ipc.c
4 //
5 // TITLE:    Inter-Processor Communication module support functions
6 //
7 //###########################################################################
8 // $TI Release: F2837xD Support Library v3.05.00.00 $
9 // $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
10 // $Copyright:
11 // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
12 //
13 // Redistribution and use in source and binary forms, with or without
14 // modification, are permitted provided that the following conditions
15 // are met:
16 //
17 //   Redistributions of source code must retain the above copyright
18 //   notice, this list of conditions and the following disclaimer.
19 //
20 //   Redistributions in binary form must reproduce the above copyright
21 //   notice, this list of conditions and the following disclaimer in the
22 //   documentation and/or other materials provided with the
23 //   distribution.
24 //
25 //   Neither the name of Texas Instruments Incorporated nor the names of
26 //   its contributors may be used to endorse or promote products derived
27 //   from this software without specific prior written permission.
28 //
29 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 // $
41 //###########################################################################
42 
43 //
44 // Included Files
45 //
46 #include "F2837xD_device.h"
47 #include "F2837xD_Examples.h"
48 #include <string.h>
49 
50 //
51 // InitIpc - Initialize all IPC registers and clear all flags
52 //
InitIpc()53 void InitIpc()
54 {
55     //
56     //Clear sent flags. Received flags must not be cleared locally
57     //to handle the case where the remote CPU starts executing first.
58     //In this case, a remote flag could be sent correctly and be
59     //incorrectly cleared by this function. Unfortunately, we're
60     //still left with a startup synchronization problem if the
61     //remote CPU has flags left over from a previous run. There's
62     //probably a better way of handling this.
63     //
64     IpcRegs.IPCCLR.all = 0xFFFFFFFF;
65 
66     //
67     //Clear commands
68     //
69     IpcRegs.IPCSENDCOM = 0;
70     IpcRegs.IPCSENDADDR = 0;
71     IpcRegs.IPCSENDDATA = 0;
72     IpcRegs.IPCLOCALREPLY = 0;
73 
74     //
75     //Clear boot status and pump semaphore
76     //
77     #if defined(CPU1)
78         IpcRegs.IPCBOOTMODE = 0;
79     #elif defined(CPU2)
80         IpcRegs.IPCBOOTSTS = 0;
81     #endif
82     ReleaseFlashPump();
83 }
84 
85 //
86 // ReadIpcTimer - Read the current IPC timer value. The low register must be
87 //                read first to latch a value in the high register.
88 //
ReadIpcTimer()89 unsigned long long ReadIpcTimer()
90 {
91     Uint32 low, high;
92 
93     low = IpcRegs.IPCCOUNTERL;
94     high = IpcRegs.IPCCOUNTERH;
95     return ((unsigned long long)high << 32) | (unsigned long long)low;
96 }
97 
98 //
99 // SendIpcData - Copy data into the IPC send message RAM for this CPU and set
100 //               a flag. If the specified 16-bit word length is greater than
101 //               the size of the message RAM, the data is truncated.
102 //
SendIpcData(void * data,Uint16 word_length,Uint16 flag)103 void SendIpcData(void *data, Uint16 word_length, Uint16 flag)
104 {
105     word_length = (word_length < MSG_RAM_SIZE) ? word_length : MSG_RAM_SIZE;
106 
107     memcpy(SEND_MSG_RAM, data, word_length);
108 
109     if (flag != NO_IPC_FLAG)
110     {
111         SendIpcFlag(flag);
112     }
113 }
114 
115 //
116 // RecvIpcData - Copy data out of the IPC receive message RAM for this CPU. If
117 //               the specified 16-bit word length is greater than the size of
118 //               the message RAM, the data is truncated.
119 //
RecvIpcData(void * recv_buf,Uint16 word_length)120 void RecvIpcData(void *recv_buf, Uint16 word_length)
121 {
122     word_length = (word_length < MSG_RAM_SIZE) ? word_length : MSG_RAM_SIZE;
123     memcpy(recv_buf, RECV_MSG_RAM, word_length);
124 }
125 
126 //
127 // FillIpcSendData - Fill the IPC send message RAM for this CPU with a constant
128 //                   value
129 //
FillIpcSendData(Uint16 fill_data)130 void FillIpcSendData(Uint16 fill_data)
131 {
132     memset(SEND_MSG_RAM, fill_data, MSG_RAM_SIZE);
133 }
134 
135 //
136 // SendIpcCommand - Write the send command, address, and data registers with
137 //                  the specified values, then set an IPC flag.
138 //
SendIpcCommand(Uint32 command,Uint32 address,Uint32 data,Uint16 flag)139 void SendIpcCommand(Uint32 command, Uint32 address, Uint32 data, Uint16 flag)
140 {
141     IpcRegs.IPCSENDCOM = command;
142     IpcRegs.IPCSENDADDR = address;
143     IpcRegs.IPCSENDDATA = data;
144 
145     if (flag != NO_IPC_FLAG)
146     {
147         SendIpcFlag(flag);
148     }
149 }
150 
151 //
152 // SendIpcFlag - Set an IPC flag bit for the other CPU. Flags 0-3 will generate
153 //               PIE interrupts.
154 //
SendIpcFlag(Uint16 flag)155 void SendIpcFlag(Uint16 flag)
156 {
157     IpcRegs.IPCSET.all = 1UL << flag;
158 }
159 
160 //
161 // AckIpcFlag - Acknowledge/clear a received IPC flag
162 //
AckIpcFlag(Uint16 flag)163 void AckIpcFlag(Uint16 flag)
164 {
165     IpcRegs.IPCACK.all = 1UL << flag;
166 }
167 
168 //
169 // CancelIpcFlag - Clear a sent IPC flag bit before the other CPU acknowledges
170 //                 it. You will normally never use this function. To clear a
171 //                 received flag, call AckIpcFlag() instead.
172 //
CancelIpcFlag(Uint16 flag)173 void CancelIpcFlag(Uint16 flag)
174 {
175     IpcRegs.IPCCLR.all = 1UL << flag;
176 }
177 
178 //
179 // WaitForIpcFlag - Wait for any IPC flag in the specified mask to be set.
180 //                  WARNING: If you use this function to wait for an IPC
181 //                  interrupt, you must not clear the IPC flag in the interrupt
182 //                  handler. Otherwise, this function will never return.
183 //
WaitForIpcFlag(Uint16 flag)184 void WaitForIpcFlag(Uint16 flag)
185 {
186     //
187     //WARNING: Don't use this function to wait for an IPC interrupt!
188     //
189     while ((IpcRegs.IPCSTS.all & (1UL << flag)) == 0x00000000) {;}
190 }
191 
192 //
193 // WaitForIpcAck - Wait for any IPC flag in the specified mask to be
194 //                 acknowledged.
195 //
WaitForIpcAck(Uint16 flag)196 void WaitForIpcAck(Uint16 flag)
197 {
198     while ((IpcRegs.IPCFLG.all & (1UL << flag)) != 0x00000000) {;}
199 }
200 
201 //
202 // IpcSync - Synchronize the two CPUs. Neither CPU will return from this
203 //           function call before the other one enters it. Must be called with
204 //           the same flag number on both CPUs.
205 //
IpcSync(Uint16 flag)206 void IpcSync(Uint16 flag)
207 {
208     SendIpcFlag(flag);
209     WaitForIpcFlag(flag);
210     AckIpcFlag(flag);
211     WaitForIpcAck(flag);
212 }
213 
214 //
215 // End of file
216 //
217