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.

MemCopy() vs memcpy()

Other Parts Discussed in Thread: CONTROLSUITE

I am developing a program that is loaded from flash and run from RAM.  I am also using the EEPROM example files in my program.  The example program to copy sections from on-chip flash to ram uses memcpy(), while the EEPROM example uses MemCopy() to run the FLASH API from RAM.  I noticed the EEPROM example is 3 years old, so is MemCopy not recommended to use anymore?

Also I am trying to figure out if I have enough space to run the program from RAM.  With the older version that used DSP28xxx_Section_Copy_nonBios.asm, I could see the Ram space being used in the memory map file.  However with the newer example the RAM used remains 0 in the memory map.  I know I am a bit borderline with space if I choose to run all the sections from RAM, can you please tell me what I need to do to see it in the map file again, and what the current recommended method is for copying sections to RAM?

Thanks,

Omer

  • Omer,

    You're absolutely correct.  We don't recommend the use of MemCopy.  We recommend users use the memcpy function which is more standard across different platforms.

    Hmmm, that's odd that there is no RAM usage in your map file.  Are the other sections that are used (for instance Flash) shown correctly in the map file?

    Trey

  • Thanks, Trey, I appreciate the quick response.
    I modified the program to use only memcpy, for the FLASH API as well, but I am still not seeing anything loaded to RAM in the memory map.  You can see that I am using a good size of Flash space.  In my older program using Section copy.asm I would see a similiar size in RAM as well.  I modified the memory allocations a little bit to make sure that Flash routines are only run from L1 Secure RAM.  (Before I had grouped L0L1H0 all into one section)  

    InitPieCtrl();
    InitWatchdog();

    // Section secureRamFuncs contains user defined code that runs from CSM secured RAM

    memcpy(&Flash28_API_runstart, &Flash28_API_loadstart, (Uint32)(&Flash28_API_loadsize));
    memcpy(&secureRamFuncs_runstart, &secureRamFuncs_loadstart, (Uint32)(&secureRamFuncs_loadsize));

    memcpy(&text_runstart, &text_loadstart, (Uint32)(&text_loadsize));
    memcpy(&econst_runstart, &econst_loadstart, (Uint32)(&econst_loadsize));
    memcpy(&const_runstart, &const_loadstart, (Uint32)(&const_loadsize));
    memcpy(&cinit_runstart, &cinit_loadstart, (Uint32)(&cinit_loadsize));
    memcpy(&pinit_runstart, &pinit_loadstart, (Uint32)(&pinit_loadsize));
    memcpy(&switch_runstart, &switch_loadstart, (Uint32)(&switch_loadsize));

    //--- Initialize the Flash and OTP
    InitFlash();

    HRDv5.zip
  • Omer,

    Everything looks fine in this command and map file.  If you look at the map file you can see that the FlashAPI is loaded at address 0x3F0000 (FLASH_AB) and run from 0x9000 (L1SECRAM).  See below...


    Flash28_API
    *          0    003f0000    000004e8     RUN ADDR = 00009000
                      003f0000    00000014     Flash2808_API_V302.lib : Flash28_Erase.obj (.econst)
                      003f0014    000000a9                            : Flash28_Prog.obj (.text)
                      003f00bd    000000a2                            : Flash28_Erase.obj (.text)
                      003f015f    0000009a                            : Flash28_Erase_Pulse.obj (.text)

    What do you mean when you say nothing is loaded into RAM in the memory map?

    Trey

  • You are correct that the FLASH API is loaded into RAM, but the program sections are not.  I created two memory sections in RAM.  L1SECRAM for the FLASH and L1H0RAM for the main program.  I figured this way would guarantee that the FLASH routines will be loaded in secure RAM.  The old example combined all three sections into L0L1H0RAM.

    You can see that L1H0RAM is not being filled with anything, even though I am copying sections there.
    L1H0RAM               00009600   00002a00  00000000  00002a00  RWIX  

    Also I noticed that in the map file only the flash_api and secureRamFuncs have a "RUN_ADDR = 0000xxxx", while the .text, .econst, etc sections don't.   

    Another question I have is, how important is it to allocate an entire memory section to Data Space and entire section to Program Space.  Right now I have it allocated like this:

    PAGE 0:  /* Program Memory */
    L1SECRAM : origin = 0x009000, length = 0x000600     /* Secure L1 RAM - Used for Secure Ram functions */
    L1H0RAM :    origin = 0x009600, length = 0x002A00     /* L1H0 SARAM */

    PAGE 1 : /* Data Memory */
    M0SARAM : origin = 0x000002, length = 0x0003FE /* M0 SARAM */
    M1SARAM : origin = 0x000400, length = 0x000400 /* M1 SARAM */
    L0SARAM : origin = 0x008000, length = 0x001000 /* L0 SARAM */

    I am only using 0x380 of L0SARAM.  Can I split in half and use the other half for Program Memory?  I am trying to maximize my program memory because I am borderline in space when trying to run the entire program from RAM.

    Thanks,

    Omer

  • Omer,

    I looked at your command file some more and it appears you are trying to link .text into two places.  At the start of the "Sections" you'll see:
       .text             : > FLASH_AB,        PAGE =0

    and then further down you'll see:

        .text            :   LOAD = FLASH_AB,     PAGE = 0    /* Load section to Flash */
                            RUN = L1H0RAM,   PAGE = 0    /* Run section from RAM */

    The linker see the first .text entry and allocates that code to FLASH_AB.  Then when it gets to the next .text entry its already allocated everything so there is nothing to allocate to L1H0RAM.  Fix this and you should see stuff being placed into L1H0RAM.  FYI several of your other sections have this same problem.


    Trey

  • Ok great so now I see the program being loaded into RAM in the map file.

    L1H0RAM               00009000   00003000  00002527  00000ad9  RWIX

    However I have an issue with the codestart branching because I get an error.  No Source Available for 0x067 (the address is random)

    I believe I need to copy the sections to RAM before I branch to _cint_00 ?

    Where is a good place to run the memcpy functions and InitFlash()?  The old example was branched in assembly with SectionCopy.asm ( An updated example for CCSv5 would really help!!)

    Thanks,

    Omer

  • Omer,

    You are unable to branch to c_int00 because it is part of the .text section.  When you try to blindly link .text to RAM and load it into flash you are going to have problems.  What you need to do is segment your code into sections and keep track of what goes where and when each section gets executed, so that you can ensure the program code is where the linker thought it would be at run time.

    You need to get friendly with the assembly language tools user guide (spru513).  Specifically look at the "CODE_SECTION" pragma which will let you designate a function as part of a section and then you also need to know how to link a library to a specific section (which you are already doing with the FlashAPI).  My advice would be that you link the RTS library to reside and run from flash.  This will allow your program to boot normally from flash.  Then you'll need to put your main function in a section using the CODE_SECTION pragma that is run and loaded into flash.  This should allow execution to get to main and then for your memcpy to be executed successfully.  If you want to InitFlash or setup the PLL before doing your memcpy make sure that the program code for those functions resides and executes from flash.

    Regards,

    Trey

  • Omer,

    Are you using memcpy() or MemCopy() in your code during start-up to copy the code from FLASH to RAM?  I don't think specifying the LOAD and RUN in the CMD file is enough.  In our examples, we do something like this:

    in linker command file
       ramfuncs            : LOAD = FLASHD,
                             RUN = RAML0,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
           LOAD_SIZE(_RamfuncsLoadSize),
                             PAGE = 0

    in main() code
       memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize);

    One example of how we use this method is to copy the FlashInit() function from FLASH to RAM at start-up.  You can find examples for running from FLASH for almost all devices inside of the device support folders in controlSUITE ("C:\TI\controlSUITE\device_support").

    Regards,
    Daniel

  • Omer Peleg said:

    Where is a good place to run the memcpy functions and InitFlash()?  The old example was branched in assembly with SectionCopy.asm ( An updated example for CCSv5 would really help!!)

    We usually run memcpy() in main() after system initialization but before the application code starts.  Also, memcpy() is run before InitFlash().

  • Omer Peleg said:

    I am only using 0x380 of L0SARAM.  Can I split in half and use the other half for Program Memory?  I am trying to maximize my program memory because I am borderline in space when trying to run the entire program from RAM.

     
    Yes, you can split up the RAM betwen program and data.  Just make sure you define the boundaries properly and avoid any overlap.
  • Hi Daniel,

    Thanks for your replies.  My problem had started when I would once in a while get locked control cards and couldn't flash them anymore.  Nothing I did seemed wrong, and I even used the TI Experimenter kit to make sure it wasn't my custom board.

    http://e2e.ti.com/support/microcontrollers/tms320c2000_32-bit_real-time_mcus/f/171/t/196377.aspx

    I decided maybe it was because I was using example "Copying Compiler Sections from Flash to RAM" as my basis for my program, which is very old and for CCSv3.3 (also used v1.40 headers).

    So I tried using the example "Running from Internal Flash Memory" because it had been updated for CCSv5.  I had posted the question in this forum when I started running into trouble attempting to run the entire program in RAM.  At this point I am having trouble branching at codestart, as you can see from the last post.

    After Trey's last post I am tempted to use the DSP28xxx_SectionCopy_nonBIOS.asm routine in the old example to copy the sections from flash to ram prior to runtime, unless you guys think this method is obsolete?  Trey, is the method you have proposed a better way to do it?

    Thanks again,

    Omer

  • Ok so for now this is what I have resided to do.  I am copying all sections to RAM except the .text section.

    I'm then copying individual functions to RAM like this:

    #pragma CODE_SECTION(Flash_Firmware, "secureRamFuncs")
    #pragma CODE_SECTION(Erase_Prog_Flash, "secureRamFuncs")
    #pragma CODE_SECTION(Flash_Section, "secureRamFuncs")

    #pragma CODE_SECTION(ecap1_isr, "RamFuncs")
    #pragma CODE_SECTION(ecap2_isr, "RamFuncs")
    #pragma CODE_SECTION(ecap3_isr, "RamFuncs")

    etc....

    It looks like this should work fine unless there is something I am missing.

    Thanks,
    Omer 

  • Omer,

    You can copy the code with whatever routine you wish.  We are just recommending people use memcpy because it is a standard function across different architectures and systems.

    Its up to you how you allocate your program into flash and RAM because there are an infinite number of ways to do this and make it work.  That being said, its probably simplest to keep .text such that it is loaded and run from flash.  Then as you have suggested, place the speed critical (or Flash related) functions into a section that is loaded into flash but run from RAM.

    One last thing, keep in mind that adding a #pragma CODE_SECTION statement doesn't actually cause the code to get copied at runtime.  It only tells the linker to put the code in that section.  In your application you still must call memcpy for each section that needs to be copied.

    Regards,

    Trey

  • Thanks for your help,

    Yes I am aware that I need to use memcpy to actually copy the section.  I am happy to be back to where I was again :)

    Hopefully I will no longer see my flash failure problem.

    Thanks,

    Omer

  • Omer Peleg said:

    Thanks for your replies.  My problem had started when I would once in a while get locked control cards and couldn't flash them anymore.  Nothing I did seemed wrong, and I even used the TI Experimenter kit to make sure it wasn't my custom board.

    http://e2e.ti.com/support/microcontrollers/tms320c2000_32-bit_real-time_mcus/f/171/t/196377.aspx

    When you are programming FLASH, are you specifying the passwords? 

    To be safe, you could add something similar to "C:\TI\controlSUITE\device_support\f2806x\v130\F2806x_common\source\F2806x_CSMPasswords.asm" to your project so that your CSM passwords are always being programmed with a known value. 

    You will also need to update the CMD file for the FLASH project to have the appropriate sections defined.  For an example, you can look at a file similar to "C:\TI\controlSUITE\device_support\f2806x\v130\F2806x_common\cmd\F28069.cmd"

  • Daniel, I'm a bit confused by your assistance.  You keep bringing up the control suite, and an example that points to a controller that I'm not using.
    The examples I have been using all have passwords.asm, and a section that is allocated specifically for the CSM in the memory linker file.

    I am not sure why I am losing chips once in a while, but at this point I am thinking maybe it was related to either the watchdog software problem or that I was using a debugger through a USB hub?  I had nothing else to try to do besides trying to rebuild the software from scratch so I found an updated example to which to build from.

    It's unfortunate that a locked chip can not be reset.  Maybe I can return the locked control cards (8 pcs) ?  By the way, I never changed the passwords to the CSM, I have no intention of locking it.

    Thanks,

    Omer

  • Omer,

    First off, yes, Memcopy is not recommended for use.  memcpy is faster and is a standard function across many different platforms...not just C2000.

    Second, The map file will show you RAM usage if you link the program correctly.  If you fix that double allocation problem I told you about earlier in your command file you should start to see the RAM usage go up.  Unless you have some special requirements, there is no reason to run the entire application from RAM.  If you have some speed critical code portions, those may be placed into RAM to improve performance but there is no reason to put things like initialization code in RAM. 

    What controller are you using?  There are examples in controlSUITE for all of our current devices, but if you are using an older device you may have to look elsewhere.  From the sounds of it you are probably using a device that isn't supported in controlSUITE.  The controlSUITE software has improved a lot over the past few years and much of it can easily be back ported to the older devices.

    I cannot comment on controlCard returns, but I don't think it is something we typically do.  I completely believe you were not trying to lock your flash, but the flash will not just lock itself...the password locations must be programmed for the flash to lock.  You probably did so unknowingly somehow.  My advice would be that if it happens again, save the .out file that caused the flash to be locked.  You can use the hex2000 utility in the compiler directory to generate an s record or hex file and you can find the passwords that were programmed.  Then you can use those passwords to unlock and erase the device.  Once again, the assembly language tools guide has some useful information for how to use the hex2000 utility.

    Hope that helps,

    Trey

  • I would like to update this post after a few more weeks of testing.  I had verified that I was not locking the chip by looking at the hex files and confirming that only 0xFFFF keys were being written to the CSM password location.  I now realize that the chips were not being locked, but actually were failing from some kind of improper ground loop.  Unfortunately I was chasing the wrong problem because the error I was getting from CCS or blackhawk flashburn was that the controller seemed to be locked.  

    I found this out by realizing I was only losing chips on a specific test bench and no where else.  I am thinking of buying an isolator to prevent this from happening again.

    Thanks for your help,

    Omer

  • Daniel Chang said:

    We usually run memcpy() in main() after system initialization but before the application code starts.  Also, memcpy() is run before InitFlash().


    Hi

    I found this thread when searching information about running from flash and the memcpy function.


    I have a question about the sequence of calling different init functions and memcpy. In "Example_2806xFlash" found from controlSUITE the sequence is exactly like Daniel said:

    main{

    InitSysCtrl();

    InitPieCtrl();

    InitPieVectTable();

    InitEPwmTimer();

    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize);

    InitFlash();

    ...

    }

    However, in F2806x_SysCtrl.c and F2806x_usDelay.asm they warn you:

     *IMPORTANT*
    //  IF RUNNING FROM FLASH, PLEASE COPY OVER THE SECTION "ramfuncs"  FROM FLASH
    //  TO RAM PRIOR TO CALLING InitSysCtrl(). THIS PREVENTS THE MCU FROM THROWING
    //  AN EXCEPTION WHEN A CALL TO DELAY_US() IS MADE.

    So why TI is not doing like they demand?

  • Olli,

    I did confirm that this is bug and have already reported the issue to software team in Houston. Hopefully, we will try to fix this in next revision of control suite.

    In F2806x_Examples.h, DSP28_DIVSEL is by default selected to 2. With this selection, InitPll() function doesn't execute DELAY_US(50) function. So, current flash example program in control suite will not show any problem. But, if you change DSP28_DIVSEL = 3, then executing DELAY_US function will trigger an ITRAP because memcpy function isn't executed.

    If I execute memcpy function before InitSysCtrl() as shown below. everything seems to work fine irrespective of DSP28_DIVSEL selection.

    main{

    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize);

    InitSysCtrl();

    InitPieCtrl();

    InitPieVectTable();

    InitEPwmTimer();

    InitFlash();

    ...

    }

    Regards,

    Manoj