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: IPC通信:CM向CPU1发送数据,CPU1只接收到命令、数据长度,具体的数据接收不到

Part Number: TMS320F28388D


我使用的是官方例程:ipc_ex2_msgqueue_c28x1.c和ipc_ex2_msgqueue_cm.c,在此基础上进行修改:

CPU1:

//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
//
// Defines
//
#define IPC_CMD_READ_MEM   0x1001
#define IPC_CMD_RESP       0x2001

#define TEST_PASS          0x5555
#define TEST_FAIL          0xAAAA
#define DATA_SUM            10

#pragma DATA_SECTION(cpu1_sendData, "MSGRAM_CPU_TO_CM")
uint32_t cpu1_readData[DATA_SUM];
uint32_t cpu1_sendData[DATA_SUM];
uint32_t pass;
IPC_MessageQueue_t messageQueue0;
IPC_Message_t      TxMsg0, RxMsg0;
IPC_MessageQueue_t messageQueue1;
IPC_Message_t      TxMsg1, RxMsg1;



//
//
//
__interrupt void IPC_ISR0()
{
    int i;

    bool status = false;

    //
    // Read the message from the message queue
    //
    IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_ADDR_CORRECTION_ENABLE,
                             &RxMsg0, IPC_NONBLOCKING_CALL);

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

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

    //
    // Send response message
    //
    TxMsg0.command = IPC_CMD_RESP;
    TxMsg0.address = 0; // Not used
    TxMsg0.dataw1  = status ? TEST_PASS : TEST_FAIL;
    TxMsg0.dataw2  = RxMsg0.dataw2; // Use the message identifier from the received message

    IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_ADDR_CORRECTION_DISABLE,
                           &TxMsg0, IPC_NONBLOCKING_CALL);

    //
    // Acknowledge the flag
    //
    IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG0);
    //
    // Acknowledge the PIE interrupt.
    //
    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);
/*******************************************cpu1 send cm read******************************************************************/
    //
    // Initialize message queue
    //
    IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue1, IPC_INT1, IPC_INT1);
/*******************************************cpu1 read cm send******************************************************************/
    //
    // Enable IPC interrupts
    //
    IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT0, IPC_ISR0);
    //
    // Initialize message queue
    //
    IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_INT0, IPC_INT0);
    //
    // Synchronize both the cores
    //
    IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);

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





    memset(cpu1_readData,0,sizeof(cpu1_readData));
    memset(cpu1_sendData,0,sizeof(cpu1_sendData));
    //
    // End of example. Loop forever
    //
    while(1);
    {
        //
        // Fill in the data to be sent
        //
        for(i=0; i<DATA_SUM; i++)
        {
            cpu1_sendData[i] = 0x5a5a1234 + 2 * i;
        }

        //
        // Update the message
        //
        TxMsg1.command = IPC_CMD_READ_MEM;
        TxMsg1.address = (uint32_t)cpu1_sendData;
        TxMsg1.dataw1  = DATA_SUM;  // Using dataw1 as data length
        TxMsg1.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, &messageQueue1, IPC_ADDR_CORRECTION_ENABLE,
                               &TxMsg1, IPC_BLOCKING_CALL);

        //
        // Read message from the queue
        // Return message from CM does not use the address field, hence
        // ADDRESS_COREECTION feature is not used
        //
        IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue1, IPC_ADDR_CORRECTION_DISABLE,
                                 &RxMsg1, IPC_BLOCKING_CALL);

        if((RxMsg1.command == IPC_CMD_RESP) && (RxMsg1.dataw1 == TEST_PASS) && (RxMsg1.dataw2 == 1))
            pass = 1;
        else
            pass = 0;
    }
}

CM:

//
// 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
#define DATA_SUM            10
uint32_t cm_readData[DATA_SUM];
uint32_t cm_sendData[DATA_SUM];
uint32_t pass;
IPC_MessageQueue_t messageQueue0;
IPC_Message_t      TxMsg0, RxMsg0;
IPC_MessageQueue_t messageQueue1;
IPC_Message_t      TxMsg1, RxMsg1;


//
// IPC ISR for Flag 1
// C28x core sends data with message queue using Flag 0
//
__interrupt void IPC_ISR1()
{
    int i;

    bool status = false;

    //
    // Read the message from the message queue
    //
    IPC_readMessageFromQueue(IPC_CM_L_CPU1_R, &messageQueue1, IPC_ADDR_CORRECTION_ENABLE,
                             &RxMsg1, IPC_NONBLOCKING_CALL);

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

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

    //
    // Send response message
    //
    TxMsg1.command = IPC_CMD_RESP;
    TxMsg1.address = 0; // Not used
    TxMsg1.dataw1  = status ? TEST_PASS : TEST_FAIL;
    TxMsg1.dataw2  = RxMsg1.dataw2; // Use the message identifier from the received message

    IPC_sendMessageToQueue(IPC_CM_L_CPU1_R, &messageQueue1, IPC_ADDR_CORRECTION_DISABLE,
                           &TxMsg1, IPC_NONBLOCKING_CALL);

    //
    // Acknowledge the flag
    //
    IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG1);
}

//
// Main
//
void main(void)
{
    uint32_t i = 0;
    //
    // Initialize device clock and peripherals
    //
    CM_init();

    //
    // Clear any IPC flags if set already
    //
    IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
    /*******************************************cpu1 send cm read******************************************************************/
    //
    // Enable IPC interrupts
    //
    IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT1, IPC_ISR1);

    //
    // Initialize message queue
    //
    IPC_initMessageQueue(IPC_CM_L_CPU1_R, &messageQueue1, IPC_INT1, IPC_INT1);
/*******************************************cpu1 read cm send******************************************************************/
    //
    // Initialize message queue
    //
    IPC_initMessageQueue(IPC_CM_L_CPU1_R, &messageQueue0, IPC_INT0, IPC_INT0);
    //
    // Synchronize both the cores.
    //
    IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31);

    //
    // Loop forever. Wait for IPC interrupt
    //
    while(1)
    {
        //
        // Fill in the data to be sent
        //
        for(i=0; i<DATA_SUM; i++)
        {
            cm_sendData[i] = 0x5a5a1234 + 2 * i;
        }

        //
        // Update the message
        //
        TxMsg0.command = IPC_CMD_READ_MEM;
        TxMsg0.address = (uint32_t)cm_sendData;
        TxMsg0.dataw1  = DATA_SUM;  // Using dataw1 as data length
        TxMsg0.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_CM_L_CPU1_R, &messageQueue0, IPC_ADDR_CORRECTION_ENABLE,
                               &TxMsg0, IPC_BLOCKING_CALL);

        //
        // Read message from the queue
        // Return message from CM does not use the address field, hence
        // ADDRESS_COREECTION feature is not used
        //
        IPC_readMessageFromQueue(IPC_CM_L_CPU1_R, &messageQueue0, IPC_ADDR_CORRECTION_DISABLE,
                                 &RxMsg0, IPC_BLOCKING_CALL);

        if((RxMsg0.command == IPC_CMD_RESP) && (RxMsg0.dataw1 == TEST_PASS) && (RxMsg0.dataw2 == 1))
            pass = 1;
        else
            pass = 0;
    }
}


//
// End of File
//

调试:

  • 额,你好,程序里面还请说明一下具体修改的哪些位置的代码。否则一句一句去校对有点费时。

  • 好的,麻烦您了。

    修改位置:

    1、CPU1中增加一个通道,设置接收中断函数,原先的通道停止发送(while(1);)。

    /*******************************************cpu1 read cm send******************************************************************/
        //
        // Enable IPC interrupts
        //
        IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT0, IPC_ISR0);
        //
        // Initialize message queue
        //
        IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_INT0, IPC_INT0);

    __interrupt void IPC_ISR0()
    {
        int i;
    
        bool status = false;
    
        //
        // Read the message from the message queue
        //
        IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_ADDR_CORRECTION_ENABLE,
                                 &RxMsg0, IPC_NONBLOCKING_CALL);
    
        if(RxMsg0.command == IPC_CMD_READ_MEM)
        {
            status = true;
    
            //
            // Read and compare data
            //
            for(i=0; i<RxMsg0.dataw1; i++)
            {
                if(i < DATA_SUM)
                {
                    cpu1_readData[i] = *((uint32_t *)RxMsg0.address + i);
                }
                if(*((uint32_t *)RxMsg0.address + i) != i)
                    status = false;
            }
        }
    
        //
        // Send response message
        //
    
        TxMsg0.command = IPC_CMD_RESP;
        TxMsg0.address = 0; // Not used
        TxMsg0.dataw1  = status ? TEST_PASS : TEST_FAIL;
        TxMsg0.dataw2  = RxMsg0.dataw2; // Use the message identifier from the received message
    
        IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue0, IPC_ADDR_CORRECTION_ENABLE,
                               &TxMsg0, IPC_NONBLOCKING_CALL);
    
        //
        // Acknowledge the flag
        //
        IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG0);
        //
        // Acknowledge the PIE interrupt.
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
    
    }

    2、在M4中,增加新的通道,设置发送

    /*******************************************cpu1 read cm send******************************************************************/
        //
        // Initialize message queue
        //
        IPC_initMessageQueue(IPC_CM_L_CPU1_R, &messageQueue0, IPC_INT0, IPC_INT0);

        while(1)
        {
            //
            // Fill in the data to be sent
            //
            for(i=0; i<DATA_SUM; i++)
            {
                cm_sendData[i] = 0x5a5a1234 + 2 * i;
            }
    
            //
            // Update the message
            //
            TxMsg0.command = IPC_CMD_READ_MEM;
            TxMsg0.address = (uint32_t)cm_sendData;
            TxMsg0.dataw1  = DATA_SUM;  // Using dataw1 as data length
            TxMsg0.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_CM_L_CPU1_R, &messageQueue0, IPC_ADDR_CORRECTION_ENABLE,
                                   &TxMsg0, IPC_BLOCKING_CALL);
    
            //
            // Read message from the queue
            // Return message from CM does not use the address field, hence
            // ADDRESS_COREECTION feature is not used
            //
            IPC_readMessageFromQueue(IPC_CM_L_CPU1_R, &messageQueue0, IPC_ADDR_CORRECTION_DISABLE,
                                     &RxMsg0, IPC_BLOCKING_CALL);
    
    
            if((RxMsg0.command == IPC_CMD_RESP) && (RxMsg0.dataw1 == TEST_PASS) && (RxMsg0.dataw2 == 1))
                pass = 1;
            else
                pass = 0;
        }

  • 收到,我会尽快回复

  • IPC 驱动程序函数中的 IPC_ADDR_CORRECTION_ENABLE 功能仅在地址在 IPC MSGRAM 中时才起作用。 例如,如果 CPU1 正在向 CM 发送数据,则地址应在 CPU1_TO_CM_MSGRAM 的地址范围内。

    你这边需要确认一下上述这点是否满足?

  • 谢谢。

    在CM向CPU1发送时,地址发送端和接收端都超出了范围:

    在CPU1中:

    在CM中:

    代码中address的值,怎么改呢?

  • 如果不使用地址参数,或者用于发送不在 CPU1-CM IPC MSGRAM 范围内的地址,请禁用 ADDRESS_CORRECTION 功能。

    IPC_sendMessageToQueue(.., .., IPC_ADDR_CORRECTION_DISABLE, .. , ..);

    IPC_readMessageFromQueue(.., .., IPC_ADDR_CORRECTION_DISABLE, .. , ..);

  • 禁用ADDRESS_CORRECTION功能,CM有什么办法向CPU1、CPU2传输数据吗?

  • 禁用 ADDRESS_CORRECTION的前提是如果不使用地址参数,或者用于发送不在 CPU1-CM IPC MSGRAM 范围内的地址,这样就可以减少空间使用

  • 这个明白了,谢谢!重点是CM有什么办法向CPU1、CPU2传输数据吗