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.

Linking IQMath in RAM

Other Parts Discussed in Thread: TMS320F28031

Hi, 

I'm using TMS320F28031 clocking at 60MHz. For improving execution speed I want to run ISRs from ram. Now my ISR contains a few control loops that invoke the IQMath library. So for best performance I need to run the IQMath from RAM too. I did that but saw no improvement in speed. Digging a little deeper I found that even though I've loaded the IQMATH in RAM during runtime, the IQMATH library invokes a few RTS library functions that get linked in FLASH.

For eg:

// IQ Code in ISR

Result = _IQ9int(_IQ9div(X,Y));

generates a .text section in map file like this:

003f7b02                 0000001f                              rts2800_ml.lib : fd_tol.obj (.text)
003f7b21                 0000001c                                                     : l_tofd.obj (.text)
003f7b3d                 00000019                                                     : args_main.obj (.text)
003f7b56                 00000019                                                     : exit.obj (.text)
003f7b6f                  00000017                                                     : u_tofd.obj (.text)
003f7b86                 00000016                                                     : ul_tofd.obj (.text)

The last 2 entries were created because of the call to IQ and they are loaded in flash under the .text section.

So how do I control this process? If IQMath is going to call functions from RTS then it defeats the purpose of loading it in RAM. I'm never going to see an improvement in execution time. 

Any suggestions on how to get around this problem?

Regards,

Vivek

PS: On a different note I have observed that if I'm running my ISRs from RAM I'm not able to put a breakpoint in the ISR. Or rather I can put a breakpoint but the execution never halts there. Is this behaviour valid? Any methods to get around this problem? 

  • Vivek,

    It appears that the IQ math lib is doing the integer division by converting to floating point, doing the divide from the RTS library, and then converting back to integer (IQ).  I didn't code it myself and look.  I'm making this observation from the RTS lib functions you show in your post.

    What you can do is link the needed functions from the RTS library to RAM.  You need to LOAD to flash, copy to RAM, and then run from RAM (you cannot just load to RAM in a standalone application!).  Here for example is what you'd put in your linker .cmd file:

    RamFuncs  :  LOAD = FLASH_ABCD, PAGE = 0
                 RUN = L1DPSARAM,   PAGE = 1
    {
       rts2800_ml.lib  <fd_tol.obj> (.text)
       rts2800_ml.lib  <I_tofd.obj.obj> (.text)
       rts2800_ml.lib  <u_tofd.obj> (.text)
       rts2800_ml.lib  <ul_tofd.obj> (.text)
    }
       LOAD_START(_RamFuncs_loadstart),
       LOAD_SIZE(_RamFuncs_loadsize),
       RUN_START(_RamFuncs_runstart)

    and then in your code you need to do the copy before you use any of the code in this section.  You can use memcpy in the RTS lib to do this copying:

    extern Uint16 RamFuncs_loadstart;
    extern Uint16 RamFuncs_loadsize;
    extern Uint16 RamFuncs_runstart;
    memcpy(&RamFuncs_runstart, &RamFuncs_loadstart, (Uint32)&RamFuncs_loadsize);

    See appnote SPRA958 on the web for information on the above copying.

     http://www.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=spra958l&docCategoryId=1&familyId=1414

    So far as the breakpoint issue goes, this has nothing to do with an ISR.  The debugger doesn't know what an ISR is.  There is something else going on.  Maybe you're not getting the interrupt.

    Regards,

    David

  • Hi David,

    Thanks for the response. I did exactly what you told me. On of your earlier posts here  guided me.

    The problem with ISRs persists. I know I'm taking the interrupts. A port toggling inside the ISR confirms this. I'm able to stop at breakpoint if ISR is being run from FLASH. I get this problem only when I place my ISR under "ramfuncs".

    Vivek

  • Vivek,

    I may know what the problem is.  You are setting a software breakpoint in your ISR before you run the code.  When you run the code, the copy from flash to RAM of the ISR is done and it overwrites your breakpoint.  Hence, no stopping in the ISR.

    There are two types a breakpoints.  A SW breakpoint is an actual instruction that the debugger uses to replace the instruction in memory.  This can only be done in RAM.  A HW breakpoint uses special logic in the device to perform a bus address compare (i.e., does the address on the data or program bus match the configured BP address, if so, halt).  HW breakpoints are used by the debugger in flash.

    There are at least three ways to get around this problem (of having your SW BP overwritten).  One approach is to run past the flash to RAM copy code in main() (or where ever you have it located).  Set a BP (in flash) after this code.  When you hit the BP, then set the BPs in your ISRs in RAM.  Downside of this approach is you need to re-set the BPs in the ISRs every time you reset/restart and run the code.

    Method two is to use a HW BP in the ISR.  Instead of double-clicking to set the BP, click once to locate the cursor at the code line you want the BP at, and then right-click on that line.  Select Breakpoint, and then set a HW breakpoint.  Only downside of this method is that you only have two HW BPs in the C28x.

    Third method is to embed a HW BP directly into your code.  The asm instruction ESTOP0 is a HW BP.  You use inline assembly to embed it into C-code:

    asm(" ESTOP0");  // Note the leading space before ESTOP0 is required

    Problem here is you cannot remove this breakpoint without rebuilding and re-flashing the code.  So you can get fancy if you want using a global array to control the execution.  For example, suppose you had 5 such ESTOP instructions scattered around your code.

    Uint16 BpControl[5];       // Global array
    if(BpControl[3] == 1) asm(" ESTOP0");

    Before running the code the first time, open BpControl[] in a memory or watch window, and zero out each element.  Then, selectively set elements to a 1 to enable whichever breakpoints you want.  The contents of BpControl will be preserved across debugger resets/restarts so you don't have to re-init the array for every run.

    I'd quickly try method #2 to confirm that the problem you are seeing is what I suspect.

    Regards,

    David

  • David,

    Thanks for the detailed response. Clarified a lot of things. 

    Will try your suggestions and will post the results here.

    Regards,

    Vivek

  • David,

    I did try the method #2 that you specified. Works perfectly.

    Also thanks for those wonderful debugging tips.

    Just one last thing. Any good resource that you can point that explains this debugging techniques in code composer and c2000 processor?

    Regards,

    Vivek

  • Vivek,

    I'm glad it is working now.

    Vivek Sankaranarayanan98982 said:

    Just one last thing. Any good resource that you can point that explains this debugging techniques in code composer and c2000 processor?

    I'm afraid not.  This stuff is not really documented in the manner you are looking for.  It's a bunch of information pulled from many different locations.  It's experience.

    Regards,

    David