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.

How to transfer a variable address declared in C to inline assembly instructions.

Other Parts Discussed in Thread: TM4C123GH6PM

Hi,

I'm working on a project using the TM4C123GH6PM where I have an interrupt routine that needs to save GPIO ports data into RAM but because of tight timing constraint, I'm programming part of the ISR with inline assembly instructions.  Is there a way to tell the assembly code the address of an array or a variable declared in C? 

I searched the web and this forum but I couldn't find how to do this.

I'm using Code Composer Studio 5.5.

Thanks,

  • With optimization enabled, modern C compilers are much more efficient than you think.

    If you can't find out about those variable addresses yourself, the compiler output will surely be more efficient than your assembler code.

    But for reference:  CCS uses the gcc compiler, and the TM4C is a Cortex M4, employing Thumb2 instructions. That should suffice to feed your favourite search engine.

    And BTW, I don't believe that I can beat a compiler in that area myself ...

  • Hi,
    I suppose you need something like this for managing addresses:
    a) in other IDEs you just write this:
    PORTA  EQU  0x400043FC
    and in your routine:
    LDR R0, =PORTA  ;R0= &PORTA
    b) the equivalent for CCS is this:
    PORTA .field 0x400043FC,32
    and in your routine in CCS write this:
    LDR R0, PORTA
    c) do the same for other variables. If your .asm routines are in another file, then you may write:
    #include "my_h_file.h" containing the externally declared variables.

    The ASM and Compiler manual are in your TI CCS installation folder; just search for them for supplementary info.

    Petrei

  • IMHO you missed something: you need to tell the compiler about variables you touch inside your assembler routines, otherwise he will ignore your code while doing optimizations. This produces very nasty side effects ...

    Here is a Howto that turned up first in a search:

    http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

    The example code is for a x86 target, but the rest is still appropriate.

  • Thanks all. 

    In my project the timing is tight and critical.  Since I need an exact timing, relying on the compiler optimization is not an option here. 

    f.m. is right.  I know how to access the GPIO but it's transferring the information to the C program through a variable that I'm trying to accomplish.

    f.m., I started experimenting with the information from your link but it didn't work, yet.  At least, it's giving me something to work with.

    I'm still open to other suggestions.

    Thanks,

  • f.m., I started experimenting with the information from your link but it didn't work, yet.  At least, it's giving me something to work with.

    That's probably because I once canceled the insertion of the link in my post, and it never again worked. Just copy the string to the web address input field of your browser ... At other times, it complains about mismatching quote/endquotes, which do not exist.

    Rather than accessing variables from within assembly code, telling the compiler about it is your most important problem.

    In my project the timing is tight and critical.  Since I need an exact timing, relying on the compiler optimization is not an option here.


    And I am still convinced than you can't do better than gcc with '-O3' ...

  • Hi f.m.

    The link worked. It's the information on the linked page that doesn't work yet.

    I followed your suggestion and here's the timing my interrupt routine takes so far.

    1.85us  - C only, optimisation off

    1.32us - C only, optimisation on, level 3

    1.29us - Assembly/C combined, optimisation off

    0.85us - Assembly/C combined, optimisation on, level3.

  • The link worked. It's the information on the linked page that doesn't work yet.

    That was just the first page that turned up in the search. I'm sure there are ARM/Thumb2 specific examples, too.

    I followed your suggestion and here's the timing my interrupt routine takes so far.

    1.85us  - C only, optimisation off

    1.32us - C only, optimisation on, level 3

    1.29us - Assembly/C combined, optimisation off

    0.85us - Assembly/C combined, optimisation on, level3.

    1.) not all compilers have identical optimisation capabilities;

    2.) make sure all investigated variants/routines are semantically identical (achieve the same thing).

    If timing is critical, consider a timer-triggered DMA transfer instead of an interrupt. That would unload the core. Not sure  if the TM4C is capable of this - a competitors MCU (I'm more familiar with) can do this for sure.

  • I tried the DMA in UDMA_MODE_PER_SCATTER_GATHER mode but the problem here is that only one task per interrupt is run.  In my project, I have 6 GPIO data registers to read and 6 GPIO registers to write to for each interrupt.

    I also noticed many times that the timing changed when I compiled with the optimisation on.  With no optimisation, the interrupt timing is always the same, which is what I need.

    I'm currently working on an interrupt routine completely in assembly to have exact control on the timing.  I've done this in the past with a MSP430.  I did some reading about the TM4C123 assembly and overall, the setup to link with a C program seems to be similar than the MSP430. 

    I'm let you know my results.

    -