This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28388D: 关于CM4到CPU1使用 IPC 消息队列时无法进入中断的问题

Part Number: TMS320F28388D

大家好,

我在使用IPC进行CM4到CPU1通信时遇到一些问题,我使用下面帖子回答的用例进行修改

https://e2echina.ti.com/support/microcontrollers/c2000/f/c2000-microcontrollers-forum/272839/tms320f28388d-c28xcpu1-cm4-ipc

原代码内容:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//#############################################################################
//
// FILE: ipc_ex2_msgqueue_cm.c
//
// TITLE: IPC example with interrupt and message queue
//
//! \addtogroup driver_cm_c28x_dual_example_list
//! <h1> IPC message passing example with interrupt and message queue </h1>
//!
//! This example demonstrates how to configure IPC and pass information from
//! C28x to CM core with message queues.
//! It is recommended to run the C28x1 core first, followed by the CM core.
//!
//! \b External \b Connections \n
//! - None.
//!
//! \b Watch \b Variables \n
//! - None.
//!
//
//#############################################################################
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//#############################################################################
//
// FILE: ipc_ex2_msgqueue_c28x1.c
//
// TITLE: IPC example with interrupt and message queue
//
//! \addtogroup driver_cm_c28x_dual_example_list
//! <h1> IPC message passing example with interrupt and message queue </h1>
//!
//! This example demonstrates how to configure IPC and pass information from
//! C28x to CM core with message queues.
//! It is recommended to run the C28x1 core first, followed by the CM core.
//!
//! \b External \b Connections \n
//! - None.
//!
//! \b Watch \b Variables \n
//! - pass
//!
//
//#############################################################################
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

修改内容:

1、我在CM4核的while循环上不断发送消息至CPU1,发现CPU1无法重复进入中断,请问是什么原因造成的?

ipc_ex2_msgqueue_cm.c

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
// End of example. Loop forever
//
while(1)
{
//
// Send response message
//
TxMsg.command = IPC_CMD_RESP;
TxMsg.address = (uint32_t)CMData;
TxMsg.dataw1 = 10;
TxMsg.dataw2 = 1;
IPC_sendMessageToQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
&TxMsg, IPC_NONBLOCKING_CALL);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

2、想问下消息队列的阻塞方式和非阻塞方式该如何理解?

  • 你好,

    1、我在CM4核的while循环上不断发送消息至CPU1,发现CPU1无法重复进入中断,请问是什么原因造成的?

    可能是中断标志位没有清除。

    2、想问下消息队列的阻塞方式和非阻塞方式该如何理解?

    你是说IPC吗?方便举个例子说明一下吗?

  • 可能是中断标志位没有清除。

    我是直接根据原代码内容进行修改的,只是将发送ipc消息队列放在while循环里了,然后就无法重复进入中断了,原代码中是有执行Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);这个函数的。

    你是说IPC吗?方便举个例子说明一下吗?

    是的,就是说我不理解IPC_NONBLOCKING_CALL和IPC_BLOCKING_CALL这两种方式根据什么情况下进行选择?

  • 我查看下相关资料后回复您。

  • 你好,请问有进展了吗?

  • 抱歉忘记回复您了。这边我已经咨询了相关工程师,但由于工程师出差了,需要等到这周三才能回来。一旦工程师有回复我会立即回复您。

  • 您是否能最少进入一次ISR?

    关于“block”参数,我认为理解它的最好方法是阅读 ipc.c 中的 IPC_sendMessageToQueue() 和 IPC_readMessageFromQueue() 函数: 

    如果放置缓冲区已满,看起来非阻塞调用将使 IPC_sendMessageToQueue() 函数立即失败。阻塞参数将使函数等待,直到放置缓冲区槽空闲。 

    我认为这在实践中意味着如果 没有 IPC_readMessageFromQueue() 就不能多次使用 IPC_sendMessageToQueue(),否则队列将满。阻塞调用将等待(可能永远)队列有空间,而非阻塞调用在看到队列已满时将立即失败。

  • 您是否能最少进入一次ISR?

    是 的,只有第一次能进来。

    如果放置缓冲区已满,看起来非阻塞调用将使 IPC_sendMessageToQueue() 函数立即失败。阻塞参数将使函数等待,直到放置缓冲区槽空闲。 

    我认为这在实践中意味着如果 没有 IPC_readMessageFromQueue() 就不能多次使用 IPC_sendMessageToQueue(),否则队列将满。阻塞调用将等待(可能永远)队列有空间,而非阻塞调用在看到队列已满时将立即失败。

    明白,非常感谢!

  • 已向相关工程师跟进。

  • 在 ISR 被触发一次之后,您是否能够在其内存浏览器中检查 cm 消息队列的放置缓冲区的内容 ?是否能够进入 IPC_sendMessageToQueue() 函数来查看函数内部发生了什么?是否通过了上面截图中的 while 循环?函数第一次运行和后续运行有什么不同吗?

  • 好的,我需要去测试看一下。

  • 你好,有结果了吗?问题是否已解决?

  • 你好,这几天在出差,回来后会尽快验证给答复

  • 你好,经过验证找到问题了

    我现在只进行cm发送ipc消息,cpu1中断读取消息,通过对两个core一起打断点来查看writeIndex和readIndex。

    验证过程:

    1、cm第一次执行完IPC_sendMessageToQueue() 函数,CPU1进入ipc中断但未IPC_readMessageToQueue() 

    上面两个图可以看到,cm的PutWriteIndex和cpu1的GetWriteIndex都加1。

    2、cm第一次执行完IPC_sendMessageToQueue() 函数,CPU1进入ipc中断执行了IPC_readMessageToQueue() 

    当cpu1执行了IPC_readMessageToQueue() 后,cm的PutReadIndex和cpu1的GetReadIndex都加1

    从上面两个验证结果来看,ipc的消息队列是能重复执行的,代码也没有问题。

    我之前不能重复中断的原因就是只在cpu1的ipc中断中设置断点,cm没有设置断点,也就导致cm不断发送ipc消息,而cpu1没有去读取,直到PutBuffer已满一直在IPC_sendMessageToQueue() 函数的while循环中执行,所以cpu1就没法重复进入中断读取消息了。

    对于阻塞和非阻塞调用,如果发送端采用阻塞调用不断发送数据而接收端采用阻塞接收,当发送端的PutBuffer已满,那发送端和接收端都会进入While循环导致两者都不能正常工作,这种情况如果其中一端采用非阻塞调用的话则这一端就能继续执行其他任务。请问我这样理解是对的吗?

  • 您的理解是正确的。