//########################################################################### // // FILE: F2837xD_Ipc_Driver.c // // TITLE: F2837xD Inter-Processor Communication (IPC) API Driver Functions. // // DESCRIPTION: // 28x API functions for inter-processor communications between the // two CPUs. The IPC functions require the usage of the CPU1 to CPU2 // and CPU2 to CPU1 MSG RAM's to store the circular ring // buffer and indexes. Commands can be queued up in order on a single // IPC interrupt channel. For those IPC commands which are not // interdependent, multiple IPC interrupt channels may be used. // 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. // 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_driver_api //! @{ //***************************************************************************** #include "F2837xD_device.h" #include "F2837xD_Ipc_drivers.h" #if defined(CPU1) #pragma DATA_SECTION(g_asIPCCPU1toCPU2Buffers, "PUTBUFFER"); #pragma DATA_SECTION(g_usPutWriteIndexes, "PUTWRITEIDX"); #pragma DATA_SECTION(g_usGetReadIndexes, "GETREADIDX"); #pragma DATA_SECTION(g_asIPCCPU2toCPU1Buffers, "GETBUFFER"); #pragma DATA_SECTION(g_usGetWriteIndexes, "GETWRITEIDX"); #pragma DATA_SECTION(g_usPutReadIndexes, "PUTREADIDX"); #elif defined(CPU2) #pragma DATA_SECTION(g_asIPCCPU2toCPU1Buffers, "PUTBUFFER"); #pragma DATA_SECTION(g_usPutWriteIndexes, "PUTWRITEIDX"); #pragma DATA_SECTION(g_usGetReadIndexes, "GETREADIDX"); #pragma DATA_SECTION(g_asIPCCPU1toCPU2Buffers, "GETBUFFER"); #pragma DATA_SECTION(g_usGetWriteIndexes, "GETWRITEIDX"); #pragma DATA_SECTION(g_usPutReadIndexes, "PUTREADIDX"); #endif // // Global Circular Buffer Definitions // tIpcMessage g_asIPCCPU1toCPU2Buffers[NUM_IPC_INTERRUPTS][IPC_BUFFER_SIZE]; tIpcMessage g_asIPCCPU2toCPU1Buffers[NUM_IPC_INTERRUPTS][IPC_BUFFER_SIZE]; // // Global Circular Buffer Index Definitions // uint16_t g_usPutWriteIndexes[NUM_IPC_INTERRUPTS]; uint16_t g_usPutReadIndexes[NUM_IPC_INTERRUPTS]; uint16_t g_usGetWriteIndexes[NUM_IPC_INTERRUPTS]; uint16_t g_usGetReadIndexes[NUM_IPC_INTERRUPTS]; //***************************************************************************** // //! Initializes System IPC driver controller //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param usCPU2IpcInterrupt specifies the CPU2 IPC interrupt number used by //! psController. //! \param usCPU1IpcInterrupt specifies the CPU1 IPC interrupt number used by //! psController. //! //! This function initializes the IPC driver controller with circular buffer //! and index addresses for an IPC interrupt pair. The //! \e usCPU2IpcInterrupt and \e usCPU1IpcInterrupt parameters can be one of //! the following values: //! \b IPC_INT0, \b IPC_INT1, \b IPC_INT2, \b IPC_INT3. //! //! \note If an interrupt is currently in use by an \e tIpcController instance, //! that particular interrupt should not be tied to a second \e tIpcController //! instance. //! //! \note For a particular usCPU2IpcInterrupt - usCPU1IpcInterrupt pair, there //! must be an instance of tIpcController defined and initialized on both the //! CPU1 and CPU2 systems. //! //! \return None. // //***************************************************************************** void IPCInitialize (volatile tIpcController *psController, uint16_t usCPU2IpcInterrupt, uint16_t usCPU1IpcInterrupt) { #if defined(CPU1) // CPU1toCPU2PutBuffer and Index Initialization psController->psPutBuffer = &g_asIPCCPU1toCPU2Buffers[usCPU2IpcInterrupt-1][0]; psController->pusPutWriteIndex = &g_usPutWriteIndexes[usCPU2IpcInterrupt-1]; psController->pusGetReadIndex = &g_usGetReadIndexes[usCPU1IpcInterrupt-1]; psController->ulPutFlag = (uint32_t)(1 << (usCPU2IpcInterrupt - 1)); // CPU1toCPU2GetBuffer and Index Initialization psController->psGetBuffer = &g_asIPCCPU2toCPU1Buffers[usCPU1IpcInterrupt-1][0]; psController->pusGetWriteIndex = &g_usGetWriteIndexes[usCPU1IpcInterrupt-1]; psController->pusPutReadIndex = &g_usPutReadIndexes[usCPU2IpcInterrupt-1]; #elif defined(CPU2) // CPU2toCPU1PutBuffer and Index Initialization psController->psPutBuffer = &g_asIPCCPU2toCPU1Buffers[usCPU1IpcInterrupt-1][0]; psController->pusPutWriteIndex = &g_usPutWriteIndexes[usCPU1IpcInterrupt-1]; psController->pusGetReadIndex = &g_usGetReadIndexes[usCPU2IpcInterrupt-1]; psController->ulPutFlag = (uint32_t)(1 << (usCPU1IpcInterrupt - 1)); // CPU1toCPU2GetBuffer and Index Initialization psController->psGetBuffer = &g_asIPCCPU1toCPU2Buffers[usCPU2IpcInterrupt-1][0]; psController->pusGetWriteIndex = &g_usGetWriteIndexes[usCPU2IpcInterrupt-1]; psController->pusPutReadIndex = &g_usPutReadIndexes[usCPU1IpcInterrupt-1]; #endif // Initialize PutBuffer WriteIndex = 0 and GetBuffer ReadIndex = 0 *(psController->pusPutWriteIndex) = 0; *(psController->pusGetReadIndex) = 0; } //***************************************************************************** // //! Writes a message into the PutBuffer. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param psMessage specifies the address of the \e tIpcMessage instance to be //! written to PutBuffer. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a free slot (1= wait until free spot available, 0 = exit with //! STATUS_FAIL if no free slot). //! //! This function checks if there is a free slot in the PutBuffer. If so, it //! puts the message pointed to by \e psMessage into the free slot and //! increments the WriteIndex. Then it sets the appropriate IPC interrupt flag //! specified by \e psController->usPutFlag. The \e bBlock parameter can be //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return \b STATUS_FAIL if PutBuffer is full. \b STATUS_PASS if Put occurs //! successfully. // //***************************************************************************** uint16_t IpcPut (volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock) { uint16_t writeIndex; uint16_t readIndex; uint16_t returnStatus = STATUS_PASS; writeIndex = *(psController->pusPutWriteIndex); readIndex = *(psController->pusPutReadIndex); // // Wait until Put Buffer slot is free // while (((writeIndex + 1) & MAX_BUFFER_INDEX) == readIndex) { // // If designated as a "Blocking" function, and Put buffer is full, // return immediately with fail status. // if (!bBlock) { returnStatus = STATUS_FAIL; break; } readIndex = *(psController->pusPutReadIndex); } if (returnStatus != STATUS_FAIL) { // // When slot is free, Write Message to PutBuffer, update PutWriteIndex, // and set the CPU IPC INT Flag // psController->psPutBuffer[writeIndex] = *psMessage; writeIndex = (writeIndex + 1) & MAX_BUFFER_INDEX; *(psController->pusPutWriteIndex) = writeIndex; IpcRegs.IPCSET.all = psController->ulPutFlag; } return returnStatus; } //***************************************************************************** // //! Reads a message from the GetBuffer. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param psMessage specifies the address of the \e tIpcMessage instance where //! the message from GetBuffer should be written to. //! \param bBlock specifies whether to allow function to block until GetBuffer //! has a message (1= wait until message available, 0 = exit with STATUS_FAIL //! if no message). //! //! This function checks if there is a message in the GetBuffer. If so, it gets //! the message in the GetBuffer pointed to by the ReadIndex and writes it to //! the address pointed to by \e psMessage. The \e bBlock parameter can be one //! of the following //! values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return \b STATUS_PASS if GetBuffer is empty. \b STATUS_FAIL if Get occurs //! successfully. // //***************************************************************************** uint16_t IpcGet (volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock) { uint16_t writeIndex; uint16_t readIndex; uint16_t returnStatus = STATUS_PASS; writeIndex = *(psController->pusGetWriteIndex); readIndex = *(psController->pusGetReadIndex); // // Loop while GetBuffer is empty // while (writeIndex == readIndex) { // // If designated as a "Blocking" function, and Get buffer is empty, // return immediately with fail status. // if (!bBlock) { returnStatus = STATUS_FAIL; break; } writeIndex = *(psController->pusGetWriteIndex); } if (returnStatus != STATUS_FAIL) { // // If there is a message in GetBuffer, Read Message and update // the ReadIndex // *psMessage = psController->psGetBuffer[readIndex]; readIndex = (readIndex + 1) & MAX_BUFFER_INDEX; *(psController->pusGetReadIndex) = readIndex; } return returnStatus; } //***************************************************************************** // //! Sends a command to read either a 16- or 32-bit data word from the remote //! CPU //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU address to read from //! \param pvData is a pointer to the 16/32-bit variable where read data will //! be stored. //! \param usLength designates 16- or 32-bit read (1 = 16-bit, 2 = 32-bit) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! \param ulResponseFlag indicates the remote CPU to the local CPU Flag //! number mask used to report when the read data is available at pvData. //! (\e ulResponseFlag MUST use IPC flags 17-32, and not 1-16) //! //! This function will allow the local CPU system to send a 16/32-bit data //! read command to the remote CPU system and set a ResponseFlag to track the //! status of the read. //! The remote CPU will respond with a DataWrite command which will place //! the data in the local CPU address pointed to by \e pvData. When the local //! CPU receives the DataWrite command and writes the read data into \e *pvData location, //! it will clear the ResponseFlag, indicating to the rest of the system that //! the data is ready. The \e usLength parameter can be one of the //! following values: \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e //! bBlock parameter can be one of the following values: \b ENABLE_BLOCKING or //! \b DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRDataRead (volatile tIpcController *psController, uint32_t ulAddress, void *pvData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag) { uint16_t status; tIpcMessage sMessage; // // Set up read command, address, dataw1 = ResponseFlag | word length, // dataw2 = address where word // should be written to when returned. // sMessage.ulcommand = IPC_DATA_READ; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000)|(uint32_t)usLength; sMessage.uldataw2 = (uint32_t)pvData; // // Set ResponseFlag (cleared once data is read into address at pvData) // Put Message into PutBuffer and set IPC INT flag // IpcRegs.IPCSET.all = (ulResponseFlag & 0xFFFF0000); status = IpcPut (psController, &sMessage, bBlock); return status; // //Note: Read Response will have sMessage.ulcommand = IPC_DATA_WRITE // sMessage.uladdress = (uint32_t) pvData // sMessage.uldataw1 = ulStatusFlag | // (uint32_t) usLength; // sMessage.uldataw2 = word to be read into // pvData address. // } //***************************************************************************** // //! Sends the command to read either a 16- or 32-bit data word from remote //! CPU system address to a write-protected local CPU address. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU address to read from //! \param pvData is a pointer to the 16/32-bit variable where read data will //! be stored. //! \param usLength designates 16- or 32-bit read (1 = 16-bit, 2 = 32-bit) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! \param ulResponseFlag indicates the local CPU to remote CPU Flag number //! mask used to report when the read data is available at pvData. //! (\e ulResponseFlag MUST use IPC flags 17-32, and not 1-16) //! //! This function will allow the local CPU system to send a 16/32-bit data //! read command to the remote CPU system and set a ResponseFlag to track the //! status of the read. //! The remote CPU system will respond with a DataWrite command which will //! place the data in the local CPU address pointed to by \e pvData. //! When the local CPU receives the DataWrite command and writes the read data //! into \e *pvData location, it will clear the ResponseFlag, indicating to //! the rest of the system that the data is ready. The \e usLength parameter //! can be one of the following values: \b IPC_LENGTH_16_BITS or //! \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be one of the following //! values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRDataRead_Protected (volatile tIpcController *psController, uint32_t ulAddress, void *pvData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag) { uint16_t status; tIpcMessage sMessage; // // Set up read command, address, dataw1 = ResponseFlag | word length, dataw2 // = address where word should be written to when returned. // sMessage.ulcommand = IPC_DATA_READ_PROTECTED; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000)|(uint32_t)usLength; sMessage.uldataw2 = (uint32_t)pvData; // // Set ResponseFlag (cleared once data is read into address at pvData) // Put Message into PutBuffer and set IPC INT flag // IpcRegs.IPCSET.all = (ulResponseFlag & 0xFFFF0000); status = IpcPut (psController, &sMessage, bBlock); return status; // // Note: Read Response will have sMessage.ulcommand = IPC_DATA_WRITE // sMessage.uladdress = (uint32_t) pvData // sMessage.uldataw1 = ulStatusFlag | // (uint32_t) usLength; // sMessage.uldataw2 = word to be read into // pvData address. // } //***************************************************************************** // //! Sets the designated bits in a 16-bit data word at the remote CPU system //! address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU address to write to //! \param ulMask specifies the 16/32-bit mask for bits which should be set at //! \e ulAddress. //! 16-bit masks should fill the lower 16-bits (upper 16-bits will be all //! 0x0000). //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to set bits specified by the //! \e ulMask variable in a 16/32-bit word on the remote CPU system. The \e //! usLength parameter can be one of the following values: \b IPC_LENGTH_16_BITS //! or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be one of the //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRSetBits(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulMask, uint16_t usLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up set bits command, address, dataw1 = word length, dataw2 = // 16/32-bit mask // sMessage.ulcommand = IPC_SET_BITS; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (uint32_t)usLength; sMessage.uldataw2 = ulMask; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Sets the designated bits in a 16-bit write-protected data word at the //! remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU address to write to //! \param ulMask specifies the 16/32-bit mask for bits which should be set at //! \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits //! will be all 0x0000). //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to set bits specified by the //! \e ulMask variable in a write-protected 16/32-bit word on the remote CPU //! system. The \e usLength parameter can be one of the following values: \b //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be //! one of the following values: //! \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRSetBits_Protected(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulMask, uint16_t usLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up set bits command, address, dataw1 = word length, dataw2 = // 16/32-bit mask // sMessage.ulcommand = IPC_SET_BITS_PROTECTED; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (uint32_t)usLength; sMessage.uldataw2 = ulMask; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Clears the designated bits in a 16-bit data word at the remote CPU system //! address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU address to write to //! \param ulMask specifies the 16/32-bit mask for bits which should be cleared //! at \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits //! will be all 0x0000). //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to clear bits specified by //! the \e ulMask variable in a 16/32-bit word on the remote CPU system. The \e //! usLength parameter can be one of the following values: \b //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRClearBits(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulMask, uint16_t usLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up clear bits command, address, dataw1 = word length, dataw2 = // 16/32-bit mask // sMessage.ulcommand = IPC_CLEAR_BITS; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (uint32_t)usLength; sMessage.uldataw2 = ulMask; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Clears the designated bits in a 16-bit write-protected data word at //! remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the secondary CPU address to write to //! \param ulMask specifies the 16/32-bit mask for bits which should be cleared //! at \e ulAddress. 16-bit masks should fill the lower 16-bits (upper 16-bits //! will be all 0x0000). //! \param usLength specifies the length of the bit mask (1=16-bits, 2=32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to set bits specified by the //! \e ulMask variable in a write-protected 16/32-bit word on the remote CPU //! system. The \e usLength parameter can be one of the following values: \b //! IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter can be //! one of the following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRClearBits_Protected(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulMask, uint16_t usLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up clear bits command, address, dataw1 = word length, dataw2 = // 16/32-bit mask // sMessage.ulcommand = IPC_CLEAR_BITS_PROTECTED; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (uint32_t)usLength; sMessage.uldataw2 = ulMask; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Writes a 16/32-bit data word to the remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote cpu address to write to //! \param ulData specifies the 16/32-bit word which will be written. //! For 16-bit words, only the lower 16-bits of ulData will be considered by //! the master system. //! \param usLength is the length of the word to write (1 = 16-bits, 2 = //! 32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! \param ulResponseFlag is used to pass the \e ulResponseFlag back to the //! remote cpu only when this function is called in response to \e //! IPCMtoCDataRead(). Otherwise, set to 0. //! //! This function will allow the local CPU system to write a 16/32-bit word //! via the \e ulData variable to an address on the remote CPU system. //! The \e usLength parameter can be one of the following values: //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter //! can be one of the following values: \b ENABLE_BLOCKING or \b //! DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRDataWrite(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag) { uint16_t status; tIpcMessage sMessage; // // Set up write command, address, dataw1 = ResponseFlag | word length, // dataw2 = data to write // sMessage.ulcommand = IPC_DATA_WRITE; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ulResponseFlag |(uint32_t)usLength; sMessage.uldataw2 = ulData; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Writes a 16/32-bit data word to a write-protected remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the write-protected remote CPU address to //! write to //! \param ulData specifies the 16/32-bit word which will be written. For //! 16-bit words, only the lower 16-bits of ulData will be considered by the //! master system. //! \param usLength is the length of the word to write (1 = 16-bits, 2 = //! 32-bits) //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! \param ulResponseFlag is used to pass the \e ulResponseFlag back to the //! remote CPU only when this function is called in response to \e //! IPCMtoCDataRead(). Otherwise, set to 0. //! //! This function will allow the local CPU system to write a 16/32-bit word //! via the \e ulData variable to a write-protected address on the remote CPU //! system. The \e usLength parameter can be one of the following values: //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter //! can be one of the following values: \b ENABLE_BLOCKING or \b //! DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - //! \b IPC_FLAG31 or \b NO_FLAG. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRDataWrite_Protected(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag) { uint16_t status; tIpcMessage sMessage; // // Set up write command, address, dataw1 = ResponseFlag | word length, // dataw2 = data to write // sMessage.ulcommand = IPC_DATA_WRITE_PROTECTED; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ulResponseFlag |(uint32_t)usLength; sMessage.uldataw2 = ulData; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Sends the command to read a block of data from remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU memory block starting address //! to read from. //! \param ulShareAddress specifies the local CPU shared memory address the //! read block will read to. //! \param usLength designates the block size in 16-bit words. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! \param ulResponseFlag indicates the local CPU to remote CPU Flag number //! mask used to report when the read block data is available starting at //! /e ulShareAddress. (\e ulResponseFlag MUST use IPC flags 17-32, and not //! 1-16) //! //! This function will allow the local CPU system to send a read block //! command to the remote CPU system and set a ResponseFlag to track the status //! of the read. The remote CPU system will process the read and place the data //! in shared memory at the location specified in the \e ulShareAddress //! parameter and then clear the ResponseFlag, indicating that the block is //! ready. The \e bBlock parameter can be one of the following values: \b //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. The \e ulResponseFlag parameter can //! be any single one of the flags \b IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRBlockRead(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulShareAddress, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag) { uint16_t status; tIpcMessage sMessage; // // Set up block read command, address, dataw1 = ResponseFlag | block length, // dataw2 = remote CPU address in shared memory // where block data should be read to // (corresponding to local CPU ulShareAddress). // sMessage.ulcommand = IPC_BLOCK_READ; sMessage.uladdress = ulAddress; sMessage.uldataw1 = (ulResponseFlag & 0xFFFF0000) |(uint32_t)usLength; sMessage.uldataw2 = ulShareAddress; // // Set ResponseFlag (cleared once data is read into Share Address location) // Put Message into PutBuffer and set IPC INT flag // IpcRegs.IPCSET.all = (ulResponseFlag & 0xFFFF0000); status = IpcPut (psController, &sMessage, bBlock); return status; // // Note: Read Block Response will occur in processing of ReadBlock (since // remote CPU has access to shared memory) // } //***************************************************************************** // //! Writes a block of data to remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU memory block starting address //! to write to. //! \param ulShareAddress specifies the local CPU shared memory address where //! data to write from resides. //! \param usLength designates the block size in 16- or 32-bit words (depends //! on \e usWordLength). //! \param usWordLength designates the word size (16-bits = 1 or 32-bits = 2). //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to write a block of data to //! the remote CPU system starting from the location specified by the //! \e ulAdress parameter. Prior to calling this function, the local CPU //! system code should place the data to write in shared memory starting at /e //! ulShareAddress. //! The \e usWordLength parameter can be one of the following values: //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter //! can be one of the following values: \b ENABLE_BLOCKING or \b //! DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \note If the shared SARAM blocks are used to pass the RAM block between the //! processors, the IPCReqMemAccess() function must be called first in order to //! give the slave CPU write access to the shared memory block(s). //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRBlockWrite(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulShareAddress, uint16_t usLength, uint16_t usWordLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up block write command, address, dataw1 = block length, // dataw2 = remote CPU shared mem address // where write data resides // sMessage.ulcommand = IPC_BLOCK_WRITE; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ((uint32_t)(usWordLength)<<16) + (uint32_t)usLength; sMessage.uldataw2 = ulShareAddress; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Writes a block of data to a write-protected remote CPU system address //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the write-protected remote CPU block starting //! address to write to. //! \param ulShareAddress specifies the local CPU shared memory address where //! data to write from resides. //! \param usLength designates the block size in 16- or 32-bit words (depends //! on \e usWordLength). //! \param usWordLength designates the word size (16-bits = 1 or 32-bits = 2). //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to write a block of data to //! a write-protected region on the remote CPU system starting from the //! location specified by the \e ulAdress parameter. Prior to calling this //! function, the local CPU system code should place the data to write in //! shared memory starting at /e ulShareAddress. //! The \e usWordLength parameter can be one of the following values: //! \b IPC_LENGTH_16_BITS or \b IPC_LENGTH_32_BITS. The \e bBlock parameter //! can be one of the following values: \b ENABLE_BLOCKING or \b //! DISABLE_BLOCKING. //! The \e ulResponseFlag parameter can be any single one of the flags \b //! IPC_FLAG16 - \b IPC_FLAG31 or \b NO_FLAG. //! //! \note If the shared SARAM blocks are used to pass the RAM block between the //! processors, the IPCReqMemAccess() function must be called first in order to //! give the the slave CPU write access to the shared memory block(s). //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRBlockWrite_Protected(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulShareAddress, uint16_t usLength, uint16_t usWordLength, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up block write command, address, dataw1 = block length, // dataw2 = remote CPU shared mem address // where write data resides // sMessage.ulcommand = IPC_BLOCK_WRITE_PROTECTED; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ((uint32_t)(usWordLength)<<16) + (uint32_t)usLength; sMessage.uldataw2 = ulShareAddress; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Calls remote CPU function with 1 optional parameter . //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulAddress specifies the remote CPU function address //! \param ulParam specifies the 32-bit optional parameter value. If not used, //! this can be a dummy value. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to call a function on the //! remote CPU. The \e ulParam variable is a single optional 32-bit parameter //! to pass to the function. The \e bBlock parameter can be one of the //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRFunctionCall(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulParam, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Set up function call command, address, dataw1 = 32-bit parameter // sMessage.ulcommand = IPC_FUNC_CALL; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ulParam; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } //***************************************************************************** // //! Sends generic message to remote CPU system //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulCommand specifies 32-bit command word to insert into message. //! \param ulAddress specifies 32-bit address word to insert into message. //! \param ulDataW1 specifies 1st 32-bit data word to insert into message. //! \param ulDataW2 specifies 2nd 32-bit data word to insert into message. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the local CPU system to send a generic message to //! the remote CPU system. Note that the user should create a corresponding //! function on the remote CPU side to interpret/use the message or fill //! parameters in such a way that the existing IPC drivers can recognize the //! command and properly process the message. //! The \e bBlock parameter can be one of the following values: \b //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCLtoRSendMessage(volatile tIpcController *psController, uint32_t ulCommand, uint32_t ulAddress, uint32_t ulDataW1, uint32_t ulDataW2, uint16_t bBlock) { uint16_t status; tIpcMessage sMessage; // // Package message to send // sMessage.ulcommand = ulCommand; sMessage.uladdress = ulAddress; sMessage.uldataw1 = ulDataW1; sMessage.uldataw2 = ulDataW2; // // Put Message into PutBuffer and set IPC INT flag // status = IpcPut (psController, &sMessage, bBlock); return status; } #if defined (CPU2) //***************************************************************************** // //! Slave CPU Configures master R/W/Exe Access to Shared SARAM. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param ulMask specifies the 32-bit mask for the GSxMSEL RAM control //! register to indicate which GSx SARAM blocks the slave CPU is requesting //! master access to. //! \param usMaster specifies whether the CPU1 or CPU2 are given //! master access to the GSx blocks. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the slave CPU system to configure master R/W/Exe //! access to the GSx SARAM blocks specified by the /e ulMask parameter. The //! function calls the \e IPCSetBits_Protected() or \e //! IPCClearBits_Protected() functions, and therefore in the master CPU //! application code, the corresponding functions should be called. //! The \e bBlock parameter can be one of the following values: \b //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. The \e usMaster parameter can be //! either: \b IPC_GSX_CPU2_MASTER or \b IPC_GSX_CPU1_MASTER. The \e ulMask //! parameter can be any of the options: \b S0_ACCESS - \b S7_ACCESS. //! //! \return status of command (\b STATUS_PASS =success, \b STATUS_FAIL = error //! because PutBuffer was full, command was not sent) // //***************************************************************************** uint16_t IPCReqMemAccess (volatile tIpcController *psController, uint32_t ulMask, uint16_t usMaster, uint16_t bBlock) { uint16_t status = STATUS_PASS; uint32_t GSxMSEL_REGaddress = (uint32_t)(&MemCfgRegs.GSxMSEL.all); if (usMaster == IPC_GSX_CPU2_MASTER) { if ((MemCfgRegs.GSxMSEL.all & ulMask) != ulMask) { status = IPCLtoRSetBits_Protected (psController, GSxMSEL_REGaddress, ulMask, IPC_LENGTH_32_BITS, bBlock); } } else if (usMaster == IPC_GSX_CPU1_MASTER) { if ((MemCfgRegs.GSxMSEL.all & ulMask) != 0) { status = IPCLtoRClearBits_Protected (psController, GSxMSEL_REGaddress, ulMask, IPC_LENGTH_32_BITS, bBlock); } } return status; } #endif //***************************************************************************** // //! Responds to 16/32-bit data word write command the remote CPU system //! //! \param psMessage specifies the pointer to the message received from remote //! CPU system which includes the 16/32-bit data word to write to the local CPU //! address. //! //! This function will allow the local CPU system to write a 16/32-bit word //! received from the remote CPU system to the address indicated in \e //! *psMessage. In the event that the IPC_DATA_WRITE command was received as a //! result of an IPC_DATA_READ command, this function will also clear the IPC //! response flag tracking the read so other threads in the local CPU system //! will be aware that the data is ready. //! //! \return None. // //***************************************************************************** void IPCRtoLDataWrite(tIpcMessage *psMessage) { // // Data word length = dataw1 (15:0), responseFlag = valid only for IPC // flags 17-32 // uint16_t length = (uint16_t) psMessage->uldataw1; uint32_t responseFlag = (psMessage->uldataw1) & 0xFFFF0000; // // Write 16/32-bit word to address // if (length == IPC_LENGTH_16_BITS) { *(uint16_t *)(psMessage->uladdress) = (uint16_t)psMessage->uldataw2; } else if (length == IPC_LENGTH_32_BITS) { *(uint32_t *)(psMessage->uladdress) = psMessage->uldataw2; } // // If data write command is in response to a data read command from remote // CPU to local CPU clear ResponseFlag, indicating read data from remote // CPU is ready. // IpcRegs.IPCCLR.all = responseFlag; } //***************************************************************************** // //! Responds to 16/32-bit write-protected data word write command from //! secondary CPU system //! //! \param psMessage specifies the pointer to the message received from the //! secondary CPU system which includes the 16/32-bit data word to write to the //! local CPU address. //! //! This function will allow the local CPU system to write a 16/32-bit word //! received from the secondary CPU system to the write-protected address //! indicated in \e *psMessage. //! In the event that the IPC_DATA_WRITE_PROTECTED command was received as a //! result of an IPC_DATA_READ_PROTECTED command, this function will also clear //! the IPC response flag tracking the read so other threads in the local CPU //! will be aware that the data is ready. //! //! \return None. // //***************************************************************************** void IPCRtoLDataWrite_Protected(tIpcMessage *psMessage) { // // Data word length = dataw1 (15:0), responseFlag = valid only for IPC // flags 17-32 // uint16_t length = (uint16_t) psMessage->uldataw1; uint32_t responseFlag = (psMessage->uldataw1) & 0xFFFF0000; // // Allow access to EALLOW-protected registers. // EALLOW; // // Write 16/32-bit word to EALLOW-protected address // if (length == IPC_LENGTH_16_BITS) { *(uint16_t *)(psMessage->uladdress) = (uint16_t)psMessage->uldataw2; } else if (length == IPC_LENGTH_32_BITS) { *(uint32_t *)(psMessage->uladdress) = psMessage->uldataw2; } // // Disable access to EALLOW-protected registers. // EDIS; // // If data write command is in response to a data read command from local // CPU to remote CPU, clear ResponseFlag, indicating read data from // secondary CPU is ready // IpcRegs.IPCCLR.all = responseFlag; } //***************************************************************************** // //! Responds to 16/32-bit data word read command from remote CPU system. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the remote CPU system to read a 16/32-bit data //! word at the local CPU address specified in /e psMessage, and send a Write //! command with the read data back to the local CPU system. It will also send //! the Response Flag used to track the read back to the remote CPU. //! The \e bBlock parameter can be one of the following values: \b //! ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return None. // //***************************************************************************** void IPCRtoLDataRead(volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock) { unsigned long ulReaddata; uint16_t usLength; // // If data word length = 16-bits, read the 16-bit value at the given // address and cast as 32-bit word to send back to remote CPU. // If data word length = 32-bits, read the 32-bit value at the given // address. // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { ulReaddata = (unsigned long)(*(volatile uint16_t *)psMessage->uladdress); } else if (usLength == IPC_LENGTH_32_BITS) { ulReaddata = *(unsigned long *)psMessage->uladdress; } // // Send a Write command to write the requested data to the remote CPU read // into address. // psMessage->uldataw2 contains remote CPU address where readdata will be // written. // psMessage->uldataw1 contains the read response flag in IPC flag 17-32. // IPCLtoRDataWrite(psController, psMessage->uldataw2, ulReaddata, usLength, bBlock,(psMessage->uldataw1 & 0xFFFF0000)); } //***************************************************************************** // //! Responds to 16/32-bit data word read command from remote CPU system. //! to read into a write-protected word on the remote CPU system. //! //! \param psController specifies the address of a \e tIpcController instance //! used to store information about the "Put" and "Get" circular buffers and //! their respective indexes. //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! \param bBlock specifies whether to allow function to block until PutBuffer //! has a slot (1= wait until slot free, 0 = exit with STATUS_FAIL if no slot). //! //! This function will allow the remote CPU system to read a 16/32-bit data //! word at the local CPU address specified in /e psMessage, and send a Write //! Protected command with the read data back to the remote CPU system at a //! write protected address. It will also send the Response Flag used to track //! the read back to the remote CPU. The \e bBlock parameter can be one of the //! following values: \b ENABLE_BLOCKING or \b DISABLE_BLOCKING. //! //! \return None. // //***************************************************************************** void IPCRtoLDataRead_Protected(volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock) { unsigned long ulReaddata; uint16_t usLength; // // If data word length = 16-bits, read the 16-bit value at the given // address and cast as 32-bit word to send back to remote CPU. // If data word length = 32-bits, read the 32-bit value at the given // address. // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { ulReaddata = (unsigned long)(*(volatile uint16_t *)psMessage->uladdress); } else if (usLength == IPC_LENGTH_32_BITS) { ulReaddata = *(unsigned long *)psMessage->uladdress; } // // Send a Write command to write the requested data to the remote CPU read // into address. // psMessage->uldataw2 contains remote CPU address where readdata will be // written. // psMessage->uldataw1 contains the read response flag in IPC flag 17-32. // IPCLtoRDataWrite_Protected(psController, psMessage->uldataw2, ulReaddata, usLength, bBlock, (psMessage->uldataw1 & 0xFFFF0000)); } //***************************************************************************** // //! Sets the designated bits in a 16/32-bit data word at a local CPU system //! address //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will allow the remote CPU system to set the bits in a //! 16/32-bit word on the local CPU system via a local CPU address and mask //! passed in via the \e psMessage. //! //! \return None. // //***************************************************************************** void IPCRtoLSetBits(tIpcMessage *psMessage) { uint16_t usLength; // // Determine length of word at psMessage->uladdress and then set bits based // on either the 16-bit or 32-bit bit-mask in psMessage->uldataw2. // (16-bit length ignores upper 16-bits of psMessage->uldataw2) // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { *(volatile uint16_t*)psMessage->uladdress |= (uint16_t) psMessage->uldataw2; } else if (usLength == IPC_LENGTH_32_BITS) { *(volatile unsigned long *)psMessage->uladdress |= psMessage->uldataw2; } } //***************************************************************************** // //! Sets the designated bits in a 16/32-bit write-protected data word at a //! local CPU system address //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will allow the remote CPU system to set the bits in a write- //! protected 16/32-bit word on the local CPU system via a local CPU address //! and mask passed in via the \e psMessage. //! //! \return None // //***************************************************************************** void IPCRtoLSetBits_Protected(tIpcMessage *psMessage) { uint16_t usLength; // // Allow access to EALLOW-protected registers. // EALLOW; // // Determine length of word at psMessage->uladdress and then set bits based // on either the 16-bit or 32-bit bit-mask in psMessage->uldataw2. // (16-bit length ignores upper 16-bits of psMessage->uldataw2) // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { *(volatile uint16_t*)psMessage->uladdress |= (uint16_t) psMessage->uldataw2; } else if (usLength == IPC_LENGTH_32_BITS) { *(volatile unsigned long *)psMessage->uladdress |= psMessage->uldataw2; } // // Disable access to EALLOW-protected registers. // EDIS; } //***************************************************************************** // //! Clears the designated bits in a 32-bit data word at a local CPU system //! address //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will allow the remote CPU system to clear the bits in a //! 16/32-bit word on the local CPU system via a local CPU address and mask //! passed in via the \e psMessage. //! //! \return None. // //***************************************************************************** void IPCRtoLClearBits(tIpcMessage *psMessage) { uint16_t usLength; // // Determine length of word at psMessage->uladdress and then clear bits // based on // either the 16-bit or 32-bit bit-mask in psMessage->uldataw2. // (16-bit length ignores upper 16-bits of psMessage->uldataw2) // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { *(volatile uint16_t*)psMessage->uladdress &= ~((uint16_t) psMessage->uldataw2); } else if (usLength == IPC_LENGTH_32_BITS) { *(volatile unsigned long *)psMessage->uladdress &= ~(psMessage->uldataw2); } } //***************************************************************************** // //! Clears the designated bits in a write-protected 16/32-bit data word at a //! local CPU system address //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will allow the secondary CPU system to clear the bits in a //! 16/32-bit write-protected word on the local CPU system via a local //! CPU address and mask passed in via the \e psMessage. //! //! \return None. // //***************************************************************************** void IPCRtoLClearBits_Protected(tIpcMessage *psMessage) { uint16_t usLength; // // Allow access to EALLOW-protected registers. // EALLOW; // // Determine length of word at psMessage->uladdress and then clear bits // based on // either the 16-bit or 32-bit bit-mask in psMessage->uldataw2. // (16-bit length ignores upper 16-bits of psMessage->uldataw2) // usLength = (uint16_t)psMessage->uldataw1; if (usLength == IPC_LENGTH_16_BITS) { *(volatile uint16_t*)psMessage->uladdress &= ~((uint16_t) psMessage->uldataw2); } else if (usLength == IPC_LENGTH_32_BITS) { *(volatile unsigned long *)psMessage->uladdress &= ~(psMessage->uldataw2); } // // Disable access to EALLOW-protected registers. // EDIS; } //***************************************************************************** // //! Reads a block of data from a remote CPU system address and stores into //! shared RAM //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will respond to the remote CPU system request to read a block //! of data from the local control system, by reading the data and placing that //! data into the shared RAM location specified in \e psMessage. //! //! \return None. // //***************************************************************************** void IPCRtoLBlockRead(tIpcMessage *psMessage) { uint16_t usLength; volatile uint16_t* pusRAddress; volatile uint16_t* pusWAddress; uint16_t usIndex; pusRAddress = (volatile uint16_t *)psMessage->uladdress; pusWAddress = (volatile uint16_t *)psMessage->uldataw2; usLength = (uint16_t)psMessage->uldataw1; for (usIndex=0; usIndexuldataw1 & 0xFFFF0000); } //***************************************************************************** // //! Writes a block of data to a local CPU system address from shared RAM //! //! \param psMessage specifies the pointer to the message received from the //! remote CPU system. //! //! This function will write a block of data to an address on the local CPU //! system. //! The data is first written by the remote CPU to shared RAM. This function //! reads the shared RAM location, word size (16- or 32-bit), and block size //! from \e psMessage and writes the block to the local address specified //! in \e psMessage. //! //! \return None. // //***************************************************************************** void IPCRtoLBlockWrite(tIpcMessage *psMessage) { uint16_t usLength; uint16_t usWLength; uint16_t usIndex; usLength = (uint16_t)psMessage->uldataw1; usWLength = (uint16_t)((psMessage->uldataw1)>>16); // // Determine data word access size to write to data block. // if (usWLength == IPC_LENGTH_16_BITS) { volatile uint16_t *pusWAddress = (volatile uint16_t *)psMessage->uladdress; volatile uint16_t *pusRAddress = (volatile uint16_t *)psMessage->uldataw2; for (usIndex=0; usIndexuladdress; volatile unsigned long *pulRAddress = (volatile unsigned long *)psMessage->uldataw2; for (usIndex=0; usIndexuldataw1; usWLength = (uint16_t)((psMessage->uldataw1)>>16); // // Determine data word access size to write to data block. // (Writes registers accessible via APB bus must be 32-bits wide) // if (usWLength == IPC_LENGTH_16_BITS) { volatile uint16_t *pusWAddress = (volatile uint16_t *)psMessage->uladdress; volatile uint16_t *pusRAddress = (volatile uint16_t *)psMessage->uldataw2; for (usIndex=0; usIndexuladdress; volatile unsigned long *pulRAddress = (volatile unsigned long *)psMessage->uldataw2; for (usIndex=0; usIndexuladdress; func_call(psMessage->uldataw1); } //***************************************************************************** // Close the Doxygen group. //! @} //*****************************************************************************