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.

TMDSECATCNCD379D: DSP Dual CPU Usage

Part Number: TMDSECATCNCD379D

Hi,

I want to communicate with EtherCAT using dual CPU. I did EtherCAT communication for CPU 1 in DSP. I want to define CPU 2 to DSP and send EtherCAT data from CPU 1 to CPU 2. Also, I will communicate with the driver use the SPI or CAN communication protocol in CPU 2.

I am waiting for your help.

DSC_CPU1

Kind regards.
Thanks.
Sinan.
Good days.
  • Hi Sinan,

    For guidance on communicating between the CPU1 and CPU2 of the F2837xD device, you can take a look at the 'cpu01_to_cpu02_ipcdrivers' software examples in C2000WARE for inter processor communication between the two cores. Directories below.

    C:\ti\c2000\C2000Ware_3_04_00_00\device_support\f2837xd\examples\dual

    Also, I will communicate with the driver use the SPI or CAN communication protocol in CPU 2.

    What will you be communicating with over SPI/CAN exactly? A motor driver you mean and if so is it a TI device?

    Best,

    Kevin

  • Hi, Kevin:

    Thank you very much for your feedback to me. I am grateful to you.

    I've looked at the example of dual CPU usage on device F2837xD. The sample application is very good.

    I will communicate with the an motor driver using the SPI, CAN or EtherCAT communication protocol on CPU 2. My motor driver is not a TI device. My motor is AC/DC servo. There is a different microcontroller (MCU) in the motor driver. I will send the data I received from EtherCAT with CPU 1 from CPU 2 to this MCU.

    Very thanks.
    Sinan.
    Kind regards.

  • Hi Sinan,

    Happy to hear the software example has helped you.

    OK, I better understand your system and topology now. By the way, you can find CAN and SPI software examples for the F2837xD device in C2000WARE as well. They are written for CPU1, but you can make necessary edits to the examples to run on CPU2. Directory location below:

    C:\ti\c2000\C2000Ware_3_04_00_00\device_support\f2837xd\examples\cpu1

    Best,

    Kevin

  • Hi,

    I am trying to make the following application.

    C:\ti\controlSUITE\device_support\F2837xD\v210\F2837xD_examples_Dual\cpu01_to_cpu02_ipcdrivers

    I am successfully doing EtherCAT communication on CPU 1. I am using ET1100 ESC (EtherCAT Slave Controller) for EtherCAT communication. However, on CPU 1, both EtherCAT communication and CPU 2 communication (IPC) do not work together. What do you think could be the reason?

    Also I will send the data I get from EtherCAT with CPU 1 to CPU 2.

    My 'cpu01_to_cpu02_ipcdrivers_cpu01.c' main code:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    \addtogroup TMDSECATCNCD379D_AIR TMDSECATCNCD379D_AIR
    @{
    */
    /**
    \file TMDSECATCNCD379D_AIR.c
    \brief Implementation
    \version 1.0.0.11
    */
    #include "F28x_Project.h"
    #include "F2837xD_Ipc_drivers.h"
    #include <stdint.h>
    #include "ecat_def.h"
    #include "applInterface.h"
    #define _TMDSECATCNCD379_D__AIR_ 1
    #include "TMDSECATCNCD379D_AIR.h"
    #undef _TMDSECATCNCD379_D__AIR_
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Very thanks.
    Sinan.

  • Hi Sinan,

    When debugging your project in CCS what line of code do you get to? It looks like you combined the F2837x ET1100 and IPC projects together. Did you run the IPC projects by themselves first to understand how they run together?

    Note that your cpu01() function has a never ending for loop at the end.

    Best,

    Kevin

  • Hi, Kevin:

    I can reach the following line of code while debugging CCS in my project. When this line of code is reached, the program halt.

    Fullscreen
    1
    2
    3
    4
    5
    6
    //
    // Read 32-bit word from CPU02 32-bit write word variable. Use IPC Flag 18 to
    // check when read data is ready.
    //
    IPCLtoRDataRead(&g_sIpcController1, pulMsgRam[1], &ulRWord32,
    IPC_LENGTH_32_BITS, ENABLE_BLOCKING, IPC_FLAG18);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    The program halt at the following line of the 'IPCLtoRDataRead' function.

       status = IpcPut (psController, &sMessage, bBlock);

    The 'IPCLtoRDataRead' function is in the code file below.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //###########################################################################
    //
    // FILE: F2837xD_Ipc_Driver.c
    //
    // TITLE: F2837xD Inter-Processor Communication (IPC) API Driver Functions.
    //
    // DESCRIPTION:
    // 28x API functions for inter-processor communications between the
    // two CPUs. The IPC functions require the usage of the CPU1 to CPU2
    // and CPU2 to CPU1 MSG RAM's to store the circular ring
    // buffer and indexes. Commands can be queued up in order on a single
    // IPC interrupt channel. For those IPC commands which are not
    // interdependent, multiple IPC interrupt channels may be used.
    // The driver functions in this file are available only as
    // sample functions for application development. Due to the generic
    // nature of these functions and the cycle overhead inherent to a
    // function call, the code is not intended to be used in cases where
    // maximum efficiency is required in a system.
    // NOTE: This source code is used by both CPUs. That is both CPU1 and CPU2
    // Cores use this code.
    // The active debug CPU will be referred to as Local CPU.
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I first carried out IPC projects on my own. However, the 'cpu01_to_cpu02_ipcdrivers' project did not work as intended. The CPU02 write and read variables could not be displayed with their defined values. Could there be a bug in the software example 'cpu01_to_cpu02_ipcdrivers' in C2000WARE? 

    Thanks.
    Sinan.

  • Sinan,

    I am looking into this. I will get back to you by tomorrow.

  • Sinan,

    I just tested the C2000ware example 'cpu01_to_cpu02_ipcdrivers'. It work fine on my system.

    I will recommend you to put the break point in IPC ISR for CPU1 and CPU2, then step through the code in main() on CPU1. You will follow the sequence of Write/Read between both cores, and ErrorCount and ErrorFlag global variables should be 0.

  • Hi, Santosh:

    How did you test the C2000ware example 'cpu01_to_cpu02_ipcdrivers'? 

    I did what you said. But the example did not work properly.

    My CCS version is 7.2.0.00013. Also my CCS compiler version is v16.12.0.STS.

    The CPU01 debug screen is as follows:

    The CPU02 debug screen is as follows:

    'cpu01_to_cpu02_ipcdrivers_cpu01' project properties are as follows:

    'cpu01_to_cpu02_ipcdrivers_cpu02' project properties are as follows:

    I load programs on cpu01 and cpu02 separately. also I run programs on separately.

    Do I need to make any hardware settings (jumpers, switches) on the TMDSECATCNCD379D evaluation board? How did you load the program (.out) to the F2837xD DSP? Also how did you run it on hardware?

    Thanks.
    Sinan.

  • Sinan,

    There is no change in hardware setting. Default setting is good. I ran on Launchpad, but it should work same way on controlCARD.

    I am using CCS 10.1. version with compiler 20.1.xx.

    Connect CPU1 and CPU2, then load the images. Set the breakpoints in ISRs as I mentioned in previous post, then let CPU2 in free run.

    Then on CPU1, again set the breakpoints in ISRs, and step-through the code. You should see the ISR on CPU2 is triggered. Then follow the sequence.

  • Hi, Santosh:

    I set breakpoints on the ISRs, then CPU2 in free run.

    Then I went step-by-step through the code on CPU1. The program halted at the following code block on CPU2. 

    In addition, the program halted in the code block below.

    I am waiting for your help.

    Thanks.
    Sinan.

  • Sinan,

    Follow this sequence:

    • Launch the target configuration, and connect CPU1 and CPU2.
    • Load program to CPU1, it should halt in main() function
    • Load program to CPU2, this should also halt in main() function.
    • Now open file,  cpu01_to_cpu02_ipcdrivers_cpu02.c, and set breakpoints in functions 

      CPU01toCPU02IPC0IntHandler (void) and CPU01toCPU02IPC1IntHandler (void). These are IPC interrupt handler ISR for IPC for CPU2. Let CPU2 Free Run now.

    • Now open file,  cpu01_to_cpu02_ipcdrivers_cpu01.c, and set breakpoints in functions CPU02toCPU01IPC0IntHandler (void) and

      CPU02toCPU01IPC1IntHandler (void). These are IPC interrupt handler ISR for IPC for CPU1.

    • Now step through the code on CPU1, it will spin in here
    • Fullscreen
      1
      2
      3
      4
      5
      6
      7
      //
      // Spin here until CPU02 has written variable addresses to pulMsgRam
      //
      while(IpcRegs.IPCSTS.bit.IPC17 != 1)
      {
      }
      IpcRegs.IPCACK.bit.IPC17 = 1;
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    • On CPU2, it should trigger ISR on CPU2.
    • Now follow the sequence.
  • In your picture, can you set breakpoint in line # 275, and then free-run? Does it break-point?

  • Hi, Santosh:

    I followed the sequence you specify me. 'cpu01_to_cpu02_ipcdrivers' example worked incorrectly as in the video below.

    Sinan.

  • Hi,

    Looking at the video, it seems it is completing the flow. It goes in the infinite loop in CPU1, there is no error. You can see that you are hitting the CPU2toCPU1IPC handler.

    Only issue, I see is that CPU2 is free running, the breakpoint you set did not enable, and it is working in free-run mode.

  • Hi, Santosh:

    In your picture, can you set breakpoint in line # 275, and then free-run? Does it break-point?

    line# 271 is not a break-point. The program halted at line #271 (infinite loop). In the picture, I set a breakpoint on line #275 and then free-run it.

    In addition, the program halted in the code block below.

    I am waiting for your help.

    Thanks.
    Sinan.

    Variables expressions (line #275):

    Variables expressions (line #304):

    As seen in the last picture 'cpu01_to_cpu02_ipcdrivers' example did not work correctly.

    Sinan.

  • Hi Sinan,

    In previous post, you mentioned that it gets halted earlier, and not going to the end of program.

    Now let's look at the values:

    Line#247
    usWWord16 = 0x1234;
    ulWWord32 = 0xABCD5678;
    usRWord16 = 0;
    ulRWord32 = 0;

    Line#304
    usWWord16 = 0x1234;
    ulWWord32 = 0xABCD5678;
    usRWord16 = 0x1234;
    ulRWord32 = 0xABCD5678;

    Line#313 -> Set Bit Mask for 16-bit
    // Set upper 8 bits in 16-bit write word variable location.
    so usRWord16 should be 0xFF34 i.e. 65332

    Line#326 -> Set Bit Mask for 32-bit
    // Set upper 8 bits in 16-bit write word variable location.
    so ulRWord32 should be 0xFFFF5678

    Do you see similar values?

    It looks like your code and my code line numbers are not lined up. I am wondering why is that. Did you import the project from C2000ware 3.04.00.00? Did you make any change in code?

  • Hi,

    I've seen similar values (Line#247, Line#304, Line#313 and Line#326).

    I tried the two project examples below. Both examples did not work on the the TMDSECATCNCD379D evolution board.

    C:\ti\c2000\C2000Ware_3_04_00_00\device_support\f2837xd\examples\dual\cpu01_to_cpu02_ipcdrivers

    C:\ti\controlSUITE\device_support\F2837xD\v210\F2837xD_examples_Dual\cpu01_to_cpu02_ipcdrivers

    I did not make any changes to the codes.

    Finally, the variables looked wrong as in the picture below.

    Thanks.

    Sinan.

  • Are you using example 

    C:\ti\controlSUITE\device_support\F2837xD\v210\F2837xD_examples_Dual\cpu01_to_cpu02_ipcdrivers

    or C2000Ware ?

    Also, if you are seeing same values at these lines, then IPC driver is working fine.

    What is value of ErrorFlag, ErrorCount?

  • Hi,

    I am using the example below.

    C:\ti\controlSUITE\device_support\F2837xD\v210\F2837xD_examples_Dual\cpu01_to_cpu02_ipcdrivers

    However, I also tried the C2000Ware example.

    The program entering an infinite loop on Line#731.

    Finally, the variables looked wrong as in the picture below.

    Thanks.

    Sinan

  • Sinan,

    I am not able to understand the issue and cannot reproduce the issue on my setup, it is working fine.  

    Let's use C2000ware example for debugging purpose. 

    What is value of ErrorFlag, ErrorCount?

    What is the compiler version and CCS version you are using?

  • Hi, Santosh:

    I am using the C2000ware instance for debugging purposes. I am using CCS 7.2.0.00013 version with compiler TI v20.2.5.LTS.

    The values of ErrorFlag and ErrorCount are zero (0).

    Are the variable values shown in the image below correct? In the picture, the variables 'Write' and 'Read' are not equal.

    DualDSP

    Thanks.

    Sinan.

  • Siran,

    Please refer to my previous post. Write and Read  values can be different based on bit-mask set using function IPCLtoRSetBits()

  • Hi, Santosh:

    usWWord16 = 0x1234;
    ulWWord32 = 0xABCD5678;

    usRWord16 = 0x1234;
    ulRWord32 = 0xABCD5678;

    What should I do to see these results? Which IPCLtoRSetBits() function do I need to disable?

    Sinan.

  • Siran,

    ipc driver allows multiple ways to communicate between cpu1 and cpu2. I will refer you to user's guide for complete details. The user's guide is located at 

    C:/ti/c2000/C2000Ware_3_03_00_00/device_support/f2837xd/docs/F2837xD_IPC_Driver_UG.pdf

    Coming back to communications mode:

    • Mode1 : you want to send the data and receive same data. In that case, you do not need to call IPCLtoRSetBits or IPCLtoRClearBits.  Just call IPCLtoRDataWrite() and IPCLtoRDataRead().

    • Mode2 : You can set any bit mask or clear the bits. Which has been demonstrated further in the example. 

    • Mode3 : Here you can set function call. There are two types function calls, function call with no parameter, in that it returns 1, as indicator of success. That is what you are seeing. Function call with one parameter. In this case, it returns the value.

    In your previous picture, you are seeing '1' as you are using pulMsgRam[3] (please read the comment above the line).

    .  If you want to see same value using function call, then change the code something like below - use pulMsgRam[4]

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //
    // Check Function Call Function
    //
    //
    // Call FunctionCall() function on CPU02 with a dummy parameter of "0"(i.e. no
    // parameter).
    //
    // IPCLtoRFunctionCall(&g_sIpcController1, pulMsgRam[3], 0, ENABLE_BLOCKING);
    IPCLtoRFunctionCall(&g_sIpcController1, pulMsgRam[4], 0xABCD,
    ENABLE_BLOCKING);
    //
    // Read status variable to check if function was entered. Use IPC Flag 17 to
    // check when read data is ready.
    //
    IPCLtoRDataRead(&g_sIpcController1, pulMsgRam[5], &usRWord16,
    IPC_LENGTH_16_BITS, ENABLE_BLOCKING,
    IPC_FLAG17);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Hope this helps.

  • Hi, Santosh:

    First of all, thank you very much for your feedbacks. I am thankful to you. 

    I have read the user's guide you mentioned. (F2837xD_IPC_Driver_UG.pdf) This user's guide helped me a lot.

    I have another problem right now. I want to use the 'usWWord16' variable in CPU 1 on CPU 2.  I want to transfer the content of 'usWWord16' variable in CPU1 to 'test_usWWord16' variable in CPU2.For this, I wrote the following code on CPU 2.

    Fullscreen
    1
    2
    3
    IPCLtoRDataRead(&g_sIpcController1, pulMsgRam[0], &test_usWWord16,
    IPC_LENGTH_16_BITS, ENABLE_BLOCKING,
    IPC_FLAG17);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I added line#225 in CPU 2.

    But this code didn't work.

    Sinan.

  • Sinan,

    in file cpu01_to_cpu02_ipcdrivers_cpu02.c

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //
    // Function Prototypes
    //
    __interrupt void CPU01toCPU02IPC0IntHandler(void);
    __interrupt void CPU01toCPU02IPC1IntHandler(void);
    void FunctionCall(void);
    void FunctionCallParam(uint32_t ulParam);
    void Error (void);
    uint16_t test_usWWord16 = 0;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    __interrupt void
    CPU01toCPU02IPC0IntHandler (void)
    {
    tIpcMessage sMessage;
    //
    // Continue processing messages as long as CPU01toCPU02 GetBuffer1 is full
    //
    while(IpcGet(&g_sIpcController1, &sMessage,
    DISABLE_BLOCKING)!= STATUS_FAIL)
    {
    switch (sMessage.ulcommand)
    {
    case IPC_SET_BITS:
    IPCRtoLSetBits(&sMessage);
    break;
    case IPC_CLEAR_BITS:
    IPCRtoLClearBits(&sMessage);
    break;
    case IPC_DATA_WRITE:
    IPCRtoLDataWrite(&sMessage);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    In cpu01_to_cpu02_ipcdrivers_cpu01.c file, it is sending random value 0x5432. Please see below.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //
    // Spin here until CPU02 has written variable addresses to pulMsgRam
    //
    while(IpcRegs.IPCSTS.bit.IPC17 != 1)
    {
    }
    IpcRegs.IPCACK.bit.IPC17 = 1;
    //
    // 16 and 32-bit Data Writes
    // Write 16-bit word to CPU02 16-bit write word variable.
    //
    IPCLtoRDataWrite(&g_sIpcController1, pulMsgRam[0], 0x5432,
    IPC_LENGTH_16_BITS, ENABLE_BLOCKING,NO_FLAG);
    // IPCLtoRDataWrite(&g_sIpcController1, pulMsgRam[0],(uint32_t)usWWord16,
    // IPC_LENGTH_16_BITS, ENABLE_BLOCKING,NO_FLAG);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi,

    The program waiting at Line#699 in the cpu01_to_cpu02_ipcdrivers_cpu01.c file.

    I did not make any code changes to the cpu01_to_cpu02_ipcdrivers example in C2000Ware_3_04_00_00. I just combined CPU1 with another project.

    The values of ErrorFlag and ErrorCount are zero (0).

    When I run the program, I can't write and read data to cpu2. What could be the reason for this?

    Thanks.

    Sinan.

  • Sinun,

    Please read the comment above. Do you have cpu2 loaded and free running? If it is not running, it will get stuck here.

    If cpu2 is free running, then set the breakpoint following line and run.

    IpcRegs.IPCACK.bit.IPC17 = 1; 

    Earlier, you were able to run much further, what happened? How did you backward? What changed? I am sure you can debug this code.

  • Hi, Santosh:

    CPU2 is loaded and running free. I set the breakpoint following line and run.

    IpcRegs.IPCACK.bit.IPC17 = 1;

    The program does not proceed step by step after the Line#730. The program does not halted at the breakpoints on Line#739 and Line#743. The program working directly.

    Actually everything was going well. However, I integrated another working project into cpu1 and combined it. I did not make any changes to the cpu01_to_cpu02_ipcdrivers_cpu01.c main code.

    Thanks.

  • Sinan,

    Probably something is conflicting. You may want to clean, and rebuild for both cores and try again.

    I am not sure what you have added in this project and what is the effect. You may want to go to working state and then add piecewise and debug from there.

  • Hi, Santosh:

    I have a project where I communicate with EtherCAT. This project works fine. In this project, I want to send the data I receive with EtherCAT to cpu2.

    How can I make cpu2 communication to this project I am working with EtherCAT?

    Thanks.

  • Sinan,

    If you want to use the ipc driver, then integrate the two projects, and make incremental change so that you can check if it continue to work. and narrow the issue if it fails.

    If you have not gone through, you can take a look at online workshop at following link. This comes with IPC exercise. if your data transfer need is simpler, then you can implement something similar to what is demoed in the lab.

    https://training.ti.com/c2000-f2837xd-microcontroller-1-day-workshop-part-7-8-inter-processor-communications-ipc