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 stucks in a loop

Part Number: TMS320F28388D

Tool/software:

I have an application that utilizes a modified version of LWIP with IPC messages for communication between the DSP and CPU1.

The following sequence occurs when a UDP packet is received:

  1. Forwarding to CPU1:

    • An IPC message containing the UDP packet data is sent to CPU1 using IPC_sendCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE, IPCTOCPU_PROTO_PCK, (uint32_t)packetData, (uint32_t)pckLength);
    • IPC_waitForAck(IPC_CM_L_CPU1_R, IPC_FLAG0); is called to wait for an acknowledgment from CPU1.
  2. Processing by CPU1:

    • CPU1 processes the received packet.
  3. Sending Response from CPU1:

    • CPU1 sends a response to CM using IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE, IPCTOCM_PROTO_PCK, (uint32_t) packetDataTx, nByte);
    • IPC_waitForAck(IPC_CPU1_L_CM_R, IPC_FLAG1); is called to wait for an acknowledgment from CM.

Problem:

The code intermittently enters a loop, indicated by the assembly instructions:

F24D0004 movw r0, #0xd004
00001628: F2C4000F movt r0, #0x400f
0000162c: 6800 ldr r0, [r0]
0000162e: 0840 lsrs r0, r0, #1
00001630: D3F8 blo #0x1624 

According to the datasheet, 0x400fd004 corresponds to an IPC configuration register. This loop appears to be associated with the IPC_waitForAck() function:

static inline void IPC_waitForAck(IPC_Type_t ipcType, uint32_t flag) { 
    while((IPC_Instance[ipcType].IPC_Flag_Ctr_Reg->IPC_FLG & flag) != 0U) { 
        // Wait for flag to be cleared
    } 
}

where #define IPC_FLAG0 0x00000001U is the flag used for ethernet messages from CM to CPU1.

Removing both IPC_waitForAck() calls did not resolve the issue.

Could you please provide guidance on troubleshooting this issue? I can share relevant code snippets via private message if needed.

  • hi,

    Have you had a chance to rake a look at the IPC examples provided in C 2000Ware? 
    https://dev.ti.com/tirex/explore/node?node=A__ANwwURrRiqh4Fp5sl6q1qQ__C2000WARE__1kRFgrO__LATEST

    there are C 28 and CM based examples that you can use as a starting point.

    Regards,

    Ozino

  • I've implemented examples in my code as provided by TI.

  • Seems like, if I add another IPC flag and increase my messages frequencies, this error happens more frequently.

  • Hi Yaro,

    Do you know how you are adding these IPC Flags? Just wanted to point out that you must use Flag 1 for interrupt 1, Flag 2 for interrupt 2, flag 3 for interrupt 3, and flag 4 for interrupt 4.

    Also see the ipc_ex2_msgqueue_c28x1, ipc_ex2_msgqueue_cm examples on to establish proper communication between the two cores.

    See this section in the IPC guide for more information on the IPC flags.

    https://software-dl.ti.com/C2000/docs/C2000_Multicore_Development_User_Guide/ipc_communication.html#ipc-flags-and-command-registers 

    Regards,

    Ozino

  • Here's some additional:

    This how I allocate memory:

    on CM:

    #define PACKET_LENGTH 1500
    uint8_t packetData[PACKET_LENGTH];
    #pragma DATA_SECTION(packetData, "MSGRAM_CM_TO_CPU1")
    uint8_t ipcTransBuff[250];
    #pragma DATA_SECTION(ipcTransBuff, "MSGRAM_CM_TO_CPU1")
    

    on CM .cmd file:

    MEMORY {
    CPU1TOCMMSGRAM0 : origin = 0x20080000, length = 0x00000800
    CPU1TOCMMSGRAM1 : origin = 0x20080800, length = 0x00000800
    CMTOCPU1MSGRAM0 : origin = 0x20082000, length = 0x00000800
    CMTOCPU1MSGRAM1 : origin = 0x20082800, length = 0x00000800
    
    SECTIONS {
    MSGRAM_CM_TO_CPU1 : > CMTOCPU1MSGRAM0, type=NOINIT
    MSGRAM_CPU1_TO_CM : > CPU1TOCMMSGRAM0, type=NOINIT


    on CPU1:

    #define PACKET_LENGTH 1500
    uint8_t packetDataTx[PACKET_LENGTH];
    #pragma DATA_SECTION(packetDataTx, "MSGRAM_CPU_TO_CM")
    uint8_t ipcTransBuff[250];
    #pragma DATA_SECTION(ipcTransBuff, "MSGRAM_CPU_TO_CM")

    on CPU1 .cmd file:

    PAGE 1:
    CPUTOCMRAM : origin = 0x039000, length = 0x000800
    CMTOCPURAM : origin = 0x038000, length = 0x000800
    SECTIONS {
    MSGRAM_CPU_TO_CM : > CPUTOCMRAM, type=NOINIT, PAGE = 1
    MSGRAM_CM_TO_CPU : > CMTOCPURAM, type=NOINIT, PAGE = 1


    CM side:

    First CM and CPU1 are sync at different moment to allow to init peripherals and memory.

    IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
    IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT1, IPC_ISR1); 
    IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT3, IPC_ISR3); 
    IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31); // Synchronize both the cores.
    
    struct cmFwInfo_s {
        uint16_t major;
        uint16_t minor;
        uint16_t rev;
    } cmFwInfo;
    
    cmFwInfo.major = VER_MAJOR;
    cmFwInfo.minor = VER_MINOR;
    cmFwInfo.rev = VER_REV;
    
    memcpy(&ipcTransBuff, &cmFwInfo, sizeof(struct cmFwInfo_s));
    
    if(!IPC_isFlagBusyLtoR(IPC_CM_L_CPU1_R, IPC_FLAG2))
        IPC_sendCommand(IPC_CM_L_CPU1_R, IPC_FLAG2, IPC_ADDR_CORRECTION_ENABLE,
        IPCTOCPU_CMD_SEND_INFO, (uint32_t) ipcTransBuff, (uint32_t) sizeof(struct cmFwInfo_s));
    IPC_waitForAck(IPC_CM_L_CPU1_R, IPC_FLAG2); // Wait for acknowledgment
    
    
    IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG30);


    Now CPU1 and CM communicates using this orders:

    from CM


     

    if(!IPC_isFlagBusyLtoR(IPC_CM_L_CPU1_R, IPC_FLAG0))
        IPC_sendCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
        IPCTOCPU_PROTO_PCK, (uint32_t)packetData, (uint32_t)pckLength);

    get from CPU1

    IPC_readCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
    &command, &addr, &data);
    
    newRxProtoPck((uint8_t *) addr, data);
    
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11); // Acknowledge this interrupt
    
    IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG0); // Acknowledge the flag


    from CPU1
    if(!IPC_isFlagBusyLtoR(IPC_CPU1_L_CM_R, IPC_FLAG1))
        IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,
        IPCTOCM_PROTO_PCK, (uint32_t) packetDataTx, nByte);


    get from CM

    IPC_readCommand(IPC_CM_L_CPU1_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,
    &command, &addr, &data);
    if(command == IPCTOCM_PROTO_PCK)
    udpSendTxProtoPck((uint8_t *) addr, data);
    
    IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG1);
    
    Interrupt on CM is registred by IPC_registerInterrupt while on CPU1 by sysBios interrupt configuration:
    Hwi_create(208, (Hwi_FuncPtr)IPC_ISR0,  &hwiParams, &eb);
    Hwi_create(210, (Hwi_FuncPtr)IPC_ISR2, &hwiParams, &eb);


    Flag used are
    IPC_FLAG0 from CM to CPU1
    IPC_FLAG1 from CPU1 to CM
    IPC_FLAG2 from CM to CPU1
    IPC_FLAG3 from CPU1 to CM

    As said, IPC works good with constant messages at a frequency of 5ms to 10ms. Both from and to CM (actually only with CPU1).

    A lot of messages are exchanged before block occur, about between 15min to 2 hours of messages. It's something random not related to a particolar event (or we're unable to relate this error to a particular one).
    Also buffers from and to CM are filled just before send ipcCommand and only filled in this occasions.

    Unfortunately your manual, and application notes of TMS320F28388, doesn't provided me additional or useful informations.

    Hoping in your support. Can share code by PM .

  • Hi,

    I've sent a friend request. Please go ahead and share your code and describe your exact use case that best replicates the error described above.

    I'll get back you with more information once I've had a chance to reach out to the IPC experts.

    Regards,

    Ozino

  • Hi,

    I came across that mentions bug in the IPC_messageRam example. Can you please apply the following changes described here:

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1292430/tms320f28388d-cpu1-to-cm-ipc-message-queue-problem 

    Are you able to use multiple message queues instead of calling the IPC send command multiple times? This thread explains the pros and cons to these implementations.https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1288693/tms320f28388d-ipc-message-queue-communication-between-cpu1-and-cm-and-ipc-communication-issues 

    Regards,

    Ozino

  • I've confirmed (pressed "This resolved my issue") on your message by mistake. Unfortunately I can't remove this.

    About your first link, I've checked memory allocation and it's correct. Also I can't call same IPC multiple times if it's not akn before . 

    I can try your proposal but I've some doubts that are not explained by C2000 manual:

    Actually I've a buffer of 1500 byte for one kind of message and 250 byte for another. A total of 1750 bytes are occupied on 2048 of available bytes on shared memory CM to CPU1 . Same from CPU1 to CM.

    I've read that IPC Messages have 4 buffer per each IPC flag. I'm unable to allocate 1500 x 4 = 6000 bytes (not even 2, that are 3000 bytes) on shared memory in case of more than 1 message in queue.

    I'm missing something? What would happen in case, an abort or an overflow?

  • Hi,

    I am going to reach out to other experts to discuss this issue you are observed. I'll get back to you on the last two questions. Can you please provide any updates on the proposed workarounds.

    Regards,

    Ozino

  • After some research I've found that it's a circular buffer and will overwrite last messages. Unfortunately I was unable to make correctly work IPC Messages. I've double checked your post and described workarounds are already implemented in last examples. IPC Interrupts are working, but only once. After IPC flag is cleared (and interrupt akn for CPU1) there's no more interrupt calls between CPU1 and CM . Also inside IPC_Message_t there's garbage, seems like it points to passed data instead of struct with data address inside.

  • Found why data was corrupted. Position of the allocated MessageQueue buffers was wrong also on CM side, so the same correction stated on your previous indicated post must be applied on CM too. Now data is correct.

    Still remain the interrupt problem that is triggered only once. Actual IPC_Flag is the same on both cores same as akn flag. On CPU1 is also ack GROUP11.

    Do you have ideas on why is not correctly working?

  • Hi,

    Thanks for your patience. Our experts are now available to look further into this thread offline. Can you share your a zip of your code on this E2E post or via your FAE contact. Once we receive the code we will return back to you with more information.

    Regards,

    Ozino