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.

C2000WARE-DIGITALPOWER-SDK: Accessing ADC sensor signals from two different CLAs

Part Number: C2000WARE-DIGITALPOWER-SDK
Other Parts Discussed in Thread: C2000WARE

Hi,

I have an input voltage measurement that I am planning to use in two different control algorithms, on two different CLA cores. 

Would the below code be suitable to initalise the variables, or is there something more appropriate? I am essentially defining a single variable, then defining sections in memory for it to be available to both CLA cores. I am unsure if this is excessive, because I do not fully understand the purpose of the DATA_SECTION statement.

#pragma DATA_SECTION(inputVolts,"Cla1ToCpuMsgRAM")
uint32_t inputVolts=0;

#pragma DATA_SECTION(inputVolts,"Cpu1ToCpu2MsgRAM")

And then in the second CPU:

#pragma DATA_SECTION(inputVolts,"Cpu2ToCla2MsgRAM")

Is there a way that CLA2 and CPU2 can access the shared variable without all these extra data_section statements? it seems a waste to define spaces in memory that contains a variable that already exists in another section, but this seems to be the way that TI defines memory that is accessible across the cores?

Thanks,

Joel

  • just to note: I am performing all of my ADC conversions on the CPU1 and just using CPU2 to handle IPC communications and launching of the second CLA - and that's why I need to define a variable that I place the sensor results in that can be viewed/accessed by the CPU1, CLA1 and CLA2. Because it needs to be accessed by CLA2, it also needs to be visible by CPU2, if I am correct. 

  • Joel,

    Are you using an existing solution provided in the DigitalPower SDK? Which device are you trying to implement this software on?

    Have your referenced the IPC examples in C2000Ware to understand how to handle the communication part?

    Regards,

    Ozino

  • Hi Ozino,

    I am not, I am developing the digital power algorithms on top of a solution I have created myself - although I have used some previous examples to understand how to lay everything out.

    I did see the IPC examples but found that they were not sufficient as they are written in the new digital library functions whereas I have been writing my code with the direct register access method and therefore a lot if not all of the code doesn't make much sense to me, for example there is no programming of an ISR, CPU Timer registers, or any #pragma statements to define variables that are shared between cores. There is also no comms between the CPUs and their CLAs. However, I do generally understand how the IPC works etc. 

    The biggest headache at the moment is just how to properly define the variables with #pragma statements, so that they are readable and writeable by the respective CPU and CLA cores that I need them on - some variables need to be readable and/or writeable by both CPUs and their respective CLAs.

    Best wishes,
    Joel

  • Hi Joel,

    The following link gives details on memory regions that are shared between the different CPU and CLA cores for F2838x family of devices and should serve as a good starting point to understand how to place a variable such that two cores can access it. If you are working with a different device, please check the TRM and datasheet for memory regions. The pragma is essentially a way of allocation the variable specifically to one of the memory blocks.

    https://software-dl.ti.com/C2000/docs/C2000_Multicore_Development_User_Guide/index.html


    The C2000 devices do not have a memory that is shared across all the C28 and CLA cores.


    Please could you let me know what device you are working with? I will sync up with the experts and get back to you with any suggestions they may have for your usecase.


    Thanks,

    Ashwini

  • Hi Ashwini, 

    My device is the F2837xD.

    Look forward to the replies - thanks for the above comments!

    Joel

  • What I mean regarding accessing sensor data on CPU1 via the CLA on CPU2 is this:

    > send data from CPU1 to CPU2
    > send this same data from CPU2 to the CLA 

    I am unsure whether I can do this in the way I stated in the original post, where inputVolts is assigned as a memory block for CPU1, CPU2 and CLA2 using the same variable, or something like this would be better:

    #pragma DATA_SECTION(inputVolts,"Cla1ToCpuMsgRAM")
    uint32_t inputVolts=0;

    #pragma DATA_SECTION(inputVolts,"Cpu1ToCpu2MsgRAM")

    uint32_t temp = 0;

    temp = inputVolts;

    And then in the second CPU:

    #pragma DATA_SECTION(temp,"Cpu2ToCla2MsgRAM")

    Since I am unsure whether you can share the names of variables in diff. data sections in the memory map. Hope that makes more sense.

  • Hi Joel,

    You can only assign the variable to one section. It is just an instruction to the compiler/linker to allocate the variable in the specified memory region.

    I believe your requirement is to share a variable from CPU1 to CPU2's CLA. There is no RAM region which is accessible to both CPU1 and CLA2. You need to share the variable first to CPU2 and then to CLA2.

    If the data you need to share is just a 32 bit word(or 3 32-bit words), you can use IPC command registers to share the same with CPU2. IPC command registers include SENDCOM, SENDDATA, and SENDADDR. Even though they are named command, data and address, you can use it to send any 32-bit value. CPU1 can write to these registers and the CPU2 can read it from the receive registers RECVCOM, RECVDATA, RECVADDR. You can directly read and write to these registers using the IPC bitfield structs

    In case you have a bigger block of data to share, you can use CPU1TOCPU2MSGRAM and use these command registers to share the address data size, or other information. You need to use DATA_SECTION pragma to allocate the data in the MSGRAM.

    You can refer to the device TRM and the MultiCoreDevelopment guide Ashwini had shared for more details.

    Once the CPU2 receives the value through command registers/MSGRAM, CPU2 need to copy them in the CPUTOCLAMSGRAM so that CLA can read it. You need to use the DATA_SECTION pragma to allocate the data in the CLAMSGRAM.

    Regards,

    Veena

  • Hi Veena,

    Thanks, this helps. However it leads me to more questions. In my linker file, I have the following:

    /* CLA sections */
    Cla1Prog : > RAMLS4_5, PAGE = 0
    CLADataLS0 : > RAMLS0, PAGE = 1
    CLADataLS1 : > RAMLS1, PAGE = 1

    Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1
    CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1

    Cpu1ToCpu2RAM : > CPU1TOCPU2RAM, PAGE = 1
    Cpu2ToCpu1RAM : > CPU2TOCPU1RAM, PAGE = 1

    #ifdef CLA_C

    CLAscratch :
    { *.obj(CLAscratch)
    . += CLA_SCRATCHPAD_SIZE;
    *.obj(CLAscratch_end) } > RAMLS1, PAGE = 1

    .scratchpad : > RAMLS1, PAGE = 1
    .bss_cla : > RAMLS1, PAGE = 1
    .const_cla : > RAMLS1, PAGE = 1
    #endif


    /* The following section definitions are required when using the IPC API Drivers */
    GROUP : > CPU1TOCPU2RAM, PAGE = 1
    {
    PUTBUFFER
    PUTWRITEIDX
    GETREADIDX
    }

    GROUP : > CPU2TOCPU1RAM, PAGE = 1
    {
    GETBUFFER : TYPE = DSECT
    GETWRITEIDX : TYPE = DSECT
    PUTREADIDX : TYPE = DSECT
    }

    I would assume I need to modify such that I assign memory for a new set of variables that are shared between CPU2 and CLA2, called Cpu2toCla2MsgRAM and Cla2toCpu2MsgRAM... but how do I check where in memory is free for me to allocate? Since LS0, LS1 and LS4 and LS5 are used, this leaves only LS2 and LS3 available, but how do I know how to do this? There is no CLA2_MSGRAMHIGH or CLA2_MSGRAMLOW - how do I define sections of memory that are for CLA2 and CPU2?

  • You mention you can only assign the variable to one section. 

    Can you assign multiple different variables to a single section?

    To be more clear, I need to send to CPU2 4 variables, which is 1 simple float value and 3 ADC samples from CPU1. 

    I then calculate a control effort from DCL library with CLA2, give that information back to CPU2, and then send that through IPC back to CPU1, which I will then use to modulate the PWM module duty cycle.

    Hopefully with an idea of my application in mind it may be easier to help with the best process to do this?

  • Can you assign multiple different variables to a single section?

    Yes, you can put multiple variables in one section. In the linker command file, this section is mapped to a memory region. The variables defined in this section will be allocated in this specific memory region, but at different addresses. 

    The CLA has direct access to the ADC result registers. Once the ADC results are available, you can trigger the CLA task and read them directly as well.

    Regards,

    Veena

  • Okay, great.

    Regarding the CLA access - I am measuring all ADC results on the CPU1, but need to access those results in CPU2 and CLA2. Hence why I have been asking about IPC and memory mapping for CLA2 and CPU2. 

    I am now much clearer on CPU1 and CLA1 memory mapping - but there is nothing in the linker file for CLA2 and CPU2, and I am unsure how I should add this, because I need to define some memory for the CLA2 and CPU2 programs themselves, and then two more for their communications, but I only have two LSB memories left. 

  • Hi Joel,

    The memory map for CPU1 is same as CPU2 for where the LS and CLA MSG RAMs are located. Each CPU1 and CPU2 has its own  independent LS and CLA MSG RAM. The device datasheet has a section on "memory map" which details this information.

    Thanks,

    Ashwini

  • Hi Joel,

    You can use the 2837xD_FLASH_lnk_cpu2.cmd file as the reference and add CLA specific sections. 2837xD_FLASH_lnk_cpu2.cmd and 2837xD_FLASH_lnk_cpu1.cmd are almost same except the starting address of RAMM0 and IPC sections.

    As Ashwini mentioned, the LS RAMs and CLA MSG RAM are at the same address as in CPU1. LSRAMs and CLA MSG RAM are dedicated to each CPU. Even though they use the same address, they are physically different memories and is not accessible by the other CPU. 

    Regards,

    Veena

     

  • Hi Joel,

    Please let us know if you need any other inputs. For now, I am marking this thread as resolved, feel free to let us know if you have additional questions.

    Thanks,
    Ashwini

  • Hi Ashwini,

    I am still confused about one specific thing regarding sharing of information between my local CPU and the CLAs.

    If I have a variable, let's call it sensor_one. I want to sample an ADC and assign the result to sensor_one. I then want to send sensor_one to the local CPU CLA, to perform some control calculations, and return this back to the local CPU. 

    I then want to make this available to CPU2, for some reason (theoretically).

    The question is simple: Would I need to define multiple locations in memory for this single variable?

    If so, can it have the same name? Or is it best to assign a new name to it for every core it is used in?

    Could I for example write the following code:

    #pragma DATA_SECTION(fromCPU2,"Cpu2ToCpu1RAM")
    int32_t sensor_one[16];

    #pragma DATA_SECTION(fromCPU2,"Cpu1ToCpu2RAM")
    int32_t sensor_one[16];

    #pragma DATA_SECTION(fromCPU2,"CpuToClaRAM")
    int32_t sensor_one[16];

    Obviously, in the correct and respective cores that these definitions need to be in.

    Thanks!

  • Hi Ashwini, still struggling very much with the concept of defining memory regions for a sensor signal that needs to be accessed by CPU1/CLA1, and by CPU2/CLA2. In my example, inputVolts refers to the input voltage that I will be using for feed-forward control. I am using it within both CLAs and the DCL controller .asm code.

    I get the following warning:

    "../MPM_CPU1.c", line 108: warning #1508-D: variable "inputVolts" has incompatible section specifications, CpuToCla1MsgRAM and Cpu1ToCpu2MsgRAM, CpuToCla1MsgRAM will be used

    Does this mean I have an issue with how I have defined the memory sections?

    Would it be better to assign a temporary variable, which is then defined in memory for CPU1 to CPU2 communications, and then again for CPU2 communications. This seems a bit clunky:

    > read ADC, assign to inputVolts1, inputVolts2: assign memory for inputVolts1 for CPU1 to CPU2, and inputVolts2 for CPU1 to CLA1.
     

    In CPU2, read inputVolts1, assign to inputVolts3, and communicate that between CLA2 and CPU2. Send this information back to CPU1 after assigning the new, modified value back to inputVolts1. 

    There must be a better way than this!

    Regards,

    Joel

  • If it would be suitable, I could send my project to an engineer at Texas Instruments, who may possibly have a look through all of my codes and assist. Is this something that TI are able to provide as a service?

  • Hi Joel,

    It may become difficult for us to understand the code just by reading it. I think it may help to think about the system design. As I understand it, the ADC value is being captured in a variable inputVolts on CPU1 and other cores CPU2, CLA1 and CLA2 need to use it. There are 2 ways to address this:

    1. Both CLAs 1 and 2 and C28 CPUs 1 and 2 have access to the ADC results register. So instead can you redesign your system such that each get it directly from reading the ADC results register?

    2. If the above is not possible, here is another suggestion - place the CPU1 inputVolts  in LSxRAM. LSxRAM is accessible by CPU1 and CLA1 so both can use it. Use IPC to have CPU2 get  the inputVolts value via a copy to the CPU1-CPU2 shared RAM. At this point now CPU2 has a copy that it can use. Have CPU2 copy that over to it's own LSx or CPU2-CLA2 message RAM and now the copy is available for CLA2. In other words, you will need to have one section mapping the inputVolts to the LSxRAM at compile time and then the application will need to be written to copy this variable over to other memories at run time for other cores to use it.

    Please see section 7.6 of the TRM for the IPC communication.

    https://www.ti.com/lit/ug/spruhm8i/spruhm8i.pdf

    Thanks,

    Ashwini