rt-thread-official/bsp/tms320f28379d/libraries/common/source/F2837xD_Ipc_Driver.c

1703 lines
66 KiB
C

//###########################################################################
//
// 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.
//
//###########################################################################
// $TI Release: F2837xD Support Library v3.05.00.00 $
// $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
// $Copyright:
// Copyright (C) 2013-2018 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; usIndex<usLength; usIndex++)
{
*pusWAddress = *pusRAddress;
pusWAddress += 1;
pusRAddress += 1;
}
IpcRegs.IPCACK.all |= (psMessage->uldataw1 & 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; usIndex<usLength; usIndex++)
{
*pusWAddress = *pusRAddress;
pusWAddress += 1;
pusRAddress += 1;
}
} else if (usWLength == IPC_LENGTH_32_BITS)
{
volatile unsigned long *pulWAddress =
(volatile unsigned long *)psMessage->uladdress;
volatile unsigned long *pulRAddress =
(volatile unsigned long *)psMessage->uldataw2;
for (usIndex=0; usIndex<usLength; usIndex++)
{
*pulWAddress = *pulRAddress;
pulWAddress += 1;
pulRAddress += 1;
}
}
}
//*****************************************************************************
//
//! Writes a block of data to a local CPU system write-protected 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 a write-protected group of
//! addresses 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_Protected(tIpcMessage *psMessage)
{
uint16_t usLength;
uint16_t usWLength;
uint16_t usIndex;
//
// Allow access to EALLOW-protected registers.
//
EALLOW;
usLength = (uint16_t)psMessage->uldataw1;
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; usIndex<usLength; usIndex++)
{
*pusWAddress = *pusRAddress;
pusWAddress += 1;
pusRAddress += 1;
}
} else if (usWLength == IPC_LENGTH_32_BITS)
{
volatile unsigned long *pulWAddress =
(volatile unsigned long *)psMessage->uladdress;
volatile unsigned long *pulRAddress =
(volatile unsigned long *)psMessage->uldataw2;
for (usIndex=0; usIndex<usLength; usIndex++)
{
*pulWAddress = *pulRAddress;
pulWAddress += 1;
pulRAddress += 1;
}
}
//
// Disable access to EALLOW-protected registers.
//
EDIS;
}
//*****************************************************************************
//
//! Calls a local function with a single optional parameter.
//!
//! \param psMessage specifies the pointer to the message received from the
//! remote CPU system.
//!
//! This function will allow the remote CPU system to call a local CPU function
//! with a single optional parameter. There is no return value from the
//! executed function.
//!
//! \return None.
//
//*****************************************************************************
void
IPCRtoLFunctionCall(tIpcMessage *psMessage)
{
//
// Executes function call with parameter at given address.
//
tfIpcFuncCall func_call = (tfIpcFuncCall)psMessage->uladdress;
func_call(psMessage->uldataw1);
}
//*****************************************************************************
// Close the Doxygen group.
//! @}
//*****************************************************************************