TI中文支持网
TI专业的中文技术问题搜集分享网站

TMS320F28388D: 关于CPU1和CM之间IPC消息队列通信以及IPC通信问题

Part Number:TMS320F28388D

大家好,

1、我在自建工程代码中在CPU1和CM之间使用IPC消息队列进行通信时遇到一些问题,就是CM通过消息队列发送数据给CPU1时,CPU1能进入IPC中断,但CPU1的GetWriteIndex没有更新

CPU1:

CM是已经发送消息队列了

CM:

CPU1相关代码:

CM:

2、我想问一下,使用IPC非消息队列通信时,在发送端调用IPC_sendCommand函数后是一定要调用IPC_waitForAck等待响应吗?

因为我尝试只调用IPC_sendCommand函数来发送,在接收端能正常进入中断,但会有几率在调用IPC_readCommand函数时无法读出数据,接收端也正常调用了IPC_ackFlagRtoL函数。

Cherry Zhou:

Hi,

我们向工程师确认后给到您答复。

,

Cherry Zhou:

Hi,

第一个问题工程师正在查看中,预计1-2天给到您答复。

关于第二个问题,

TFTMing 说:

2、我想问一下,使用IPC非消息队列通信时,在发送端调用IPC_sendCommand函数后是一定要调用IPC_waitForAck等待响应吗?

因为我尝试只调用IPC_sendCommand函数来发送,在接收端能正常进入中断,但会有几率在调用IPC_readCommand函数时无法读出数据,接收端也正常调用了IPC_ackFlagRtoL函数。

IPC_waitForAck()函数只是等待作为参数传递的 IPC  flag被清除。 如果在没有 IPC_waitForAck ()函数的情况下多次使用 IPC_sendCommand ()函数,那么这个flag可能已经是高电平,因此远程 CPU 并不会看到flag再次变为高电平。

IPC_readCommand()函数在调用时返回 true (1)或 false (0)。 在 IPC_readCommand ()函数未读取预期数据时,您会看到什么?

,

TFTMing:

Cherry Zhou 说:第一个问题工程师正在查看中,预计1-2天给到您答复。

好的,感谢。

Cherry Zhou 说:IPC_waitForAck()函数只是等待作为参数传递的 IPC  flag被清除。 如果在没有 IPC_waitForAck ()函数的情况下多次使用 IPC_sendCommand ()函数,那么这个flag可能已经是高电平,因此远程 CPU 并不会看到flag再次变为高电平。

这个我明白,因为代码中是间隔1ms调用IPC_sendCommand函数一次,所以基本不会重复调用。 

Cherry Zhou 说:IPC_readCommand()函数在调用时返回 true (1)或 false (0)。 在 IPC_readCommand ()函数未读取预期数据时,您会看到什么?

这边读回来的值是1,但读回来的command的值不对。

因为我在CM中使用ECAT和Enet通信,ECAT通过IPC0将数据发送至CPU1,Enet通过IPC1将数据发送至CPU1,IPC0的sendCommand函数是在while循环中调用,IPC1发送函数是在Enet的接收中断中调用,所以我猜测是在执行IPC0发送函数,并在IPC_waitForAck()函数等待时,有Enet的接收中断打断了IPC0的等待,并执行了Enet的IPC1的发送函数,我在CPU1的IPC0中断中读回来的command值是IPC1发送给CPU1的command的值,但IPC0和IPC1是两个不同的中断。

所以不知道为什么会在IPC0中读回来了IPC1的command值,而且这种情况是有概率出现的。

,

Cherry Zhou:

您好,

很抱歉问题1工程师还在查看中,尽快给到您答复。

工程师怀疑是 CCS 中的寄存器视图的问题,并且实际上可能会递增。

请问IPC0和 IPC1都使用 messageQueue 吗? 是否使用了相同的消息队列地址?

,

TFTMing:

Cherry Zhou 说:很抱歉问题1工程师还在查看中,尽快给到您答复。

你好,我已经找到问题了,是CM和CPU1映射到消息RAM的变量不一样导致的。

CM:

// .map
20080000IPC_CM_To_CPU1_GetBuffer20082000cmSend2CPUBuffer20082400cmDatSendBuffer20082414cmObjSendBuffer20082514IPC_CM_To_CPU1_PutBuffer20084000IPC_CM_To_CPU2_GetBuffer20086000IPC_CM_To_CPU2_PutBuffer// .c文件
#pragma DATA_SECTION(cmDatSendBuffer,"MSGRAM_CM_TO_CPU1")
#pragma DATA_SECTION(cmObjSendBuffer,"MSGRAM_CM_TO_CPU1")
#pragma DATA_SECTION(cmSend2CPUBuffer,"MSGRAM_CM_TO_CPU1")uint16_t cmDatSendBuffer[10];
uint32_t cmObjSendBuffer[64];
uint16_tcmSend2CPUBuffer[512];

CPU1:

// .map
000038000IPC_CPU_To_CM_GetBuffer000039000ipcTxBuffer000039180ipcSampleTxBuffer000039300cpu1DatSendBuffer00003930acpu1MonitSendBuffer000039440IPC_CPU_To_CM_PutBuffer00003a000IPC_CPU1_To_CPU2_PutBuffer00003b000IPC_CPU1_To_CPU2_GetBuffer// .c文件
#pragma DATA_SECTION(cpu1DatSendBuffer,"MSGRAM_CPU_TO_CM")
#pragma DATA_SECTION(ipcTxBuffer,"MSGRAM_CPU_TO_CM")
#pragma DATA_SECTION(cpu1MonitSendBuffer,"MSGRAM_CPU_TO_CM")
#pragma DATA_SECTION(ipcSampleTxBuffer,"MSGRAM_CPU_TO_CM")uint16_tipcTxBuffer[384] = {0};uint16_tipcSampleTxBuffer[384];int32_tcpu1MonitSendBuffer[128];

CPU1的IPC_CPU_To_CM_GetBuffer所在MSGRAM的位置和CM的IPC_CM_To_CPU1_PutBuffer所在位置不一样,所以没法正常使用。

所以现在有一个新的问题,如果自己想要在MSGRAM定义变量,怎样才能避免上述这个问题呢?

Cherry Zhou 说:请问IPC0和 IPC1都使用 messageQueue 吗? 是否使用了相同的消息队列地址?

第二个问题没有使用消息队列,使用的是IPC_sendCommand和IPC_readCommand函数

,

Cherry Zhou:

Hi,

能否分享下所有与 IPC 相关的代码?

您是否查看过 ipc_ex2_msgqueue 示例来了解如何处理不同地址的这一问题? 以下屏幕截图来自 IPC_sendMessageToQueue()函数。

您试下修改函数的地址更正部分来适用于特定的地址位置? 

,

TFTMing:

Cherry Zhou 说:能否分享下所有与 IPC 相关的代码?

CM内核发送IPC0函数:

void CMTOCPU1_ipc0SendData(uint32_t dataAddr, uint32_t dataSize, uint32_t command)
{//// Send a message without message queue// Since C28x and CM does not share the same address space for shared RAM,// ADDRESS_CORRECTION is enabled// Length of the data to be read is passed as data.//IPC_sendCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,command, (uint32_t)dataAddr, dataSize);//GPIO_togglePin(mGPIO_PIN_LED5);//// Wait for acknowledgment//IPC_waitForAck(IPC_CM_L_CPU1_R, IPC_FLAG0);}

CM内核while循环发送调用发送函数:

while(1){
//testcount++;
//if(testcount >= 64)if(EcatRev_Flag == 1){SYNC0_Update_Send();EcatRev_Flag = 0;
//testcount = 0;}}

CM:ENET接收函数,IPC1发送Enet接收的数据至CPU1

void udp_rx_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p,struct ip_addr *addr, u16_t port){int i;enet_actualCnt = p->len;enet_totalCnt= p->tot_len;struct pbuf *ptmp = p;if (p != NULL){{for (i = 0; i < enet_actualCnt; i++){cmSend2CPUBuffer[i]=(*((uint8_t *)p->payload + i));}ptmp = p->next;CMTOCPU1_ipc1SendData(cmSend2CPUBuffer, enet_totalCnt, IPC1_CMD_CPU1_READ_MEM);
//memset(&cmDatSendBuffer[0], 0, enet_totalCnt);}enet_remotePort = port;udp_connect(upcb, addr, port); /* connect to the remote host */}// 释放缓冲区数据pbuf_free(p);
}

void CMTOCPU1_ipc1SendData(uint32_t dataAddr, uint32_t dataSize, uint32_t command)
{//// Send a message without message queue// Since C28x and CM does not share the same address space for shared RAM,// ADDRESS_CORRECTION is enabled// Length of the data to be read is passed as data.//IPC_sendCommand(IPC_CM_L_CPU1_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,command, (uint32_t)dataAddr, dataSize);//// Wait for acknowledgment//IPC_waitForAck(IPC_CM_L_CPU1_R, IPC_FLAG1);
}

CPU1的中断IPC0和IPC1接收函数:

__interrupt void CMTOCPU1IPC1_ISR(void)
{uint32_t enet_totalRvCnt;uint32_t command;uint32_t Addr;int i = 0;IPC_readCommand(IPC_CPU1_L_CM_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,&command, &Addr, &enet_totalRvCnt);if(command == IPC1_CMD_CPU1_READ_MEM || command == IPC1_CMD_CM_READ_ARRAY ||command == IPC1_CMD_CM_READ_MONITOR){for(i=0; i<enet_totalRvCnt; i++){*(RevBuffer + i) = *((uint16_t *)Addr + i);}}IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
}__interrupt void CMTOCPU1IPC0_ISR(void)
{uint32_t command;// sig0_updata_sendcommand= CMTOCPU1_ipc0ReadData(cpu1ObjReadBuffer);Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
}uint32_t CMTOCPU1_ipc0ReadData(uint32_t *dataAddr)
{uint32_t command, Addr;uint32_t dataSize;//// Read the command//IPC_readCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,&command, &Addr, &dataSize);if(command == IPC0_CMD_CPU1_ECAT_UPDATE){int i;for(i=0; i<dataSize; i++){*(dataAddr + i) = *((uint32_t *)Addr + i);}}IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG0);return command;
}

Cherry Zhou 说:您试下修改函数的地址更正部分来适用于特定的地址位置? 

这个函数我看了,我不太理解你说的意思,,但 我在cmd文件中通过将IPCMSGRAM的地址重新划分出一个区用来存储用户定义的数组,不知这样可不可行

,

Cherry Zhou:

好的,感谢您提供的信息。

工程师正在查看中,预计1-2天内给到您答复。给您带来的不便敬请谅解!

,

Cherry Zhou:

您好,

我们再确认下您这里的具体问题:

1) 缓冲区索引不会因其消息队列而递增(使用 IPC2)

2) 在 CPU1上读取 IPC0的命令但返回了 IPC1传递的命令

请问问题2)是间歇性发生的,还是每次为 IPC0读取命令时都会发生?

,

TFTMing:

Cherry Zhou 说:1) 缓冲区索引不会因其消息队列而递增(使用 IPC2)

该问题已经找到原因了。

Cherry Zhou 说:请问问题2)是间歇性发生的,还是每次为 IPC0读取命令时都会发生?

是间歇性发生的,IPC0是在CM的while循环上发送至CPU1的,而IPC1是在CM的一个中断中发送的,所以我猜测是IPC0在执行发送并等待CPU1应答过程中,CM的中断触发了IPC1的发送,所以在CPU1的IPC0中断中接收到了IPC1传递的命令,但不清楚为什么会这样。

,

Cherry Zhou:

好的感谢您提供的信息,我们看下给到您答复。

,

Cherry Zhou:

您好,

TFTMing 说:是间歇性发生的,IPC0是在CM的while循环上发送至CPU1的,而IPC1是在CM的一个中断中发送的,所以我猜测是IPC0在执行发送并等待CPU1应答过程中,CM的中断触发了IPC1的发送,所以在CPU1的IPC0中断中接收到了IPC1传递的命令,但不清楚为什么会这样。

通过查看 IPC_sendCommand()函数来我们可以了解这是如何发生的。 该行为应该是在 IPC_sendCommand()函数中断后,在第一个函数完成前使用另一个 IPC_sendCommand()函数时的预期行为。

我们需要再和其他团队讨论下您的问题,看下如何解决。您的系统这边是否可以将以太网中断延迟到 IPC0 sendCommand 功能完成? 您可以先试下。

Thanks

赞(0)
未经允许不得转载:TI中文支持网 » TMS320F28388D: 关于CPU1和CM之间IPC消息队列通信以及IPC通信问题
分享到: 更多 (0)