• AVR Freaks

Hot!inline assembly

Page: 12 > Showing page 1 of 2
Author
scrungy
Senior Member
  • Total Posts : 133
  • Reward points : 0
  • Joined: 2016/02/02 09:56:54
  • Location: 0
  • Status: offline
2019/04/23 11:10:30 (permalink)
0

inline assembly

I am attempting to create a simple inline assembly function, and really don't understand the advanced parameter stuff
 
Because a while (!SPI1STATLbits.SPIRBF);   generates a lot of overhead, I would like to be able to replace it with
the equivalent of the following psuedo code.
asm volatile 
       (
       "1:  BTSS  SPI1STATLbits.SPIRBF \n"
       "     bra 1b   \n"
       ) 
given that I can find the address of SPISTATL  (0x3FC)
I believe that this would do it, but I am not certain.
asm volatile
        (
        "1:  BTSS  0x3FC,0 \n"
        "      bra 1b            \n"  );
 
It would be nice to be able to create some macro whose use would be
#define SPI1STAT  0x3FC
#define SPIRBF  0
#define SPITBF   1
 
wait_0 (SPI1STAT,SPIRBF); // hangs as long as  the bit is 0
wait_1 (SPI1STAT,SPITBF); // hangs as long as the bit is 1
 
Additionally it would be nice to inline this.
So exactly how do you do this?
 
 
#1

35 Replies Related Threads

    andersm
    Super Member
    • Total Posts : 2621
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/23 12:00:42 (permalink)
    0
    As long as the parameters are compile-time constants, all you need is some C preprocessor trickery and string concatenation:
    #define xstr(s) str(s)
    #define str(s) #s

    #define wait_0(addr, bit) do { \
            asm ( \
                    "1: btss " xstr(addr) ", #" xstr(bit) "\n\t" \
                    "   bra 1b\n\t" \
                    ); \
        } while(0)

    #2
    dan1138
    Super Member
    • Total Posts : 3166
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/23 12:02:05 (permalink)
    0
    Give this a try:
        asm volatile(
           "1:  BTSS  %0,#%1\n"
           "     bra 1b   \n"
           : /* no outputs */
           : "T"(SPI1STATL), "i"(_SPI1STATL_SPIRBF_POSITION)
           : /* no registers changed */
           )



    post edited by dan1138 - 2019/04/23 12:12:36
    #3
    NKurzman
    A Guy on the Net
    • Total Posts : 17610
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/23 13:05:09 (permalink)
    +1 (1)
    Did you Try the Eval Version with a higher optimization? 
    Or is your Plan to generate a C / ASM hybrid Program?
     
    SPI1STAT  should be defined in one of the Header Files.  The Bits maybe defined already too.  It maybe next to where SPI1STATLbits is defined.
    #4
    vjasinski
    Super Member
    • Total Posts : 156
    • Reward points : 0
    • Joined: 2013/04/30 11:48:06
    • Location: Michigan, USA
    • Status: offline
    Re: inline assembly 2019/04/24 05:34:28 (permalink)
    0
    As described by NKurzman, the the following was compiled using XC16 optimization level 1
    88: _SPI4MD = 0; // enable the module
    003686 A9276A BCLR PMD6, #1
    89: while(_SPI4MD != 0);
    003688 AB276A BTST PMD6, #1
    00368A 3AFFFE BRA NZ, .L3

    #define _SPI4MD PMD6bits.SPI4MD

    The define is in the device header file included via xc.h
    That should do what you want.
    Vince
    #5
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:14:23 (permalink)
    0
    why the do while?
     
    #6
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:21:53 (permalink)
    0
    C/asm hybrid.
    Trying to port the st7735s arduino library over to the PIC24.  It is proving to be non-trivial.  They rely on delays, to allow bytes to be transmitted, then control the cs.  Trying to capture all this on a logic analyzer and figure out why
    it is not working, I need a way to make certain that a spi transmission has completely transmitted the byte.  But having a bunch of
    1: mov SPI1STATL,W1
    mov #02,W0
    and W1,W0,W0
    cp0 wo
    bra nz  1b
    in my code rather than
    1: btss SPI1STATL,#2
        bra 1b
    is cleaner and much faster.
     
    In order to debug the code, I have had to slow the SPI down to 247 khz so I can get my salae logic 16 to capture and decode the spi stream.  Of course, this means that the data gets way out of sync with cs and the like, so I need to make sure that each byte is fully transmitted.
    Using SPIRBF vs SPIRBE seems to be problematic (I get hangs)....
    anyrate that is another problem.
     
     
    #7
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:26:30 (permalink)
    0
    I don't have the professional version.  having to use the crippled standard version, damn Microchips hide....
    The only optimization level is 0.
     
     
    #8
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:32:04 (permalink)
    0
    Dan thanks.
    I am trying to understand this code....
    can it be written
    #define SPI_SPIRBF 2
    asm volatile ("1: BTSS %0,#%1 \n"
                       "     BRA  1b           \n" ::"T"(SPISTATL),"i"(SPI_SPIRBf): )
    Trying to understand the "T" (SPISTATL) and "i"(_SPISTATL_SPIRBF_POSITION)
    what does that accomplish?  I've read through the enhanced assemby stuff, and really don't understand it....
     
     
     
     
    #9
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:36:22 (permalink)
    0
    All this is complicated by the fact that the ST7735S arduino library is C++
     
     
    #10
    NKurzman
    A Guy on the Net
    • Total Posts : 17610
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 08:46:41 (permalink)
    0
    scrungy
    I don't have the professional version.  having to use the crippled standard version, damn Microchips hide....
    The only optimization level is 0.

    No, You should have level 1 also.  What Version do you have?
    You can Rent the Compiler for about $30 (USD) per month.
    #11
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 09:27:14 (permalink)
    0
    https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html  I think I understand this now.
    hmm.
    doing that and 
    #define SPI1TBF 2
    wait_0 (SPISTATL,SPI1TBF);
    results in a red tag in the editor   when hovering over it it is saying
    unexpected token:  do
     
     
    #12
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 09:42:39 (permalink)
    0
    1.36 standard.
    hmm.. interesting link, so it looks like optimization -O1 is allowed.
    https://hackaday.io/project/27250-mcu-how-tos-reviews-rants/log/72734-exploring-microchip-xc16-compiler
     
    Now: to see how to turn it on....
     
     
     
    #13
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: inline assembly 2019/04/24 09:43:30 (permalink)
    0
    scrungy
    Because a while (!SPI1STATLbits.SPIRBF);   generates a lot of overhead, ...

    That would be optimization level 0.  Free mode has optimization level 1, and it generates:

    27: while(!SPI1STATLbits.SPIRBF);
    00304 AB0308 btst.b 0x0308,#0
    00306 32FFFE bra z, 0x000304

    #14
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: inline assembly 2019/04/24 09:48:10 (permalink)
    0
    scrungy
    why the do while?

    The "do { ... } while (0)" is a standard way to wrap a macro so the content of the macro executes in the way it was intended to.
     
    Edit: That said, in that macro it was not necessary as it's only one statement and can be coded as:

    #define wait_0(addr, bit)  asm volatile ( \
                    "1: btss " xstr(addr) ", #" xstr(bit) "\n\t" \
                    "   bra 1b\n\t" )

    post edited by 1and0 - 2019/04/24 10:01:03
    #15
    aschen0866
    Super Member
    • Total Posts : 4481
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: inline assembly 2019/04/24 09:57:58 (permalink)
    #16
    andersm
    Super Member
    • Total Posts : 2621
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 11:00:34 (permalink)
    0
    scrungywhy the do while?

    If you have a macro that expands to multiple statements, and you use it as the body of an if-statement, the result will not be what you want. The do-while wraps the body of the macro into a single statement, protecting you from that error.

    #define my_nifty_macro() do_something(); \
        do_something_else()
     
    if (whatever)
      my_nifty_macro();
     
    // Error:
    if (whatever)
      do_something();
    do_something_else();
     
    #define my_other_macro() do { \
      do_something(); \
      do_something_else(); \
    } while(0)
     
    // OK
    if (whatever)
      do {
        do_something();
        do_something_else();
      } while(0);

    #17
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: inline assembly 2019/04/24 11:23:51 (permalink)
    +1 (1)
    ... and even if you wrap the macro in braces it can still break; for example, this
    #define my_nifty_macro(x) { do_something(x); do_something_else(x); }

    if (whatever)
      my_nifty_macro(1);
    else
      my_nifty_macro(2);

    expands to
    if (whatever)
    {
      do_something(1);
      do_something_else(1);
    };
    else
    {
      do_something(2);
      do_something_else(2);
    };

    which will break the else branch away from the if() statement and result in a build error.
     
    #18
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 11:32:14 (permalink)
    0
    Set -O1 in command line in the IDE 5.15 optional parameters window.
    Also set -g to force it to save the temporary files.
    and indeed, I do see the code
    .L16  btst.b SPISTATLbits,#1
           bra nz   .L16
    So turned off the -g, and just left -O1  and I can verify that in the compile file, however, once the file is compiled, and I go look at the code in memory, it is NOT that.  It is still the old load, and, ... etc.
     
    I'm lost....
    what is going on?
     
     
    #19
    scrungy
    Senior Member
    • Total Posts : 133
    • Reward points : 0
    • Joined: 2016/02/02 09:56:54
    • Location: 0
    • Status: offline
    Re: inline assembly 2019/04/24 11:40:02 (permalink)
    0
    thanks for the clarification.  I understand it now...
     
     
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5