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.

TMS320F28377D: CPU1 not receiving update of shared arrays, whereas CPU2 can

Part Number: TMS320F28377D


Hi,

I am trying to pass data from one CPU1 to CPU2 and vice-versa in the form of arrays. I have been successful in transferring data from CPU1 to CPU2, whereas it does not seem to work the other way around.

The two arrays, with #pragma statements for memory allocation are the following:

 

#pragma DATA_SECTION(mT,"Cpu1ToCpu2RAM")
uint16_t	mT[4];

#pragma DATA_SECTION(iT,"Cpu2ToCpu1RAM")
uint16_t    iT[2];

mT is updated in CPU1 and if passed to CPU2 in the following ISR, triggered by CPU1: 

interrupt void probe_CPU2(void)
{

    // stuff to ship to CPU2 dummy update --------------------
    if((ISR_count1 % 40000) == 0){
        slider1++;
        slider2 += 2;
    }

	// Communicate with CPU2 via IPC
	SendDataToCpu2 = slider1;
	SendAddrToCpu2 = slider2;
	IpcRegs.IPCSENDDATA = (Uint32) SendDataToCpu2;		// Write the result to the IPC data register
	IpcRegs.IPCSENDADDR = (Uint32) SendAddrToCpu2;		// Write the result to the IPC addr register
	IpcRegs.IPCSET.bit.IPC1 = 1;						// Set the IPC1 flag for CPU2

	RecDataFromCpu2 = (Uint16) IpcRegs.IPCRECVDATA;		// Read data on IPC data register
	RecAddrFromCpu2 = (Uint16) IpcRegs.IPCRECVADDR;		// Read data on IPC addr register

	// Arrays management
	// Transfer modulation signals from CPU1 to CPU2
	mT[0] = slider1;
	mT[1] = slider2;
	mT[2] = slider1;
	mT[3] = slider2;

	// data updated by CPU2 --- NOT WORKING!!!
	input1 = iT[0];
	input2 = iT[1];

	PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;     // Acknowledge PIE group 3 to enable further interrupts
	EPwm2Regs.ETCLR.bit.INT = 1;                // Clear EPWM1_INT flag to allow further interrupts

}

This ISR sets the IPC1 flag for CPU2 to respond with the following ISR (where iT is modified):

interrupt void ipc1_isr(void)
{

	// Read data from CPU1
	temp1 = (Uint16) IpcRegs.IPCRECVDATA;
	temp2 = (Uint16) IpcRegs.IPCRECVADDR;

	// Send data back to CPU1 multiplied
	IpcRegs.IPCSENDDATA = (Uint16) temp1*4;			// send CPU2.CLA response back to CPU1
	IpcRegs.IPCSENDADDR = (Uint16) temp2*4;

	ISR_count1_cpu2++;  // ISR coutner

	if(ISR_count1_cpu2 % 20000 == 0){

	    dummy1++;

	    iT[0] = dummy1;
	    iT[1] = dummy1 + 1;
	}


	// Return from interrupt house keeping
	IpcRegs.IPCACK.bit.IPC1 = 1;				// Clear IPC1 bit
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;		// Acknowledge PIE group 1 to enable further interrupts

}

Debugging I have no problem in seeing mT updated correctly in CPU2. I can also see iT updated correctly in CPU2, however I cannot see any modification of iT seen by CPU1, as input1 and input2 variables remain always 0 and not updated with the actual new value of iT, which is indeed modified by CPU2. 

It seems as if I can modify mT from CPU1 and make it visible to CPU2, and that is ok, whereas it seems that although I can modify iT array in CPU2 I cannot see that modification taking place for CPU1.

Any help would be really appreciated. 

Many thanks,

Nicola 

  • As an update, I was actually able to see that the following commands:

    #pragma DATA_SECTION(mT,"Cpu1ToCpu2RAM")
    uint16_t mT[4];

    #pragma DATA_SECTION(iT,"Cpu2ToCpu1RAM")
    uint16_t iT[2];

    do not actually identify the same memory address for the two different CPUs, although defined in the same way. This happens for the second array only. In other words the addresses in memory are the same seen from CPU1 and CPU2 debugger for mT array, yet they are different for iT. I checked the sections of memory in the .cmd file, yet they seem to be consistent. Any suggestion?

    Many thanks,

    Nicola

  • Hi Nicola,

    Are you defining the same variables in both the projects? This may not guarantee that the variables gets assigned to the same address in both cores, as they are both independent CCS projects. This could happen if you have multiple sections allocated to the Cpu1ToCpu2RAM / Cpu2ToCpu1RAM.

    Few ways to resolve the issue would be - 

    1) Define the variable in only one project and pass the address of the arrays to CPU2 using IPC, during initialization

    2) Have separate sections for each of the global you need to allocate to MSGRAM

    #pragma DATA_SECTION(mT,"Cpu1ToCpu2RAM_1")
    uint16_t mT[4];
    
    #pragma DATA_SECTION(iT,"Cpu2ToCpu1RAM_1")
    uint16_t iT[2];
    
    
    #pragma DATA_SECTION(otherVar,"Cpu1ToCpu2RAM_2")
    uint16_t otherVar[4];
    
    #pragma DATA_SECTION(otherVar,"Cpu2ToCpu1RAM_2")
    uint16_t otherVar[2];

    In linker cmd file, you could use GROUP to ensure the sections are allocated in the exact same order

        GROUP : > CPU1TOCPU2RAM
        {
            Cpu1ToCpu2RAM_1
            Cpu1ToCpu2RAM_2
        }

    3) instead of using DATA_SECTION pragma, you could use the LOCATION pragma to enforce the linker to allocate the array in specified memory location

    Sample usage : 

    #pragma LOCATION( x , address )
    int x;

    Regards,

    Veena

  • Hi Veena,

    thanks. 

    Yes I have been assigning the #pragma statement in both projects. 

    Thanks for the suggestions I will try them out.

    Regards,

    Nicola

  • Hi Nicola,

    Here is the response from the compiler team - 

    The article Methods to Force an Ordering of Global Variables shows how to put one or more variables at a specific address.  In your case, two projects would have to share code that does this.  With regard to the source files that implement it, I recommend they reside in one place outside of the two CCS projects, then link those files into each project as described here.  Remember that the linker command file can also #include files.  It is a best programming practice to define important details,  such as the base address of shared memory, in exactly one place, then automatically propagate it to all the other places that require it.

    Regards,

    Veena