文章目录
开发环境
IDE:CCS 12.3.0.00005
例程获取来源:controlSuite
使用感觉
觉得官方的例程有点抽象,用了全局变量做句柄来被2个CPU都访问
IPC通信协议
寄存器描述
事件有关
支持通过中断和寄存器轮询进行基于事件的通信。
发送
CPUx可以通过写入其IPCSET
寄存器的32位中的任何一位来引发IPC事件。这将在CPUx-IPCFLG
寄存器和CPUy-IPCSTS
寄存器中设置相应的位。
响应
CPUy可以通过在其IPCACK
寄存器中设置适当的位来发出对事件的响应信号。这将清除CPUx-IPCFLG
寄存器和CPUy-IPCSTS
寄存器中的相应位。
取消
如果CPUx需要取消事件,它可以在IPCCLR
寄存器中设置适当的位。这与CPUy写入IPCACK
具有相同的效果。
触发远程中断
0–3(通过IPCSET[3:0]设置)激发远程CPU的中断。远程CPU必须正确配置其ePIE模块才能接收IPC中断。标志4–31(通过IPCSET[31:4]设置)不会产生中断。可以同时设置、确认和清除多个标志。
数据有关
命令寄存器支持发送多条不同的信息。它们被命名为COM
、ADDR
、DATA
和REPLY
,只是为了方便起见,并且可以保存应用程序需要的任何数据。
发送
CPUx可以将数据写入其IPCSENDCOM
、IPCSENDADDR
和IPCSENDDATA
寄存器。
接收
CPUy在其IPCRECVCOM
、IPCRECVADDR
和IPCRECVDATA
寄存器中接收这些。
响应
CPUy可以通过写入其IPCLOCALLREPLY
寄存器来进行响应。CPUx在其IPCREMOTEREPLY
寄存器中接收此数据
IPC BOOT
有一对类似命令的寄存器,可用于引导时IPC或任何其他方便的用途——IPCBOOTMODE和IPCBOOTSTS。两个CPU都可以读取这些寄存器。CPUx只能写入IPCBOOTMODE,CPUy只能写入IPCBOOTSTS。
共享存储器
有两个共享存储器,用于在CPU之间传递大量数据。每个CPU具有用于发送数据的可写存储器和用于接收数据的只读存储器。
使用示例
以下是如何将这些功能结合使用的示例。CPUx需要来自CPUy的LS RAM的一些数据。数据位于CPUy地址0x9400,长度为0x80 16位字。该协议可以这样实现:
- CPUx将0x1写入IPCSENDCOM,在软件中定义为“从地址复制数据”。它将地址(0x9400)写入IPCSENDADDR,将数据长度(0x80)写入IPCSENDDATA。
- CPUx写入IPCSET[3]和IPCSET[16]。这里,IPC标志3被配置为发送中断,并且IPCSET[16]在软件中被定义为指示传入命令。CPUx开始轮询IPCFLG[3]是否变低。
- CPUy接收中断。在中断处理程序中,它检查IPCSTS,发现标志16已设置,并运行命令处理器。
- CPUy从IPCRECVCOM读取命令(0x1),从IPCRECVADDR读取地址(0x9400),从IPC RECVDATA读取数据长度(0x80)。CPUy然后从偏移0x210开始将LS RAM数据复制到其可写共享存储器中的空白空间。
- CPUy将共享内存地址(0x210)写入其IPCLOCALREPLY寄存器。然后,它写入IPCACK[16]和IPCACK[3]以清除标志并指示命令完成。CPUy的工作完成了。
- CPUx看到IPCFLG[3]变低。它读取IPCREMOTEREPLY以获得复制数据的共享内存偏移量(0x210)
官方F2837xD_IPC_Driver.c分析
描述:
28x API函数,两个CPU都可以用。IPC功能需要使用CPU1至CPU2和CPU2到CPU1 MSG RAM存储圆环缓冲区和索引。命令可以在单个命令上按顺序排队IPC中断通道。对于那些没有可以使用相互依赖的多个IPC中断通道。
此文件中的驱动程序功能仅作为用于应用程序开发的示例函数。由于这些功能的性质以及函数调用,该代码无法效率最大化。
NOTE:
两个CPU都使用此源代码。即CPU1和CPU2 core使用此代码。
活动的调试CPU将被称为本地CPU。
在CPU1中使用此源代码时,术语“local” 术语“remote”CPU将是指CPU2。
在CPU2中使用此源代码时,术语“local” 术语“remote”CPU将是指CPU1。
函数名称中的缩写LtoR和RtoL表示分别从本地到远程和从远程到本地。
结构体变量
tIpcController
typedef struct
{
//! The address of the PutBuffer IPC message (in MSGRAM)
tIpcMessage *psPutBuffer;
//! The IPC INT flag to set when sending messages
//! for this IPC controller instance.
uint32_t ulPutFlag;
//! The address of the PutBuffer Write index (in MSGRAM)
uint16_t *pusPutWriteIndex;
//! The address of the PutBuffer Read index (in MSGRAM)
uint16_t *pusPutReadIndex;
//! The address of the GetBuffer IPC message(in MSGRAM)
tIpcMessage *psGetBuffer;
//! The address of the GetBuffer Write Index (in MSGRAM)
uint16_t *pusGetWriteIndex;
//! The address of the GetBuffer Read Index (in MSGRAM)
uint16_t *pusGetReadIndex;
} tIpcController;
tIpcMessage
brief:
给IPC消息定义的结构。这些字段由IPC驱动程序,用于确定处理器之间传递的数。虽然它们有一个指定的应用场景,但也可以使用一般用于在处理器之间传递32位数据字。
typedef struct
{
//! The command passed between processor systems.
uint32_t ulcommand;
//! The receiving processor address the command is requesting action on.
uint32_t uladdress;
//! A 32-bit variable, the usage of which is determined by ulcommand.
//! The most common usage is to pass length requirements
//! with the upper 16-bits storing a Response Flag for read commands.
uint32_t uldataw1;
//! A 32-bit variable, the usage of which is determined by ulcommand.
//! For block transfers, this variable is generally the address in
//! shared memory used to pass data between processors.
uint32_t uldataw2;
} tIpcMessage;
函数(看懂这些就明白是咋回事了)
IPCInitialize
void IPCInitialize (volatile tIpcController *psController, uint16_t usCPU2IpcInterrupt, uint16_t usCPU1IpcInterrupt)
brief:
初始化Ipc控制结构体,也就是tIpcController
parameter:
psController :
指向结构体变量tIpcController指针`usCPU2IpcInterrupt
当前tIpcController对于CPU2指定的中断号,可以使用以下参数:IPC_INT0, IPC_INT1, IPC_INT2, IPC_INT3.
usCPU1IpcInterrupt
当前tIpcController
对于CPU1指定的中断号,可以使用以下参数:IPC_INT0, IPC_INT1, IPC_INT2, IPC_INT3.
(只有4个中断)
此函数使用循环缓冲区(循环缓冲区用来存放发送的命令,例程里只有4个)初始化IPC驱动程序控制器以及IPC中断对的索引地址。
note: 如果中断当前正由tIpcController
实例使用,该特定中断不应与第二个tIpcController instance
绑定。
return:
void
Example:
volatile tIpcController g_sIpcController1;
IPCInitialize (&g_sIpcController1, IPC_INT0, IPC_INT0);
IPCInitialize (&g_sIpcController2, IPC_INT1, IPC_INT1);
函数
//
// 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;
}
IpcPut
uint16_t IpcPut (volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock)
brief:
将消息写入PutBuffer
parameter:
psController
指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController
实例的地址。psMessage
指定了哪个地址要写入bBlock
是否阻塞 1阻塞 0不阻塞
return:
STATUS_FAIL
if PutBuffer is full
STATUS_PASS
Put successfully
Example:
status = IpcPut (psController, &sMessage, bBlock);
函数
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;
}
IpcGet
uint16_t IpcGet (volatile tIpcController *psController, tIpcMessage *psMessage, uint16_t bBlock)
brief:
从GetBuffer
中获取消息
parameter:
psController
指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController
实例的地址。psMessage
指定了哪个地址要读取bBlock
是否阻塞 1阻塞 0不阻塞 参数选择ENABLE_BLOCKING DISABLE_BLOCKING
return:
STATUS_PASS
GetBuffer为空
STATUS_FAIL
Get成功
Example:
while(IpcGet(&g_sIpcController1, &sMessage,
DISABLE_BLOCKING) != STATUS_FAIL)
{
switch (sMessage.ulcommand)
{
case IPC_DATA_WRITE:
IPCRtoLDataWrite(&sMessage);
break;
default:
ErrorFlag = 1;
break;
}
}
函数
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;
}
IPCLtoRDataWrite
uint16_t IPCLtoRDataWrite(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag)
brief:
将16/32位数据字写入远程CPU的RAM
parameter:
*psController
指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController
实例的地址。ulAddress
指定要写入的远程cpu地址ulData
指定要写入的16/32位字。对于16位字,主系统将只考虑ulData的较低的16位。usLength
: 是要写入的字的长度(1=16位,2=32位)bBlock
指定是否允许函数进行阻塞,直到PutBuffer
有一个插槽(1=等待插槽空闲,0=如果没有插槽则使用STATUS_FAIL
退出)。ulResponseFlag
用于仅当响应IPCMtoCDataRead()
调用此函数时,将ulResponceFlag
传递回远程cpu。否则,请设置为0。
return:
status of command ( STATUS_PASS =success, STATUS_FAIL = error because PutBuffer was full, command was not sent)
Example:
此函数将允许本地CPU系统通过ulData变量将16/32位字写入远程CPU系统上的地址。usLength
参数可以是以下值之一:IPC_LENGTH_16BITS
或IPC_LENGTH_32_BITS
。
bBlock
参数可以是以下值之一: ENABLE_BLOCKING
或DISABLE_BLOCKING
。
ulResponseFlag参数可以是标志 IPC_FLAG16- IPC-FLAG31
或 NO_FLAG
中的任何一个。
//
// 16 and 32-bit Data Writes
// Write 16-bit word to CPU02 16-bit write word variable.
//
IPCLtoRDataWrite(&g_sIpcController1, pulMsgRam[0],(uint32_t)usWWord16,
IPC_LENGTH_16_BITS, ENABLE_BLOCKING,NO_FLAG);
函数
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;
}
IPCLtoRDataRead
uint16_t IPCLtoRDataRead (volatile tIpcController *psController, uint32_t ulAddress,void *pvData, uint16_t usLength, uint16_t bBlock, uint32_t ulResponseFlag)
brief:
发送一个指令去读取远端CPU的16 bit or 32 bit的数据
此功能将允许本地CPU系统向远程CPU系统发送16/32位数据读取命令,并设置ResponseFlag以跟踪读取状态。
parameter:
psController
psController指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController实例的地址。 `ulAddress
要读取的远端CPU地址`pvData
是一个指针,可以读取16/32长度的地址 `usLength
usLength指定16位或32位读取(1=16位,2=32位)参数选择IPC_LENGTH_16_BITS / IPC_LENGTH_32_BITS
bBlock
指定是否允许函数进行阻塞,直到PutBuffer
有一个slot(1=等待空闲 阻塞,0=如果没有插槽则使用STATUS_FAIL退出)参数选择ENABLE_BLOCKING / DISABLE_BLOCKING
ulResponseFlag
表示远程CPU到本地CPU的标志号掩码,用于报告读取数据何时在pvData可用。ulResponseFlag
MUST use IPC flags 17-32, and not 1-16) 参数选择:IPC_FLAG16 - IPC_FLAG31 或者 NO_FLAG
return:
status of command ( STATUS_PASS =success, STATUS_FAIL = error because PutBuffer was full, command was not sent)
Example:
IPCLtoRDataRead(&g_sIpcController1, pulMsgRam[0], &usRWord16,
IPC_LENGTH_16_BITS, ENABLE_BLOCKING,
IPC_FLAG17);
函数
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.
//
}
IPCLtoRSetBits
uint16_t IPCLtoRSetBits(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulMask, uint16_t usLength, uint16_t bBlock)
brief: 将另一个CPU的指定地址变量置为1
parameter:
psController
指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController
实例的地址。ulAddress
指定了哪个地址要置1ulMask
为应设置为的位指定16/32位掩码,16位掩码应填充较低的16位(较高的16位将全部为0x0000)。usLength
specifies the length of the bit mask (1=16-bits, 2=32-bits)bBlock
是否阻塞 1阻塞 0不阻塞 参数选择`ENABLE_BLOCKING DISABLE_BLOCKIN
return:
status of command ( STATUS_PASS =success, STATUS_FAIL = error because PutBuffer was full, command was not sent)
Example:
//
// 16 and 32-bit Data Set Bits
// Set upper 8 bits in 16-bit write word variable location.
//
IPCLtoRSetBits(&g_sIpcController1, pulMsgRam[0],(uint32_t)SETMASK_16BIT,
IPC_LENGTH_16_BITS,ENABLE_BLOCKING);
//
// Set upper 16 bits in 32-bit write word variable location.
//
IPCLtoRSetBits(&g_sIpcController1, pulMsgRam[1], SETMASK_32BIT,
IPC_LENGTH_32_BITS,ENABLE_BLOCKING);
函数
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;
}
IPCLtoRBlockWrite
uint16_t IPCLtoRBlockWrite(volatile tIpcController *psController, uint32_t ulAddress, uint32_t ulShareAddress, uint16_t usLength, uint16_t usWordLength, uint16_t bBlock)
brief: 将另一个CPU的指定地址变量置为1
parameter:
psController
指定用于存储有关“Put”和“Get”循环缓冲区及其各自索引的信息的tIpcController
实例的地址。ulAddress
指定了哪个远端地址要写ulShareAddress
指定要写入的数据所在的本地CPU共享内存地址。usLength
specifies the length of the bit mask (1=16-bits, 2=32-bits)bBlock
是否阻塞 1阻塞 0不阻塞 参数选择`ENABLE_BLOCKING DISABLE_BLOCKIN
return:
status of command ( STATUS_PASS =success, 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;
}
官方例程
描述
此示例测试F2837xD_IPC_Driver.c中提供的所有基本读/写CPU01到CPU02 IPC Driver功能。
CPU01 是主 CPU02是从
CPU01项目向CPU02项目发送命令,然后CPU02项目处理命令。
CPU02项目响应CPU01项目发送的命令。
请注意,IPC INT0和IPC INT1用于本例处理IPC命令。
官方代码思路
数据依托的实例是一个可以被2个CPU都访问到的全局变量,把这点搞懂就很好理解它是怎么传的(我觉得这个方法有点奇奇怪怪的,但是也没打错)
CPU1
- 中断函数remap
CPU02toCPU01IPC0IntHandler
CPU02toCPU01IPC1IntHandler
这里分别用来处理按byte或者按block传输CPU02toCPU01IPC0IntHandler
Byte级数据量CPU02toCPU01IPC1IntHandler
Block级数据量
- 使用
IPCInitialize
初始化全局变量g_sIpcController1
g_sIpcController2
CPU1和CPU2的区别就是buffer不一样,put和get对调
- 启用中断
- 初始化约定好的RAM,其中包括CPU2的
Message RAM
,划分好两边都能共享的RAM区域(GS0SARAM_START) - 准备好写入的变量值
- 16bit 传输 0x1234
- 32bit 传输 0xABCD5678
- 初始化接收 变量
- 等CPU2把被写数据的地址给传过来(目的:就可以由CPU1来决定写哪个数据了)
- 用
IPCLtoRDataWrite
和IPCLtoRDataRead
来写和读的 - 等对方接收玩后来判断写和读的是否准确
- 同理 来验证
IPCRtoLSetBits
函数 - 验证
IPCLtoRBlockWrite
,首先需要把共享RAM给CPU1来使用,接下来也和IPCLtoRDataWrite
一样
11. IPCLtoRFunctionCall
也是类似的,初始化的时候已经获取了另一个CPU提供的可供IPC通讯使用的接口
CPU2
- 初始化这一块和CPU1基本一样,
tIpcController
也用的是同一个变量 - 以下是准备要被CPU1改的变量和响应的函数
- 在主轮询初始化的部分,把CPU2准备要改的变量的地址写入到消息队列
pulMsgRam
中,这块RAM归CPU2读写,CPU1只读
- 写完后通知CPU1好了
IpcRegs.IPCSET.bit.IPC17 = 1;
- 中断函数里响应CPU1发过来的命令,比较简单,不继续展开来写了,点进去看一下就知道是怎么回事了
watch variables
CPU0
name | function |
---|---|
ErrorCount | Counts # of errors |
pusCPU01BufferPt | Stores 256 16-bit words block to write to CPU02 |
pusCPU02BufferPt | Points to beginning of 256 word block received back from CPU02 |
usWWord16 | 16-bit word to write to CPU02 |
ulWWord32 | 32-bit word to write to CPU02 |
usRWord16 | 16-bit word to read from CPU02 |
ulRWord32 | 32-bit word to read from CPU02 |
CPU1
name | function |
---|---|
ErrorFlag | Indicates an unrecognized command was sent from CPU01 to CPU02. |