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.

CLA Data read from shared memory issue - F28069

I am running into some strange issue with the CLA reading the shared data in CLARAM2, which I make readable from C28 side as follows:

Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM2CPUE;

I put a buffer (type short) that collects ADC data into the shared RAM and at the end of a 60Hz line cycle it is used to calculate the RMS. For testing purposes, I have two identical RMS computing routines running from C28 and CLA (task1). These two routines process the same data buffer configured exactly the same (in CLARAM2). When I run the RMS calculation from the C28 it reads and compute the RMS values with no problem. However, when I try to run the RMS from CLA by calling Cla1ForceTask1(), it always returns zero. I put some breakpoints in the CLA routine and see that when it reads the buffer it always gets zero out of it.

Looking at the map file, I can verify all the CLA program and data to be properly located in the intended memory. The MMEMCFG register looks good through the watch window. Also all CLA and CPU interrupts are checked and the CLA seems to run with no problem. 

So why do I see only zero when I try to read it from the CLA, but normal data from the C28?

Thanks in advance,

Erik

 

  • Hi Erik,

    Can you check the value of MMEMCFG register in CCS register watch window to confirm that expected value is getting programmed into this register.

    Regards,

    Vivek Singh

  • Vivek,

    Yes, that was what I meant when I said MMEMCFG register looks good. All the bits are set as expected, looking at the watch window.

    Thanks,

    Erik

  • Hi Eric,

    Im wondering if your issue is related to whats in this post

    http://e2e.ti.com/support/microcontrollers/tms320c2000_32-bit_real-time_mcus/f/171/p/218230/770892.aspx#770892

  • Actually not. I've read it probably half a dozen times. I have no problem reading it from the C28 side, or so it seems. My problem is when I read the buffer from the CLA side to do the RMS, even though all the RAMxE bits are set in the MMEMCFG register.

    Thanks,

    Erik

  • Are you seeing this issue with CLARAM0 and 1? The only reason i can think of it coming up zeros at the CLA end is that the CLA cant access the memory. On the C28x side, can you do a read of MMEMCFG

    temp = Cla1Regs.MMEMCFG.all and check against the value that you programmed it with. Im wondering if the debug read is showing the true bit value.

  • I saw it happen in CLARAM1 but have not tried CLARAM0. Since then the buffer has grown to more than 1K so I had to put it in CLARAM2. I got temp = ox0071 when I did what you suggested, which seems fine considering the RAMxCPUE bits will show zero since they are read-only.

    I agree with you that the CLA doesn't appear to be able to access the RAM, and I am interested in the solution.

    Thanks,

    Erik

  • I think I should show how the memory is set up. Please take a look and see if I am missing anything.

    Here is my cmd file

    _Cla1Prog_Start = _Cla1funcsRunStart;

    -heap 0x400

    -stack 0x400

    // Define a size for the CLA scratchpad area that will be used

    // by the CLA compiler for local symbols and temps

    // Also force references to the special symbols that mark the

    // scratchpad are.

    CLA_SCRATCHPAD_SIZE=0x200;

    --undef_sym=__cla_scratchpad_end

    --undef_sym=__cla_scratchpad_start

    MEMORY

    {

    PAGE 0 : /* Program Memory */

    /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */

    //progRAM : origin = 0x008000, length = 0x001000 /* on-chip RAM block L0, L1, L2 */

    progRAM : origin = 0x012000, length = 0x002000

    progRAMCLA : origin = 0x009000, length = 0x001000 /* on-chip RAM block L3 */

    OTP : origin = 0x3D7800, length = 0x000400 /* on-chip OTP */

    FLASH_NVM : origin = 0x3D8000, length = 0x004000 /* on-chip FLASH FLASHH */

    FLASHG : origin = 0x3DC000, length = 0x004000 /* on-chip FLASH FLASHG ENERGY ACCUMULATION */

    FLASHF : origin = 0x3E0000, length = 0x004000 /* on-chip FLASH FLASHF ENERGY RECORDS */

    FLASH : origin = 0x3E4000, length = 0x013F80 /* on-chip FLASH */

    CSM_RSVD : origin = 0x3F7F80, length = 0x000076 /* Part of FLASHA. Program with all 0x0000 when CSM is in use. */

    BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Part of FLASHA. Used for "boot to Flash" bootloader mode. */

    CSM_PWL_P0 : origin = 0x3F7FF8, length = 0x000008 /* Part of FLASHA. CSM password locations in FLASHA */

    FPUTABLES : origin = 0x3FD860, length = 0x0006A0 /* FPU Tables in Boot ROM */

    IQTABLES : origin = 0x3FDF00, length = 0x000B50 /* IQ Math Tables in Boot ROM */

    IQTABLES2 : origin = 0x3FEA50, length = 0x00008C /* IQ Math Tables in Boot ROM */

    IQTABLES3 : origin = 0x3FEADC, length = 0x0000AA /* IQ Math Tables in Boot ROM */

    ROM : origin = 0x3FF3B0, length = 0x000C10 /* Boot ROM */

    RESET : origin = 0x3FFFC0, length = 0x000002 /* part of boot ROM */

    VECTORS : origin = 0x3FFFC2, length = 0x00003E /* part of boot ROM */

    PAGE 1 : /* Data Memory */

    /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */

    /* Registers remain on PAGE1 */

    BOOT_RSVD : origin = 0x000000, length = 0x000050 /* Part of M0, BOOT rom will use this for stack */

    RAMM0 : origin = 0x000050, length = 0x0003B0 /* on-chip RAM block M0 */

    RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */

    CLARAM0 : origin = 0x008800, length = 0x000400

    CLARAM1 : origin = 0x008C00, length = 0x000400

    CLARAM2 : origin = 0x008000, length = 0x000800

    //RAML0 : origin = 0x008000, length = 0x000800 /* on-chip RAM block L0 */

    //RAML1 : origin = 0x008800, length = 0x000400 /* on-chip RAM block L1 */

    //RAML2 : origin = 0x008C00, length = 0x000400 /* on-chip RAM block L2 */

    //RAML3 : origin = 0x009000, length = 0x001000 /* on-chip RAM block L3 */

    RAML4 : origin = 0x00A000, length = 0x002000 /* on-chip RAM block L4 */

    RAML5 : origin = 0x00C000, length = 0x002000 /* on-chip RAM block L5 */

    RAML6 : origin = 0x00E000, length = 0x002000 /* on-chip RAM block L6 */

    RAML7 : origin = 0x010000, length = 0x002000 /* on-chip RAM block L7 */

    //RAML8 : origin = 0x012000, length = 0x002000 /* on-chip RAM block L8 */

    USB_RAM : origin = 0x040000, length = 0x000800 /* USB RAM */

    CLA1_MSGRAMLOW : origin = 0x001480, length = 0x000080

    CLA1_MSGRAMHIGH : origin = 0x001500, length = 0x000080

    }

    /* Allocate sections to memory blocks.

    Note:

    codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code

    execution when booting to flash

    ramfuncs user defined section to store functions that will be copied from Flash into RAM

    */

    SECTIONS

    {

    /* The Flash API functions can be grouped together as shown below.

    The defined symbols _Flash28_API_LoadStart, _Flash28_API_LoadEnd

    and _Flash28_API_RunStart are used to copy the API functions out

    of flash memory and into SARAM */

    /******************************************************************/

    /* For Piccolo B we dont need to copy the API from Flash as it is */

    /* present in BOOT ROM */

    /******************************************************************/

    Flash28_API:

    {

    -l Flash2806x_API_fpu32_V100.lib(.text)

    -l Flash2806x_API_fpu32_V100.lib(.econst)

    } LOAD = FLASH,

    RUN = progRAM,

    LOAD_START(_Flash28_API_LoadStart),

    LOAD_SIZE(_Flash28_API_LoadSize),

    LOAD_END(_Flash28_API_LoadEnd),

    RUN_START(_Flash28_API_RunStart),

    PAGE = 0

    /* Allocate program areas: */

    passwords : > CSM_PWL_P0, PAGE = 0

    csm_rsvd : > CSM_RSVD, PAGE = 0

    /* Allocate uninitalized data sections: */

    .stack : > USB_RAM, PAGE = 1

    .ebss : > RAML4 | RAML5, PAGE = 1

    .esysmem : > RAML4 | RAML5, PAGE = 1

    .bss_cla : > CLARAM2, PAGE = 1

    .const_cla : > CLARAM2, PAGE = 1

    /* Initalized sections to go in Flash */

    /* For SDFlash to program these, they must be allocated to page 0 */

    .econst : > FLASH, PAGE = 0

    .switch : > FLASH, PAGE = 0

    .cinit : > FLASH, PAGE = 0

    .pinit : > FLASH, PAGE = 0

    .text : > FLASH, PAGE = 0

    codestart : > BEGIN, PAGE = 0

    ramfuncs : LOAD = FLASH, PAGE = 0,

    RUN = progRAM, PAGE = 0,

    LOAD_START(_RamfuncsLoadStart),

    LOAD_SIZE(_RamfuncsLoadSize),

    LOAD_END(_RamfuncsLoadEnd),

    RUN_START(_RamfuncsRunStart)

    Cla1Prog : LOAD = FLASH,

    RUN = progRAMCLA,

    LOAD_START(_Cla1funcsLoadStart),

    LOAD_END(_Cla1funcsLoadEnd),

    RUN_START(_Cla1funcsRunStart),

    LOAD_SIZE(_Cla1funcsLoadSize),

    PAGE = 0

    Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1

    CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1

    Cla1DataRam0 : > CLARAM0, PAGE = 1

    Cla1DataRam1 : > CLARAM1, PAGE = 1

    Cla1DataRam2 : > CLARAM2, PAGE = 1

    CLA1mathTables : > CLARAM0,

    LOAD_START(_Cla1mathTablesLoadStart),

    LOAD_END(_Cla1mathTablesLoadEnd),

    LOAD_SIZE(_Cla1mathTablesLoadSize),

    RUN_START(_Cla1mathTablesRunStart),

    PAGE = 1

    CLAscratch :

    { *.obj(CLAscratch)

    . += CLA_SCRATCHPAD_SIZE;

    *.obj(CLAscratch_end) } > CLARAM1,

    PAGE = 1

    /* Allocate IQ math areas: */

    IQmath : > FLASH, PAGE = 0 /* Math Code */

    IQmathTables : > IQTABLES, PAGE = 0, TYPE = NOLOAD

    /* Allocate FPU math areas: */

    FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD

    DATADUMP_BUF : > RAML6, PAGE = 1

    //DMARAML5 : > RAML5, PAGE = 1

    //PATTERNS : > RAML6, PAGE = 1

    DMARAML7 : > RAML7, PAGE = 1

    //DMARAML8 : > RAML8, PAGE = 1

    /* Uncomment the section below if calling the IQNexp() or IQexp()

    functions from the IQMath.lib library in order to utilize the

    relevant IQ Math table in Boot ROM (This saves space and Boot ROM

    is 1 wait-state). If this section is not uncommented, IQmathTables2

    will be loaded into other memory (SARAM, Flash, etc.) and will take

    up space, but 0 wait-state is possible.

    */

    /*

    IQmathTables2 : > IQTABLES2, PAGE = 0, TYPE = NOLOAD

    {

    IQmath.lib<IQNexpTable.obj> (IQmathTablesRam)

    }

    */

    /* Uncomment the section below if calling the IQNasin() or IQasin()

    functions from the IQMath.lib library in order to utilize the

    relevant IQ Math table in Boot ROM (This saves space and Boot ROM

    is 1 wait-state). If this section is not uncommented, IQmathTables2

    will be loaded into other memory (SARAM, Flash, etc.) and will take

    up space, but 0 wait-state is possible.

    */

    /*

    IQmathTables3 : > IQTABLES3, PAGE = 0, TYPE = NOLOAD

    {

    IQmath.lib<IQNasinTable.obj> (IQmathTablesRam)

    }

    */

    /* .reset is a standard section used by the compiler. It contains the */

    /* the address of the start of _c_int00 for C Code. /*

    /* When using the boot ROM this section and the CPU vector */

    /* table is not needed. Thus the default type is set here to */

    /* DSECT */

    .reset : > RESET, PAGE = 0, TYPE = DSECT

    vectors : > VECTORS, PAGE = 0, TYPE = DSECT

    }

  • I cant see anything wrong with the linker file. Can you post the disassembly for the RMS routine in the CLA? Perhaps its not a memory issue at all.

  • I kind of figured out what was going on but still have no explanation for it yet. It was the way I organized my buffers in a typedef struct, which the CLA somehow did not like. I wanted to set up the buffers this way to process the data efficiently in a ping-pong manner. The C28 RMS routine did not have any problem with this typedef, and read/compute the data fine, but the CLA did not seem to be able to read the data from it (all zeros).

    So, I had to break up the struct and allocate the buffers individually from:

     

    typedef struct PHASE_DATA

    {

                    short Voltage[BUF_LEN];

                    short Current[BUF_LEN];

    } PHASE_DATA;

    typedef struct RAW_DATA

    {

                    PHASE_DATA     PhaseA;

                    PHASE_DATA     PhaseB;

                    PHASE_DATA     PhaseC;

    } RAW_DATA;

    #pragma DATA_SECTION(Raw, "Cla1DataRam2");                            

    EXTERN volatile RAW_DATA        Raw[2];

     

    to:

     

    #pragma DATA_SECTION(RawVoltageA, "Cla1DataRam2");                         

    EXTERN short RawVoltageA[BUF_LEN];

    #pragma DATA_SECTION(RawCurrentA, "Cla1DataRam2");                         

    EXTERN short RawCurrentA[BUF_LEN];

    #pragma DATA_SECTION(RawVoltageB, "Cla1DataRam2");                         

    EXTERN short RawVoltageB[BUF_LEN];

    #pragma DATA_SECTION(RawCurrentB, "Cla1DataRam2");                         

    EXTERN short RawCurrentB[BUF_LEN];

    #pragma DATA_SECTION(RawVoltageC, "Cla1DataRam2");                         

    EXTERN short RawVoltageC[BUF_LEN];

    #pragma DATA_SECTION(RawCurrentC, "Cla1DataRam2");                         

    EXTERN short RawCurrentC[BUF_LEN];

    Then it started working normally. I now can properly process the RMS routine from the CLA side with no issue.

    Is there a problem putting data buffers in a typedef struct in the CLA data space? Again, the C28 side has absolutely no problem with it.

    Thanks,

    Erik

  • I will probably have to forward this to the compiler forum if its an issue with data types. But before i do that id like to look at the disassembly for just the RMS routine (if that is something you can share) with the original data structure so i can see where its trying to get the data from. Also if you can check the .map file and tell me where "Raw" is being allocated, then i can try to figure out why the data access isnt working.

  • Hi Vishal,

    I don't think this has anything to do with the RMS routine since the only thing I changed was the memory allocation method and it started working. Also I did verify with the map file that all the "Raw" data was properly located where it was supposed to (please re-read my original message).

    I just talked to my colleague who also used typedef struct for his CLA memory and he did not have any problem. The major deference is his buffer length is 2, whereas my buffer length is 64 (x6 for V and I of all 3 phases).

    Thanks,

  • Please send the source to the function which reads and writes memory using the PHASE_DATA and RAW_DATA typedefs.  You will probably need to preprocess it like this.  Also show the exact build options used.  We'll take a look at the assembly generated and might see the cause of the problem.  

    Thanks and regards,

    -George