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.

TMS320F28386S-Q1: IPC API stops signaling the other processor

Part Number: TMS320F28386S-Q1
Other Parts Discussed in Thread: C2000WARE

This is a modification of the original post. I tried to lead my original post with a clearer summary and statement of my problem:

I tried to modify a TI-provided example for basic IPC communication so it is bi-directional, but I am  having a problem.

The TI example is this:

"C:\ti\c2000\C2000Ware_4_03_00_00\driverlib\f2838x\examples\c28x_cm\ipc\CCS\ipc_ex1_basic.projectspec"

It has two source files:  "ipc_ex1_basic_c28x1.c" and "ipc_ex1_basic_cm.c".

This example code demonstrates the C28x processor using basic IPC API functions to send an array of 10 integers to the Communications Manager (CM) processor.  I am able to build and run the example on the TI board as it is written.

I modified the example so that CM will use basic IPC functions to send an array of 10 integers back to the C28x after it receives the data from the C28x. In each program, I added a global variable which I increment within the IPC interrupt handler of the respective program.

Finally, I modified the example programs to continue to exchange messages in this way, one at a time, forever. 

The problem is that the IPC interrupt handler function is not invoked a second time after the first time CM sends C28x an IPC message. Therefore, when the CM attempts to send a second message, it is endlessly waiting for an acknowledgement from the C28x side.  Just as in the unmodified example, I am calling IPC_sendResponse() and IPC_ackFlagRtoL() after first calling IPC_readCommand() within the IPC ISR.  Shouldn't the call to IPC_ackFlagRtoL() clear everything necessary so that the IPC flag can be used by the CM a second time to interrupt the C28x?  I have attached the CM and C28x example projects (having my modifications).

The following is the original post with a little more detail ...

I modified the "ipc_ex1_basic_cm" example in two ways:

1. I added code to have a message with data sent back to CPU1 from the CM.

2. I modified the example so the CPU1 and CM would take turns sending each other messages using IPC.

I have been able to observe the following, and then a problem occurs:

a. CPU1 sends a message with data to CM using IPC with FLAG0

b. CM's handler uses IPC_readCommand(), IPC_sendResponse(), and IPC_ackFlagRtoL() with IPC_FLAG0. The handler increments a counter (which was initialized to 0 when the program started).

c. CPU1 waits for that ack and calls IPC_getResponse() to read the response value.

Steps a - c are repeated, this time with CM sending a message to CPU1 and CM is using IPC_FLAG1 to signal CPU1.  The handler in CPU1 increments a counter (which was initialized to 0 when the program started).

The counter in each processor is now 1.

Steps a - c are repeated (CPU1 sending to CM).  The counter on the CM side is now 2, while the counter on the CPU1 side is still 1.

Here is the problem:

Steps a - c are about to repeat (with CM sending to CPU1), but during step a, the CM remains blocked on the call to IPC_waitForAck().  The CPU1 code did not execute its handler for this second transmission by CM, so it does not call the IPC_ackFlagRtoL() function (which is part of the handler code).

The question is this - why is CPU1's handler not being invoked after it is invoked the first time?  It seems as though something is not being cleared for CPU1 after its handler (for IPC_FLAG1) is invoked  that first time, but I cannot figure it out.

No message queues are used (this is a modification of the basic IPC example).TI_help_ticket_IPC_lockup.zip

  • You're not acknowledging the interrupt on CPU1. Put this code right after acknowledging the IPC ack flag. 

    IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);
    ->Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);


  • Thank you Tristen!  Nowhere in the documentation that I have read have I seen anything about the need for this call after using "IPC ack".  So either the documentation does not specifically state the need for it, or I missed a document, or it is something the reader must glean after having a greater understanding from disparate parts of the documentation.  I wish I had that understanding, or I knew where to read. After reading the documentation I assumed that the IPC_ackFlagRtoL() call was sufficient to clear everything, but obviously that assumption is incorrect.

    Your suggestion worked.

    Are you able to point me to place(s) in the documentation where I should read so I can better understand why this is required with IPC?  Also, I wonder why this call is not necessary on the CM processor, but is necessary on the C28x processor.  Can you explain?  

  • Hi James,

    Please allow me another day to write a full response.

    Best Regards,

    Ben Collier

  • Hi James,

    For the C28x processor, you could read this section of the F2838x TRM to understand why the PIEACK register needs to be cleared.

    Section 3.4 of the TRM gives a general overview of interrupts on a C28x CPU, and 3.4.2.2 discusses the PIEACK, although the PIEACK registers section screenshotted above gives more detail.

    The CM is a different CPU with a different architecture (ARM), and its interrupts work differently. From the section 41.7.1 of the TRM, it looks like the interrupt flag gets cleared automatically when an ISR is entered. 

    Please let me know if you have any more questions.

    Best Regards,

    Ben Collier

  • Ben - thanks a million for pointing me to the right documentation which explains why Tristen's submission resolved my problem.  Having the context is extremely valuable.