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: Question about IPC communication

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE

Dear team:

My customer want to change the communication method of routine(ipc_ex2_msgqueue_c28x1.c) into interrupt method. And he made the following modifications:

1, Added interrupt receiving function

//
// IPC ISR for Flag 1
// C28x core sends data with message queue using Flag 0
//
__interrupt void IPC_ISR1() 
{
int i;
//IPC_Message_t TxMsg, RxMsg;
bool status = false;

//
// Read the message from the message queue
//
IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
&RxMsg, IPC_NONBLOCKING_CALL);

if(RxMsg.command == IPC_CMD_READ_MEM)
{
status = true;

//
// Read and compare data
//
for(i=0; i<RxMsg.dataw1; i++)
{
if((*(uint32_t *)RxMsg.address + i) != i)
status = false;
}
}

//
// Acknowledge the flag
//
IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);

//
// Acknowledge the PIE interrupt.
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

2, Enable IPC interrupts
//
IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT1, IPC_ISR1); 

//
Initialize message queue
//
IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_INT1, IPC_INT1);

3, Added send loop for testing

while(1) 
{

DEVICE_DELAY_US(100000);
IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
&TxMsg, IPC_NONBLOCKING_CALL);
DEVICE_DELAY_US(100000);

}

The test result is that the IPC communication between CPU1 and CM cannot be interrupted. What is the problem? Here is the complete code:

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define IPC_CMD_READ_MEM 0x1001
#define IPC_CMD_RESP 0x2001

#define TEST_PASS 0x5555
#define TEST_FAIL 0xAAAA


#pragma DATA_SECTION(readData, "MSGRAM_CPU_TO_CM")
uint32_t readData[10];

uint32_t pass;

IPC_MessageQueue_t messageQueue;
IPC_Message_t TxMsg, RxMsg;

//
// IPC ISR for Flag 1
// C28x core sends data with message queue using Flag 0
//
__interrupt void IPC_ISR1()          //增加了中断接收函数
{
int i;
//IPC_Message_t TxMsg, RxMsg;
bool status = false;

//
// Read the message from the message queue
//
IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
&RxMsg, IPC_NONBLOCKING_CALL);

if(RxMsg.command == IPC_CMD_READ_MEM)
{
status = true;

//
// Read and compare data
//
for(i=0; i<RxMsg.dataw1; i++)
{
if((*(uint32_t *)RxMsg.address + i) != i)
status = false;
}
}

//
// Acknowledge the flag
//
IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);

//
// Acknowledge the PIE interrupt.
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}













//
// Main
//
void main(void)
{
int i;


//
// Initialize device clock and peripherals
//
Device_init();


// Boot CM core
//
#ifdef _FLASH
Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#else
Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
#endif

// Clear any IPC flags if set already
//
IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);

//
// Enable IPC interrupts
//
IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT1, IPC_ISR1);              //注册了中断

//
// Initialize message queue
//
IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_INT1, IPC_INT1);    //初始化中断

//
// Synchronize both the cores
//


//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;

IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);
//
// Fill in the data to be sent
//
for(i=0; i<10; i++)
{
readData[i] = i;
}

//
// Update the message
//
TxMsg.command = IPC_CMD_READ_MEM;
TxMsg.address = (uint32_t)readData;
TxMsg.dataw1 = 10; // Using dataw1 as data length
TxMsg.dataw2 = 1; // Message identifier




//
// End of example. Loop forever
//
while(1)            //增加了循环发送用于测试
{

DEVICE_DELAY_US(100000);
IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
&TxMsg, IPC_NONBLOCKING_CALL);
DEVICE_DELAY_US(100000);

}
}

Best regards,

Green

  • Green,

    Do you mean to say IPC_ISR1 interrupt is not triggered in CM side? (or) IPC_ISR1 interrupt isn't triggered in CPU1 side? 

    CPU1 side of the code presents only one side of the story? what is happening in CM? 

    Regards,

    Manoj

  • Hi Manoj:

    Customer feedback: CM4 side can enter the interrupt normally, CPU1 side cannot enter the interrupt, and CM4 uses routine program:

    #include "cm.h"
    #include "ipc.h"
    
    //
    // Defines
    //
    #define IPC_CMD_READ_MEM 0x1001
    #define IPC_CMD_RESP 0x2001
    
    #define TEST_PASS 0x5555
    #define TEST_FAIL 0xAAAA
    
    IPC_MessageQueue_t messageQueue;
    
    
    //
    // IPC ISR for Flag 1
    // C28x core sends data with message queue using Flag 0
    //
    __interrupt void IPC_ISR1()
    {
    int i;
    IPC_Message_t TxMsg, RxMsg;
    bool status = false;
    
    //
    // Read the message from the message queue
    //
    IPC_readMessageFromQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
    &RxMsg, IPC_NONBLOCKING_CALL);
    
    if(RxMsg.command == IPC_CMD_READ_MEM)
    {
    status = true;
    
    //
    // Read and compare data
    //
    for(i=0; i<RxMsg.dataw1; i++)
    {
    if((*(uint32_t *)RxMsg.address + i) != i)
    status = false;
    }
    }
    
    //
    // Send response message
    //
    TxMsg.command = IPC_CMD_RESP;
    TxMsg.address = 0; // Not used
    TxMsg.dataw1 = status ? TEST_PASS : TEST_FAIL;
    TxMsg.dataw2 = RxMsg.dataw2; // Use the message identifier from the received message
    
    IPC_sendMessageToQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_ADDR_CORRECTION_DISABLE,
    &TxMsg, IPC_NONBLOCKING_CALL);
    
    //
    // Acknowledge the flag
    //
    IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG1);
    }
    
    //
    // Main
    //
    void main(void)
    {
    //
    // Initialize device clock and peripherals
    //
    CM_init();
    
    //
    // Clear any IPC flags if set already
    //
    IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
    
    //
    // Enable IPC interrupts
    //
    IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT1, IPC_ISR1);
    
    //
    // Initialize message queue
    //
    IPC_initMessageQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_INT1, IPC_INT1);
    
    //
    // Synchronize both the cores.
    //
    IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31);
    
    //
    // Loop forever. Wait for IPC interrupt
    //
    while(1);
    }

    Regards,

    Green

  • Green,

    I will try to reproduce the issue from my side. Please expect a reply within 3 - 4 business days.

    Regards,

    Manoj

  • Manoj:

    Thank you for your help and wait for your reply.

    Green

  • Green,

    I started working on this today. I ran into compile issues and working to fix it.

    Regards,

    Manoj

  • Manoj:

    Thank you very much for your help.

    Best regards,

    Green

  • Deng,

    I have started working on this project. I shall keep you posted.

    I expect to provide a response by tomorrow.

    Regards,

    Manoj

  • Hi Manoj:

    Are there any updates on this issue?

    Best regards,

    Green

  • I have been able to get CM to interrupt CPU1 using IPC1 but not yet successful in having CM send message to CPU1 successfully.

  • Green,

    I have attached modified version of C2000Ware msgqueue example code which has CPU1 pass information (data passed 1 to 10) to CM and CM pass information (data passed 11 to 20) using interrupt method. Both CPU1 and CM interrupt eachother using IPC1 interrupt.

    //#############################################################################
    //
    // 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.
    //!
    //
    //#############################################################################
    // $Copyright:
    // Copyright (C) 2022 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.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "cm.h"
    #include "ipc.h"
    
    //
    // Defines
    //
    #define IPC_CMD_READ_MEM   0x1001
    #define IPC_CMD_RESP       0x2001
    
    #define TEST_PASS          0x5555
    #define TEST_FAIL          0xAAAA
    
    IPC_MessageQueue_t messageQueue;
    
    #pragma DATA_SECTION(CMData, "MSGRAM_CM_TO_CPU1")
    uint32_t CMData[10];
    
    
    //
    // IPC ISR for Flag 1
    // C28x core sends data with message queue using Flag 0
    //
    __interrupt void IPC_ISR1()
    {
        int i;
        IPC_Message_t TxMsg, RxMsg;
        bool status = false;
    
        //
        // Read the message from the message queue
        //
        IPC_readMessageFromQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                 &RxMsg, IPC_NONBLOCKING_CALL);
    
        if(RxMsg.command == IPC_CMD_READ_MEM)
        {
            status = true;
    
            //
            // Read and compare data
            //
            for(i=0; i<RxMsg.dataw1; i++)
            {
                if((*(uint32_t *)RxMsg.address + i) != i)
                    status = false;
            }
        }
    
        //
        // 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);
    
        //
        // Acknowledge the flag
        //
        IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG1);
    }
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        CM_init();
    
        //
        // Clear any IPC flags if set already
        //
        IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
    
        //
        // Enable IPC interrupts
        //
        IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT1, IPC_ISR1);
    
        //
        // Initialize message queue
        //
        IPC_initMessageQueue(IPC_CM_L_CPU1_R, &messageQueue, IPC_INT1, IPC_INT1);
    
        //
        // Synchronize both the cores.
        //
        IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31);
    
        int i;
        for(i=0; i<10; i++)
        {
            CMData[i] = i+11;
        }
    
        //
        // Loop forever. Wait for IPC interrupt
        //
        while(1);
    }
    
    
    //
    // End of File
    //
    

    //#############################################################################
    //
    // 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
    //!
    //
    //#############################################################################
    // $Copyright:
    // Copyright (C) 2022 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.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    #define IPC_CMD_READ_MEM   0x1001
    #define IPC_CMD_RESP       0x2001
    
    #define TEST_PASS          0x5555
    #define TEST_FAIL          0xAAAA
    
    
    #pragma DATA_SECTION(CPU1Data, "MSGRAM_CPU_TO_CM")
    uint32_t CPU1Data[10];
    
    IPC_MessageQueue_t messageQueue;
    IPC_Message_t      TxMsg, RxMsg;
    
    uint32_t pass;
    
    __interrupt void IPC_ISR1()
    {
        int i;
        bool status = false;
    
        //
        // Read the message from the message queue
        //
        IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                 &RxMsg, IPC_NONBLOCKING_CALL);
    
        if(RxMsg.command == IPC_CMD_RESP)
        {
            status = true;
    
            for(i=0; i<RxMsg.dataw1; i++)
            {
               if((*(uint32_t *)RxMsg.address + i) != i+11)
                           status = false;
            }
        }
    
    
        //
        // Send response message
        //
        TxMsg.command = IPC_CMD_READ_MEM;
        TxMsg.address = (uint32_t)CPU1Data;
        TxMsg.dataw1  = 10;  // Using dataw1 as data length
        TxMsg.dataw2  = 1;   // Message identifier
    
        IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                               &TxMsg, IPC_NONBLOCKING_CALL);
    
        //
        // Acknowledge the flag
        //
        IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);
    
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
    }
    
    //
    // Main
    //
    void main(void)
    {
        int i;
    
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Boot CM core
        //
    #ifdef _FLASH
        Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
    #else
        Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
    #endif
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Clear any IPC flags if set already
        //
        IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);
    
        //
        // Enable IPC interrupts
        //
        IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT1, IPC_ISR1);
    
        //
        // Initialize message queue
        //
        IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_INT1, IPC_INT1);
    
        //
        // Synchronize both the cores
        //
        IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Fill in the data to be sent
        //
        for(i=0; i<10; i++)
        {
            CPU1Data[i] = i;
        }
    
        //
        // Update the message
        //
        TxMsg.command = IPC_CMD_READ_MEM;
        TxMsg.address = (uint32_t)CPU1Data;
        TxMsg.dataw1  = 10;  // Using dataw1 as data length
        TxMsg.dataw2  = 1;   // Message identifier
    
        //
        // Send message to the queue
        // Since C28x and CM does not share the same address space for shared RAM,
        // ADDRESS_CORRECTION is enabled
        //
        IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                               &TxMsg, IPC_NONBLOCKING_CALL);
    
        //
        // End of example. Loop forever
        //
        while(1);
    }
    
    
    //
    // End of File
    //
    

    Regards,

    Manoj