//########################################################################### // // FILE: F2837xD_Ipc_Driver_Util.c // // TITLE: F2837xD Inter-Processor Communication (IPC) API Driver Utility // Functions // // DESCRIPTION: // API functions for inter-processor communications between the // Local and Remote CPU system. // The driver functions in this file are available only as // sample functions for application development. Due to the generic // nature of these functions and the cycle overhead inherent to a // function call, the code is not intended to be used in cases where // maximum efficiency is required in a system. // // NOTE: This source code is used by both CPUs. That is both CPU1 and CPU2 // cores use this code. // The active debug CPU will be referred to as Local CPU and the other // CPU will be referred to as Remote CPU. // When using this source code in CPU1, the term "local" // will mean CPU1 and the term "remote" CPU will be mean CPU2. // When using this source code in CPU2, the term "local" // will mean CPU2 and the term "remote" CPU will be mean CPU1. // // The abbreviations LtoR and RtoL within the function names mean // Local to Remote and Remote to Local respectively. // //########################################################################### // // $Release Date: $ // $Copyright: // Copyright (C) 2013-2022 Texas Instruments Incorporated - http://www.ti.com/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // $ //########################################################################### //***************************************************************************** // //! \addtogroup ipc_util_api //! @{ // //***************************************************************************** #include "F2837xD_device.h" #include "F2837xD_GlobalPrototypes.h" #include "F2837xD_Gpio_defines.h" #include "F2837xD_Ipc_drivers.h" //***************************************************************************** // //! Local CPU Acknowledges Remote to Local IPC Flag. //! //! \param ulFlags specifies the IPC flag mask for flags being acknowledged. //! //! This function will allow the Local CPU system to acknowledge/clear the IPC //! flag set by the Remote CPU system. The \e ulFlags parameter can be any of //! the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31. //! //! \return None. // //***************************************************************************** void IPCRtoLFlagAcknowledge (uint32_t ulFlags) { IpcRegs.IPCACK.all = ulFlags; } //***************************************************************************** // //! Determines whether the given Remote to Local IPC flags are busy or not. //! //! \param ulFlags specifies Remote to Local IPC Flag number masks to check the //! status of. //! //! Allows the caller to determine whether the designated IPC flags are //! pending. The \e ulFlags parameter can be any of the IPC flag //! values: \b IPC_FLAG0 - \b IPC_FLAG31. //! //! \return Returns \b 1 if the IPC flags are busy or \b 0 if designated //! IPC flags are free. // //***************************************************************************** Uint16 IPCRtoLFlagBusy (uint32_t ulFlags) { Uint16 returnStatus; if ((IpcRegs.IPCSTS.all & ulFlags) == 0) { returnStatus = 0; } else { returnStatus = 1; } return returnStatus; } //***************************************************************************** // //! Determines whether the given IPC flags are busy or not. //! //! \param ulFlags specifies Local to Remote IPC Flag number masks to check the //! status of. //! //! Allows the caller to determine whether the designated IPC flags are //! available for further control to master system communication. If \b 0 is //! returned, then all designated tasks have completed and are available. //! The \e ulFlags parameter can be any of the IPC flag //! values: \b IPC_FLAG0 - \b IPC_FLAG31. //! //! \return Returns \b 1 if the IPC flags are busy or \b 0 if designated //! IPC flags are free. // //***************************************************************************** Uint16 IPCLtoRFlagBusy (uint32_t ulFlags) { Uint16 returnStatus; if ((IpcRegs.IPCFLG.all & ulFlags) == 0) { returnStatus = 0; } else { returnStatus = 1; } return returnStatus; } //***************************************************************************** // //! Local CPU Sets Local to Remote IPC Flag //! //! \param ulFlags specifies the IPC flag mask for flags being set. //! //! This function will allow the Local CPU system to set the designated IPC //! flags to send to the Remote CPU system. The \e ulFlags parameter can be any //! of the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31. //! //! \return None. // //***************************************************************************** void IPCLtoRFlagSet (uint32_t ulFlags) { IpcRegs.IPCSET.all = ulFlags; } //***************************************************************************** // //! Local CPU Clears Local to Remote IPC Flag //! //! \param ulFlags specifies the IPC flag mask for flags being set. //! //! This function will allow the Local CPU system to set the designated IPC //! flags to send to the Remote CPU system. The \e ulFlags parameter can be any //! of the IPC flag values: \b IPC_FLAG0 - \b IPC_FLAG31. //! //! \return None. // //***************************************************************************** void IPCLtoRFlagClear (uint32_t ulFlags) { IpcRegs.IPCCLR.all = ulFlags; } //***************************************************************************** // //! Local Return CPU02 BOOT status //! //! This function returns the value at IPCBOOTSTS register. //! //! \return Boot status. // //***************************************************************************** uint32_t IPCGetBootStatus (void) { return(IpcRegs.IPCBOOTSTS); } #if defined (CPU1) //***************************************************************************** //! Executes a CPU02 control system bootloader. //! //! \param ulBootMode specifies which CPU02 control system boot mode to execute. //! //! This function will allow the CPU01 master system to boot the CPU02 control //! system via the following modes: Boot to RAM, Boot to Flash, Boot via SPI, //! SCI, I2C, or parallel I/O. Unlike other IPCLite driver functions, this //! function blocks and waits until the control system boot ROM is configured //! and ready to receive CPU01 to CPU02 IPC INT0 interrupts. It then blocks and //! waits until IPC INT0 and IPC FLAG31 are available in the CPU02 boot ROM //! prior to sending the command to execute the selected bootloader. The \e //! ulBootMode parameter accepts one of the following values: \b //! C1C2_BROM_BOOTMODE_BOOT_FROM_PARALLEL, \b //! C1C2_BROM_BOOTMODE_BOOT_FROM_SCI, \b //! C1C2_BROM_BOOTMODE_BOOT_FROM_SPI, \b //! C1C2_BROM_BOOTMODE_BOOT_FROM_I2C, \b C1C2_BROM_BOOTMODE_BOOT_FROM_CAN, //! \b C1C2_BROM_BOOTMODE_BOOT_FROM_RAM, \b //! C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH. //! //! \return 0 (success) if command is sent, or 1 (failure) if boot mode is //! invalid and command was not sent. // //***************************************************************************** uint16_t IPCBootCPU2(uint32_t ulBootMode) { uint32_t bootStatus; uint16_t pin; uint16_t returnStatus = STATUS_PASS; // // If CPU2 has already booted, return a fail to let the application // know that something is out of the ordinary. // bootStatus = IPCGetBootStatus() & 0x0000000F; if(bootStatus == C2_BOOTROM_BOOTSTS_C2TOC1_BOOT_CMD_ACK) { // // Check if MSB is set as well // bootStatus = ((uint32_t)(IPCGetBootStatus() & 0x80000000)) >> 31U; if(bootStatus != 0) { returnStatus = STATUS_FAIL; return returnStatus; } } // // Wait until CPU02 control system boot ROM is ready to receive // CPU01 to CPU02 INT1 interrupts. // do { bootStatus = IPCGetBootStatus() & C2_BOOTROM_BOOTSTS_SYSTEM_READY; } while ((bootStatus != C2_BOOTROM_BOOTSTS_SYSTEM_READY)); // // Loop until CPU02 control system IPC flags 1 and 32 are available // while ((IPCLtoRFlagBusy(IPC_FLAG0) == 1) || (IPCLtoRFlagBusy(IPC_FLAG31) == 1)) { } if (ulBootMode >= C1C2_BROM_BOOTMODE_BOOT_COMMAND_MAX_SUPPORT_VALUE) { returnStatus = STATUS_FAIL; } else { // // Based on boot mode, enable pull-ups on peripheral pins and // give GPIO pin control to CPU02 control system. // switch (ulBootMode) { case C1C2_BROM_BOOTMODE_BOOT_FROM_SCI: EALLOW; // //SCIA connected to CPU02 // DevCfgRegs.CPUSEL5.bit.SCI_A = 1; // //Allows CPU02 bootrom to take control of clock //configuration registers // ClkCfgRegs.CLKSEM.all = 0xA5A50000; ClkCfgRegs.LOSPCP.all = 0x0002; EDIS; GPIO_SetupPinOptions(29, GPIO_OUTPUT, GPIO_ASYNC); GPIO_SetupPinMux(29,GPIO_MUX_CPU2,1); GPIO_SetupPinOptions(28, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(28,GPIO_MUX_CPU2,1); break; case C1C2_BROM_BOOTMODE_BOOT_FROM_SPI: EALLOW; // //SPI-A connected to CPU02 // DevCfgRegs.CPUSEL6.bit.SPI_A = 1; // //Allows CPU02 bootrom to take control of clock configuration // registers // ClkCfgRegs.CLKSEM.all = 0xA5A50000; EDIS; GPIO_SetupPinOptions(16, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(16,GPIO_MUX_CPU2,1); GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(17,GPIO_MUX_CPU2,1); GPIO_SetupPinOptions(18, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(18,GPIO_MUX_CPU2,1); GPIO_SetupPinOptions(19, GPIO_OUTPUT, GPIO_ASYNC); GPIO_SetupPinMux(19,GPIO_MUX_CPU2,0); break; case C1C2_BROM_BOOTMODE_BOOT_FROM_I2C: EALLOW; // //I2CA connected to CPU02 // DevCfgRegs.CPUSEL7.bit.I2C_A = 1; // //Allows CPU2 bootrom to take control of clock //configuration registers // ClkCfgRegs.CLKSEM.all = 0xA5A50000; ClkCfgRegs.LOSPCP.all = 0x0002; EDIS; GPIO_SetupPinOptions(32, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(32,GPIO_MUX_CPU2,1); GPIO_SetupPinOptions(33, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(33,GPIO_MUX_CPU2,1); break; case C1C2_BROM_BOOTMODE_BOOT_FROM_PARALLEL: for(pin=58;pin<=65;pin++) { GPIO_SetupPinOptions(pin, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(pin,GPIO_MUX_CPU2,0); } GPIO_SetupPinOptions(69, GPIO_OUTPUT, GPIO_ASYNC); GPIO_SetupPinMux(69,GPIO_MUX_CPU2,0); GPIO_SetupPinOptions(70, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinMux(70,GPIO_MUX_CPU2,0); break; case C1C2_BROM_BOOTMODE_BOOT_FROM_CAN: // //Set up the GPIO mux to bring out CANATX on GPIO71 //and CANARX on GPIO70 // EALLOW; GpioCtrlRegs.GPCLOCK.all = 0x00000000; //Unlock GPIOs 64-95 // //Give CPU2 control just in case // GpioCtrlRegs.GPCCSEL1.bit.GPIO71 = GPIO_MUX_CPU2; // //Set the extended mux to 0x5 // GpioCtrlRegs.GPCGMUX1.bit.GPIO71 = 0x1; GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 0x1; // //Set qualification to async just in case // GpioCtrlRegs.GPCQSEL1.bit.GPIO71 = 0x3; GpioCtrlRegs.GPCLOCK.all = 0x00000000; //Unlock GPIOs 64-95 // //Give CPU2 control just in case // GpioCtrlRegs.GPCCSEL1.bit.GPIO70 = GPIO_MUX_CPU2; // //Set the extended mux to bring out CANATX // GpioCtrlRegs.GPCGMUX1.bit.GPIO70 = 0x1; GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 0x1; // //Set qualification to async just in case // GpioCtrlRegs.GPCQSEL1.bit.GPIO70 = 0x3; GpioCtrlRegs.GPCLOCK.all = 0xFFFFFFFF; //Lock GPIOs 64-95 ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0x0; CpuSysRegs.PCLKCR10.bit.CAN_A = 1; EDIS; break; } // //CPU01 to CPU02 IPC Boot Mode Register // IpcRegs.IPCBOOTMODE = ulBootMode; // // CPU01 To CPU02 IPC Command Register // IpcRegs.IPCSENDCOM = BROM_IPC_EXECUTE_BOOTMODE_CMD; // // CPU01 to CPU02 IPC flag register // IpcRegs.IPCSET.all = 0x80000001; } return returnStatus; } #endif //***************************************************************************** // Close the Doxygen group. //! @} //*****************************************************************************