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.

Program Execution from Ram?

Other Parts Discussed in Thread: MSP430F5438A, CC430F5137

I hadn't noticed it before, but some of the 5xx devices (such as the msp430f5438a) spec a different operating current when executing from ram vs flash.  I don't really have a use case for this yet, but putting a few ISRs in RAM seems like something interesting that I'd love to play with :)

Maybe my google-fu is rusty but I haven't come across very many examples on that do this.  Slaa103 (Flash self-programming guide) has some assembly that copies a chunk of flash code into ram and then jumps to it (Figure 3), but Id love to stay in my nice, civilized C environment because writing things in assembly makes it feel like work :(

Does anyone have a C example of how to do this, or should I set out to write my own?

  • Hi memoryleak,

    we have created some sample code  that demonstrates execution from RAM. Hopefully it could be a good starting point for you.

    Regards,

    Dung

    4035.RunningfromRAM_IAR.zip

    4276.RunningfromRAM_CCE.zip

    RunningfromRAM_CCE.zip
  • One main reason for executing something in ram is that you cannot do burst flash writing when the code that does it is in flash itself.

    Some MSPs allow moving the vector table into RAM, so if you are flashing data and need some ISR being executed while the flash is busy erasing/writing, it might be useful to move it into RAM (and the vector table too, as it is inaccessible in flash during erase/write).

    I don't think that executing code from ram instead of flash will save that much energy, but well, in theory the whoel applicaiton can be copied into ram and executed there. If there is enough ram, that is.

    There are several way for putting code into ram. One way is to move the function into the data segment. Then it is stored in the flash area along with the variable init values and copied into ram at startup.How to do this depends on the compiler (#pragma, function attributes etc.)
    The ddrawback is that the function can be overwritten, and even if not, it consumes ram all the time. Moving just the required code to ram temporarily might be the better solution.

    It should be possible to generate fully relocatable code too in C, as long as you don't use any class stuff. (but usually, you cannot rely on this if not explicitely supported by the compiler), so you can have the funciton in flash, copy it to RAM when needed. Fully relocatable means that inside the code chunk only relative jumps are used, and calls are only used to functions that will never mode or through function pointers

  • Dung,

    Thanks for the examples!  The procedure looks pretty straightforward, I can't wait to play with these later today :)

     

    Jens,

    As always, I appreciate your thoughts.  I also wouldn't think that executing out of ram would save much power, but apparently it cuts CPU related power by a decent bit(at least in the 5438a).  This is a purely academic pursuit for me right now, so I have no real power target other than "as low as I can possibly make it".  Right now I spend most of my time in LPM3 (running on VLO), waking only to service and interrupt, do some math (running on DCO) and go back to sleep.  If large portions (CPU time wise) of my code can fit in ram I might be able to reduce power significantly if I have the extra ram to devote to code storage.

    I hadn't thought of moving the ISR vector table to ram or even modifying the ISR vectors, I had just planned to have a one-liner ISR that calls my volatile function.  Once I get that working I think I'll look at moving the ISR vectors around :)

     

    Thank you both for the help!

  • Executing the majority of my ISR out of ram reduced my CPU related power consumption by about ~20% (on my FE4272).  My margin for error is pretty high (quickie experiment, hand dmm) but it does seem to be a viable way to squeeze few more electrons out of a design if you're feeling hardcore about it :)

    Of course since I don't touch the CPU but every 16ms and only for a handful of cycles, the savings is somewhere around the difference between picking XCAP14PF vs XCAP0PF for my crystal.  Still a fun optimization though :)

  • memoryleak said:
    Still a fun optimization though

    Indeed it is. I never used hte MSP because of its low power consumption. My predecessor seelcted the MSP because its hardware modules were superior to the PICs while still being cheap and easy to handle. Then I inherited all the PIC projects and some started MSP migrations and had to do all the new firmware. It was easier to writ ethe new ode than to understand the condensed and complicated (because of the hardware limitations) PIC code.

    Anyway, many people pick the MSP because of its low power consumtion, and making it even lower is a nice thing.

    For larger projects, it still needs to be calculated whether the reduced power consumption for RAM execution pays for the increased runtime required for the setup and copying. Especially if the code needs to be moved more than once (there's so much more flash than RAM and therefore larger projects might need to exchange the code in ram more or less often)

     

  • Hello

     

    I have been using your example to program a small bootloader program that can update the flash via an RF link.

    I run into problems now because I erase some functions I use from a library, and although the function itself is also copied to RAM first, at some point the code still jumps to Flash rather than to RAM.

    How can I make sure that library functions are also called from RAM?

    Is this an IAR problem or is there some linker option to force it to use the functions in memory?

     

    I have not copied all my code into RAM, to save memory, the initialisation of my system can be run from flash first. Once initialised, I then jump to running from RAM.

    Is this ok to do? Or should I copy all functions to RAM first?

     

    thanks

  • Only move the code to ram that is needed when there is no more flash.

    However, if you use a library, fucntions of the library may use other functions and might not kow htat these are moved to ram. If the library was precompiled, the linker will link these 'internal' calls to the flash location.
    Also, if the library is available in source code, either the calls inside or the segment definitions need to be changes so they will assume the code in RAM rather than flash. (if you change the segment definitions, the linker will automatically adjust the calls and also copy the functions from flash to ram on startup, but that's not trivial)

    This kind of code tweaking usually only works with code you have written yourself or at least adjusted yourself.

    Bout the segment definitions, on mspgcc, you simply say in yur source code that the function belongs to the data segment. Then it is treated liek initialized variables (copied to ram on startup) and all references to it are pointing to ram.

    I don't know how to do it with IAR. Maybe some sort of #pragma.

  • Hi All,

    I want to run function form RAM in CC430F5137. I saw RAM example project. 

    I have once question, how do i decide how much memory to allocated to the function.

    For ex: In linker file of the example I found this,

    RAM_MEM                 : origin = 0x1C00, length = 0x0200   ????

    FLASH_MEM               : origin = 0x5C00, length = 0x0200 ???

    How those numbers(red)are decided ??


    Thanks,

    Rahul



  • For obvious reasons, FLASH_MEM and RAM_MEM must be same size.
    The size of 0x200 likely was chosen because 0x200 is the size of a main flash segment. In general, the size must be of course large enough to hold your code. Aligning the segment sizes to flash segment borders allows runtime-updates of this part of flash without affecting other code in flash. AFAIK not a requirement for the simple case of a monolithic compiled/linked application.

  • Thanks Michael,

    I wanted to run piece code from ram. How do I decide the code size of that piece code. Because I need size to be mentioned in linker command file ! right? pls refer this source code,

    1565.msp430x54xA_adc12_10_4.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //******************************************************************************
    // MSP430F543xA Demo - ADC12_A, Sample A10 Temp and Convert to oC and oF
    //
    // Description: A single sample is made on A10 with reference to internal
    // 1.5V Vref. Software sets ADC12SC to start sample and conversion - ADC12SC
    // automatically cleared at EOC. ADC12 internal oscillator times sample
    // and conversion. In Mainloop MSP430 waits in LPM4 to save power until
    // ADC10 conversion complete, ADC12_ISR will force exit from any LPMx in
    // Mainloop on reti.
    // ACLK = n/a, MCLK = SMCLK = default DCO ~ 1.045MHz, ADC12CLK = ADC12OSC
    //
    // Uncalibrated temperature measured from device to devive will vary due to
    // slope and offset variance from device to device - please see datasheet.
    //
    // MSP430F5438A
    // -----------------
    // /|\| XIN|-
    // | | |
    // --|RST XOUT|-
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    In linker command file,

              In sections, 

    .FLASHCODE : load = FLASH_MEM, run = RAM_MEM
    /* CODE IN FLASH AND WILL BE COPIED
    TO RAM AT EXECUTION HANDLED BY
    USER */

          In Memory,

    RAM_MEM : origin = 0x1C00, length = 0x0200
    RAM : origin = 0x1E00, length = 0x3E00

    FLASH_MEM : origin = 0x5C00, length = 0x0200

    FLASH : origin = 0x5E00, length = 0xA180

    FLASH2 : origin = 0x10000,length = 0x25C00

    Hows that 0x200 has been decided!?

    Thanks,

    Rahul

  • The size of the segments must be equal or larger than the size of the code you want to place in. That's obvious.

    You can figure out the size of the functions by looking at the map file before placing them into the ram segment. Or you just try and when the code is larger, the linker will tell you so and also give you the required size. You can then increase the segment size.

  • Thanks Michael :)

  • Thank you Dung for this example!

    Does anyone know how to handle it in mspgcc? The syntax of TI linker's .cmd file is not supported by the GNU ld.

    Best Regards,

    tml

**Attention** This is a public forum