1 //###########################################################################
2 //
3 // FILE:   F2837xD_Ipc_Driver_Util.c
4 //
5 // TITLE:  F2837xD Inter-Processor Communication (IPC) API Driver Utility
6 //         Functions
7 //
8 // DESCRIPTION:
9 //         API functions for inter-processor communications between the
10 //         Local and Remote CPU system.
11 //         The driver functions in this file are available only as
12 //         sample functions for application development.  Due to the generic
13 //         nature of these functions and the cycle overhead inherent to a
14 //         function call, the code is not intended to be used in cases where
15 //         maximum efficiency is required in a system.
16 //
17 // NOTE:   This source code is used by both CPUs. That is both CPU1 and CPU2
18 //         cores use this code.
19 //         The active debug CPU will be referred to as Local CPU and the other
20 //         CPU will be referred to as Remote CPU.
21 //         When using this source code in CPU1, the term "local"
22 //         will mean CPU1 and the term "remote" CPU will be mean CPU2.
23 //         When using this source code in CPU2, the term "local"
24 //         will mean CPU2 and the term "remote" CPU will be mean CPU1.
25 //
26 //         The abbreviations LtoR and RtoL  within the function names mean
27 //         Local to Remote and Remote to Local respectively.
28 //
29 //###########################################################################
30 // $TI Release: F2837xD Support Library v3.05.00.00 $
31 // $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
32 // $Copyright:
33 // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
34 //
35 // Redistribution and use in source and binary forms, with or without
36 // modification, are permitted provided that the following conditions
37 // are met:
38 //
39 //   Redistributions of source code must retain the above copyright
40 //   notice, this list of conditions and the following disclaimer.
41 //
42 //   Redistributions in binary form must reproduce the above copyright
43 //   notice, this list of conditions and the following disclaimer in the
44 //   documentation and/or other materials provided with the
45 //   distribution.
46 //
47 //   Neither the name of Texas Instruments Incorporated nor the names of
48 //   its contributors may be used to endorse or promote products derived
49 //   from this software without specific prior written permission.
50 //
51 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 // $
63 //###########################################################################
64 
65 //*****************************************************************************
66 //
67 //! \addtogroup ipc_util_api
68 //! @{
69 //
70 //*****************************************************************************
71 #include "F2837xD_device.h"
72 #include "F2837xD_GlobalPrototypes.h"
73 #include "F2837xD_Gpio_defines.h"
74 #include "F2837xD_Ipc_drivers.h"
75 
76 //*****************************************************************************
77 //
78 //! Local CPU Acknowledges Remote to Local IPC Flag.
79 //!
80 //! \param ulFlags specifies the IPC flag mask for flags being acknowledged.
81 //!
82 //! This function will allow the Local CPU system to acknowledge/clear the IPC
83 //! flag set by the Remote CPU system. The \e ulFlags parameter can be any of
84 //! the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31.
85 //!
86 //! \return None.
87 //
88 //*****************************************************************************
89 void
IPCRtoLFlagAcknowledge(uint32_t ulFlags)90 IPCRtoLFlagAcknowledge (uint32_t ulFlags)
91 {
92     IpcRegs.IPCACK.all |= ulFlags;
93 }
94 
95 //*****************************************************************************
96 //
97 //! Determines whether the given Remote to Local IPC flags are busy or not.
98 //!
99 //! \param ulFlags specifies Remote to Local IPC Flag number masks to check the
100 //!        status of.
101 //!
102 //! Allows the caller to determine whether the designated IPC flags are
103 //! pending. The \e ulFlags parameter can be any of the IPC flag
104 //! values: \b IPC_FLAG0 - \b IPC_FLAG31.
105 //!
106 //! \return Returns \b 1 if the IPC flags are busy or \b 0 if designated
107 //! IPC flags are free.
108 //
109 //*****************************************************************************
110 Uint16
IPCRtoLFlagBusy(uint32_t ulFlags)111 IPCRtoLFlagBusy (uint32_t ulFlags)
112 {
113     Uint16 returnStatus;
114 
115     if ((IpcRegs.IPCSTS.all & ulFlags) == 0)
116     {
117         returnStatus = 0;
118     }
119     else
120     {
121         returnStatus = 1;
122     }
123 
124     return returnStatus;
125 }
126 
127 //*****************************************************************************
128 //
129 //! Determines whether the given IPC flags are busy or not.
130 //!
131 //! \param ulFlags specifies Local to Remote IPC Flag number masks to check the
132 //!        status of.
133 //!
134 //! Allows the caller to determine whether the designated IPC flags are
135 //! available for further control to master system communication. If \b 0 is
136 //! returned, then all designated tasks have completed and are available.
137 //! The \e ulFlags parameter can be any of the IPC flag
138 //! values: \b IPC_FLAG0 - \b IPC_FLAG31.
139 //!
140 //! \return Returns \b 1 if the IPC flags are busy or \b 0 if designated
141 //! IPC flags are free.
142 //
143 //*****************************************************************************
144 Uint16
IPCLtoRFlagBusy(uint32_t ulFlags)145 IPCLtoRFlagBusy (uint32_t ulFlags)
146 {
147     Uint16 returnStatus;
148 
149     if ((IpcRegs.IPCFLG.all & ulFlags) == 0)
150     {
151         returnStatus = 0;
152     }
153     else
154     {
155         returnStatus = 1;
156     }
157 
158     return returnStatus;
159 }
160 
161 //*****************************************************************************
162 //
163 //! Local CPU Sets Local to Remote IPC Flag
164 //!
165 //! \param ulFlags specifies the IPC flag mask for flags being set.
166 //!
167 //! This function will allow the Local CPU system to set the designated IPC
168 //! flags to send to the Remote CPU system. The \e ulFlags parameter can be any
169 //! of the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31.
170 //!
171 //! \return None.
172 //
173 //*****************************************************************************
174 void
IPCLtoRFlagSet(uint32_t ulFlags)175 IPCLtoRFlagSet (uint32_t ulFlags)
176 {
177     IpcRegs.IPCSET.all |= ulFlags;
178 }
179 
180 //*****************************************************************************
181 //
182 //! Local CPU Clears Local to Remote IPC Flag
183 //!
184 //! \param ulFlags specifies the IPC flag mask for flags being set.
185 //!
186 //! This function will allow the Local CPU system to set the designated IPC
187 //! flags to send to the Remote CPU system. The \e ulFlags parameter can be any
188 //! of the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31.
189 //!
190 //! \return None.
191 //
192 //*****************************************************************************
193 void
IPCLtoRFlagClear(uint32_t ulFlags)194 IPCLtoRFlagClear (uint32_t ulFlags)
195 {
196     IpcRegs.IPCCLR.all |= ulFlags;
197 }
198 
199 //*****************************************************************************
200 //
201 //! Local Return CPU02 BOOT status
202 //!
203 //! This function returns the value at IPCBOOTSTS register.
204 //!
205 //! \return Boot status.
206 //
207 //*****************************************************************************
208 uint32_t
IPCGetBootStatus(void)209 IPCGetBootStatus (void)
210 {
211    return(IpcRegs.IPCBOOTSTS);
212 }
213 
214 #if defined (CPU1)
215 //*****************************************************************************
216 //! Executes a CPU02 control system bootloader.
217 //!
218 //! \param ulBootMode specifies which CPU02 control system boot mode to execute.
219 //!
220 //! This function will allow the CPU01 master system to boot the CPU02 control
221 //! system via the following modes: Boot to RAM, Boot to Flash, Boot via SPI,
222 //! SCI, I2C, or parallel I/O. Unlike other IPCLite driver functions, this
223 //! function blocks and waits until the control system boot ROM is configured
224 //! and ready to receive CPU01 to CPU02 IPC INT0 interrupts. It then blocks and
225 //! waits until IPC INT0 and IPC FLAG31 are available in the CPU02 boot ROM
226 //! prior to sending the command to execute the selected bootloader. The \e
227 //! ulBootMode parameter accepts one of the following values: \b
228 //! C1C2_BROM_BOOTMODE_BOOT_FROM_PARALLEL, \b
229 //! C1C2_BROM_BOOTMODE_BOOT_FROM_SCI, \b
230 //! C1C2_BROM_BOOTMODE_BOOT_FROM_SPI, \b
231 //! C1C2_BROM_BOOTMODE_BOOT_FROM_I2C, \b C1C2_BROM_BOOTMODE_BOOT_FROM_CAN,
232 //! \b C1C2_BROM_BOOTMODE_BOOT_FROM_RAM, \b
233 //! C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH.
234 //!
235 //! \return 0 (success) if command is sent, or 1 (failure) if boot mode is
236 //! invalid and command was not sent.
237 //
238 //*****************************************************************************
239 uint16_t
IPCBootCPU2(uint32_t ulBootMode)240 IPCBootCPU2(uint32_t ulBootMode)
241 {
242     uint32_t bootStatus;
243     uint16_t pin;
244     uint16_t returnStatus = STATUS_PASS;
245 
246     //
247     // If CPU2 has already booted, return a fail to let the application
248     // know that something is out of the ordinary.
249     //
250     bootStatus = IPCGetBootStatus() & 0x0000000F;
251 
252     if(bootStatus == C2_BOOTROM_BOOTSTS_C2TOC1_BOOT_CMD_ACK)
253     {
254         //
255         // Check if MSB is set as well
256         //
257         bootStatus = ((uint32_t)(IPCGetBootStatus() & 0x80000000)) >> 31U;
258 
259         if(bootStatus != 0)
260         {
261             returnStatus = STATUS_FAIL;
262 
263             return returnStatus;
264         }
265     }
266 
267     //
268     // Wait until CPU02 control system boot ROM is ready to receive
269     // CPU01 to CPU02 INT1 interrupts.
270     //
271     do
272     {
273         bootStatus = IPCGetBootStatus() & C2_BOOTROM_BOOTSTS_SYSTEM_READY;
274     } while ((bootStatus != C2_BOOTROM_BOOTSTS_SYSTEM_READY));
275 
276     //
277     // Loop until CPU02 control system IPC flags 1 and 32 are available
278     //
279     while ((IPCLtoRFlagBusy(IPC_FLAG0) == 1) ||
280            (IPCLtoRFlagBusy(IPC_FLAG31) == 1))
281     {
282 
283     }
284 
285     if (ulBootMode >= C1C2_BROM_BOOTMODE_BOOT_COMMAND_MAX_SUPPORT_VALUE)
286     {
287         returnStatus = STATUS_FAIL;
288     }
289     else
290     {
291         //
292         // Based on boot mode, enable pull-ups on peripheral pins and
293         // give GPIO pin control to CPU02 control system.
294         //
295         switch (ulBootMode)
296         {
297             case C1C2_BROM_BOOTMODE_BOOT_FROM_SCI:
298 
299                  EALLOW;
300 
301                  //
302                  //SCIA connected to CPU02
303                  //
304                  DevCfgRegs.CPUSEL5.bit.SCI_A = 1;
305 
306                  //
307                  //Allows CPU02 bootrom to take control of clock
308                  //configuration registers
309                  //
310                  ClkCfgRegs.CLKSEM.all = 0xA5A50000;
311 
312                  ClkCfgRegs.LOSPCP.all = 0x0002;
313                  EDIS;
314 
315                  GPIO_SetupPinOptions(29, GPIO_OUTPUT, GPIO_ASYNC);
316                  GPIO_SetupPinMux(29,GPIO_MUX_CPU2,1);
317 
318                  GPIO_SetupPinOptions(28, GPIO_INPUT, GPIO_ASYNC);
319                  GPIO_SetupPinMux(28,GPIO_MUX_CPU2,1);
320 
321                 break;
322 
323             case C1C2_BROM_BOOTMODE_BOOT_FROM_SPI:
324                  EALLOW;
325 
326                  //
327                  //SPI-A connected to CPU02
328                  //
329                  DevCfgRegs.CPUSEL6.bit.SPI_A = 1;
330 
331                  //
332                  //Allows CPU02 bootrom to take control of clock configuration
333                  // registers
334                  //
335                  ClkCfgRegs.CLKSEM.all = 0xA5A50000;
336                  EDIS;
337 
338                  GPIO_SetupPinOptions(16, GPIO_INPUT, GPIO_ASYNC);
339                  GPIO_SetupPinMux(16,GPIO_MUX_CPU2,1);
340 
341                  GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC);
342                  GPIO_SetupPinMux(17,GPIO_MUX_CPU2,1);
343 
344                  GPIO_SetupPinOptions(18, GPIO_INPUT, GPIO_ASYNC);
345                  GPIO_SetupPinMux(18,GPIO_MUX_CPU2,1);
346 
347                  GPIO_SetupPinOptions(19, GPIO_OUTPUT, GPIO_ASYNC);
348                  GPIO_SetupPinMux(19,GPIO_MUX_CPU2,0);
349 
350                 break;
351 
352             case C1C2_BROM_BOOTMODE_BOOT_FROM_I2C:
353                  EALLOW;
354 
355                  //
356                  //I2CA connected to CPU02
357                  //
358                  DevCfgRegs.CPUSEL7.bit.I2C_A = 1;
359 
360                  //
361                  //Allows CPU2 bootrom to take control of clock
362                  //configuration registers
363                  //
364                  ClkCfgRegs.CLKSEM.all = 0xA5A50000;
365                  ClkCfgRegs.LOSPCP.all = 0x0002;
366                  EDIS;
367                  GPIO_SetupPinOptions(32, GPIO_INPUT, GPIO_ASYNC);
368                  GPIO_SetupPinMux(32,GPIO_MUX_CPU2,1);
369 
370                  GPIO_SetupPinOptions(33, GPIO_INPUT, GPIO_ASYNC);
371                  GPIO_SetupPinMux(33,GPIO_MUX_CPU2,1);
372 
373                 break;
374             case C1C2_BROM_BOOTMODE_BOOT_FROM_PARALLEL:
375 
376                  for(pin=58;pin<=65;pin++)
377                  {
378                     GPIO_SetupPinOptions(pin, GPIO_INPUT, GPIO_ASYNC);
379                     GPIO_SetupPinMux(pin,GPIO_MUX_CPU2,0);
380                  }
381 
382                  GPIO_SetupPinOptions(69, GPIO_OUTPUT, GPIO_ASYNC);
383                  GPIO_SetupPinMux(69,GPIO_MUX_CPU2,0);
384 
385                  GPIO_SetupPinOptions(70, GPIO_INPUT, GPIO_ASYNC);
386                  GPIO_SetupPinMux(70,GPIO_MUX_CPU2,0);
387                  break;
388 
389 
390             case C1C2_BROM_BOOTMODE_BOOT_FROM_CAN:
391                  //
392                  //Set up the GPIO mux to bring out CANATX on GPIO71
393                  //and CANARX on GPIO70
394                  //
395                  EALLOW;
396                  GpioCtrlRegs.GPCLOCK.all = 0x00000000; //Unlock GPIOs 64-95
397 
398                  //
399                  //Give CPU2 control just in case
400                  //
401                  GpioCtrlRegs.GPCCSEL1.bit.GPIO71 = GPIO_MUX_CPU2;
402 
403                  //
404                  //Set the extended mux to 0x5
405                  //
406                  GpioCtrlRegs.GPCGMUX1.bit.GPIO71 = 0x1;
407                  GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 0x1;
408 
409                  //
410                  //Set qualification to async just in case
411                  //
412                  GpioCtrlRegs.GPCQSEL1.bit.GPIO71 = 0x3;
413 
414                  GpioCtrlRegs.GPCLOCK.all = 0x00000000; //Unlock GPIOs 64-95
415 
416                  //
417                  //Give CPU2 control just in case
418                  //
419                  GpioCtrlRegs.GPCCSEL1.bit.GPIO70 = GPIO_MUX_CPU2;
420 
421                  //
422                  //Set the extended mux to bring out CANATX
423                  //
424                  GpioCtrlRegs.GPCGMUX1.bit.GPIO70 = 0x1;
425                  GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 0x1;
426 
427                  //
428                  //Set qualification to async just in case
429                  //
430                  GpioCtrlRegs.GPCQSEL1.bit.GPIO70 = 0x3;
431                  GpioCtrlRegs.GPCLOCK.all = 0xFFFFFFFF; //Lock GPIOs 64-95
432                  ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0x0;
433                  CpuSysRegs.PCLKCR10.bit.CAN_A = 1;
434                  EDIS;
435 
436                break;
437 
438          }
439 
440         //
441         //CPU01 to CPU02 IPC Boot Mode Register
442         //
443         IpcRegs.IPCBOOTMODE = ulBootMode;
444 
445         //
446         // CPU01 To CPU02 IPC Command Register
447         //
448         IpcRegs.IPCSENDCOM  = BROM_IPC_EXECUTE_BOOTMODE_CMD;
449 
450         //
451         // CPU01 to CPU02 IPC flag register
452         //
453         IpcRegs.IPCSET.all = 0x80000001;
454 
455     }
456 
457 
458 
459     return returnStatus;
460 }
461 
462 
463 #endif
464 //*****************************************************************************
465 // Close the Doxygen group.
466 //! @}
467 //*****************************************************************************
468 
469 
470