Shop OBEX P1 Docs P2 Docs Learn Events
Probably another misunderstanding on my part.. — Parallax Forums

Probably another misunderstanding on my part..

Jack BuffingtonJack Buffington Posts: 115
edited 2013-06-13 11:45 in Propeller 1
I'm continuing on with my project and am hitting some difficulty again. I am using inline assembly since I am short on the number of cycles available and the compiler isn't generating tight enough code. That's OK though I can work in assembly.

I have a bit of code that is supposed to work like a serial port running at about 1.8 MHz. Here is the assembly that I am giving it:
__asm__ volatile(
     //  a bunch of other code here but I am just showing the last bit for the sake of simplicity
     //  It is pretty much a bunch of repetitions of the snippet shown below.

        "waitcnt    %[temp1],%[waitDelay]\n\t"  // bit 7        
        "mov        %[temp3],INA\n\t" 
        "and        %[temp3],%[theBit]\n\t"         // clear everything but the bit that I am looking at
        "shr        %[outLong],#1\n\t"
        "add        %[outLong],%[temp3]\n\t"    


        : //outputs 
            [outLong]     "=r" (outLong)
        : //inputs 
            [temp1] "r" (temp1),
            [theBit] "r" (theBit),
            [LED] "r" (LED),
            [waitDelay] "r" (waitDelay),
            [zero] "r" (zero),
            [temp3] "r" (temp3)          
        );




The compiled version of this looks like this with what the code should be in comments to its right:
  69 00dc 0000BCF8         waitcnt    r6,r2         // waitcnt    temp1,waitDelay
  70 00e0 0000BCA0         mov        r7,INA        // mov        temp3,INA
  71 00e4 0000BC60         and        r7,r5         // and        temp3,theBit
  72 00e8 0100FC28         shr        r7,#1         // shr        outLong,#1
  73 00ec 0000BC80         add        r7,r7         // add        outLong,temp3

For some reason, it is using r7 as both temp3 and outLong, which doesn't do what I want. Is there a way to force it to honor the difference between these variables? I tried sticking in volatile after __asm__ as suggested by this page https://sites.google.com/site/propellergcc/documentation/tutorials/inline-asm-basics but that didn't do the trick.

Any ideas?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-05-30 17:29
    This looks familiar, check this [post=1169646]post[/post].
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-05-30 18:29
    Thank you! It seems to be working now.

    For those of you who might be reading this in the future, I changed:

    [outLong] "=r" (outLong)
    to
    [outLong] "&=r" (outLong)

    Now, I need to dive into the documentation to really understand why this did the trick.
  • SRLMSRLM Posts: 5,045
    edited 2013-05-30 21:01
    The pages on constraints are good reading: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-06-06 18:28
    Here's another one that I am having trouble with. I am trying to write a function to read three buttons on my board and return a priority-encoded value based on what buttons are pushed. The following C code doesn't compile properly:

    //-------------------------------------------------------------------------------------------------------------------------------
    volatile int readButtons()
        {// top button takes highest priority if multiple buttons are being pushed
        if(INA & (1<<6) == (1<<6))
            return 1;
        if(INA & (1<<7) == (1<<7))
            return 2;
        if(INA & (1<<8) == (1<<8))
            return 3;
        return 0;
        }
    

    Here is the assembly code that is generated:
    
     149:encoderDevice02.c **** volatile int readButtons()
     150:encoderDevice02.c ****     {// top button takes highest priority if multiple buttons are being pushed
       7                      .loc 1 150 0
       8 0000 031E             lpushm    #16+14
       9                  .LCFI0
      10 0002 F2101CA0         mov    r14, sp
      11                  .LCFI1
     151:encoderDevice02.c ****     if(INA & (1<<6) == (1<<6))
      12                      .loc 1 151 0
      13 0006 F2000EA0         mov    r7, INA
      14 000a F9010E60         test    r7,#0x1 wz
     152:encoderDevice02.c ****         return 1;
      15                      .loc 1 152 0
      16 000e 8AA001           IF_NE mov    r0, #1
     151:encoderDevice02.c ****     if(INA & (1<<6) == (1<<6))
      17                      .loc 1 151 0
      18 0011 751D             IF_NE    brs    #.L2
     153:encoderDevice02.c ****     if(INA & (1<<7) == (1<<7))
      19                      .loc 1 153 0
      20 0013 F2000EA0         mov    r7, INA
      21 0017 F9010E60         test    r7,#0x1 wz
     154:encoderDevice02.c ****         return 2;
      22                      .loc 1 154 0
      23 001b 8AA002           IF_NE mov    r0, #2
     153:encoderDevice02.c ****     if(INA & (1<<7) == (1<<7))
      24                      .loc 1 153 0
      25 001e 7510             IF_NE    brs    #.L2
     155:encoderDevice02.c ****     if(INA & (1<<8) == (1<<8))
      26                      .loc 1 155 0
      27 0020 F2000EA0         mov    r7, INA
      28 0024 FB010E60         and    r7,#1 wz
     156:encoderDevice02.c ****         return 3;
      29                      .loc 1 156 0
      30 0028 2702             cmps    r7, #0 wz,wc
      31 002a 85A000           IF_E  mov    r0,#0
      32 002d 8AA003           IF_NE mov    r0,#3
      33                  .L2
     157:encoderDevice02.c ****     return 0;
    

    It doesn't appear to be doing the correct thing. It is doing some optimization here, which is good because what I have to do in C isn't optimal but the line:

    test r7,#0x1 wz

    Is comparing what was copied from INA to the value 1, which isn't what I want. In my case, I really need to compare to 1<<6, 1<<7, or 1<<8 to get correct answers.

    Is there a setting or keyword that I can use (short of setting things to -O0) to keep the compiler from being so hyperactive about its optimization that it loses sight of what I am asking it to do?

    No hurry on this one though, it was relatively easy to drop to assembly for this one.
  • kuronekokuroneko Posts: 3,623
    edited 2013-06-06 18:53
    No hurry on this one though, it was relatively easy to drop to assembly for this one.
    In C binary AND (&) has lower priority than == so for what you want you need brackets around your & part. Enabling warnings from now on would also be a good idea.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-06-06 18:56
    I'm not sure of the relative precedence of == and & but you might be safer with this:
        if((INA & (1<<6)) == (1<<6))
            return 1;
    
  • David BetzDavid Betz Posts: 14,516
    edited 2013-06-06 18:58
    kuroneko wrote: »
    In C binary AND (&) has lower priority than == so for what you want you need brackets around your & part. Enabling warnings from now on would also be a good idea.
    Ah, I see you beat me to it! :-)
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-06-07 16:04
    Thanks again guys! Because of you, I am slowly getting the hang of this compiler.

    ...Though this one ended up not having anything to do with the compiler. I can't believe that I have never run across this one before.
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-06-13 11:45
    Ok, I have another one for you guys, The program that I am working on needs to use both TV output and launch a pasm cog (from a .spin file). As of yesterday I had all of my graphics working properly and started to make it run my pasm COG but just couldn't get it to launch. Today I gave up on that and decided to try to make it launch the toggle pasm cog instead. That didn't work so I slowly commented out sections of my code to try to figure out where the problem was. Eventually I got to just the launch and setup code for the toggle cog and it still didn't work. Grasping at straws, I removed the references to the tv and graphics files in the project manager and suddenly my LED was blinking away. Great! Now I added back the references to tv and graphics and the led kept blinking. Still good. Finally I uncommented all of my code relating to tv and graphics. The LED kept blinking but my screen never showed anything. I realize that the screen should be glitchy at first when the LED was blinking since toggle is toggling the pins that I am using for TV output too but nothing was on the screen once the LED stopped blinking. As one final experiment, since it seemed to have something to do with the project manager, I decided to remove the reference to toggle.spin and then immediately add it right back in. Now when I run it, neither the LED blinks nor does the screen come alive.

    Do any of you have any ideas about this one?

    Update....

    I just built a new project from scratch that only has the toggle cog and the TV and graphics stuff. This project isn't allowing me to run both things at the same time as well.

    Here is the code for that project:
    /*  LensEncoderDevice.c
    
    
    
    
    
    
    
    
    */
    
    
    #include "propeller.h"
    #include "tv.h"
    #include "Graphics.h"
    
    
    
    
    void startTVgraphics();
    void startToggleCog();
    void drawSomethingOnTheScreen();
    
    
    
    
    // STUFF FOR THE TV AND GRAPHICS COG
    #define X_TILES         10 
    #define Y_TILES         7 
    #define X_EXPANSION     16 
    #define Y_EXPANSION     2                    
    #define X_ORIGIN        0 // sets the origin to be the bottom left corner
    #define Y_ORIGIN        0 
    #define MAX_COLORS      64
    HUBDATA TV_t  gTV;
    HUBDATA volatile uint16_t gScreen[X_TILES * Y_TILES];
    HUBDATA volatile uint32_t gColors[MAX_COLORS];
    HUBDATA volatile uint32_t gDisplay[(X_TILES * Y_TILES << 4)+128];
    HUBDATA volatile uint32_t gBitmap [(X_TILES * Y_TILES << 4)+128];
    HUBDATA volatile unsigned int bottomButton = 1 << 6;
    #define BITMAP_BASE (((int)gBitmap +256) & ~127)    // page align
    #define DISPLY_BASE (((int)gDisplay+256) & ~127)
    
    
    
    
    
    
    
    
    // VARIABLES FOR THE TOGGLE COG
    static uint32_t delay; // a pointer to this gets passed to the PASM code as the PAR register
    static uint32_t pins;  
    static uint32_t loop_cnt;
    static uint32_t pasm_done;
    
    
    
    
    _COGMEM volatile unsigned int LED = 1 << 13;
    
    
    //------------------------------------------------------------------------------------------------
    int main()                                    
        {
        startToggleCog();
        startTVgraphics();
        drawSomethingOnTheScreen();
    
    
        while(1)                                    
            {
            }  
        }// end of main
    
    
    //------------------------------------------------------------------------------------------------
    void startTVgraphics()
        {
        int n, dx, dy;
        int cog;
        TV_t* tp = &gTV;
    
    
        tp->enable = 1;
        tp->pins   = TV_BASEBAND_PIN(24); 
        tp->mode   = 0;
        tp->screen = (uint32_t) &gScreen[0];     
        tp->colors = (uint32_t) &gColors[0];     
        tp->ht     = X_TILES;
        tp->vt     = Y_TILES;
        tp->hx     = X_EXPANSION;
        tp->vx     = Y_EXPANSION;
        tp->ho     = 0;
        tp->vo     = 0;
        tp->broadcast = 0;
        tp->auralcog  = 0;
    
    
        cog = TV_start(tp);
    
    
    
    
    
    
        // init colors
        for(n = 0; n < MAX_COLORS; n++)
            gColors[n] = 0x1010 * ((n+4) & 0xF) + 0x2B060C02;
    
    
        // init tile screen
        for (dx = 0; dx < tp->ht; dx++)
            for (dy = 0; dy < tp->vt; dy++)
                gScreen[dy * tp->ht + dx] = (DISPLY_BASE >> 6) + dy + dx * tp->vt + ((dy & 0x3F) << 10);
    
    
    
    
        // start graphics cog
        Graph_start();
        Graph_setup(X_TILES, Y_TILES, X_ORIGIN, Y_ORIGIN, BITMAP_BASE);
        }
    
    
    //------------------------------------------------------------------------------------------------
    void startToggleCog()
        { // just blinks my LED pin now.
        delay = CLKFREQ>>4;  
        pins = LED;                   
        loop_cnt = 50;                    
        pasm_done = 0;
    
    
        extern unsigned int binary_toggle_dat_start[];
        cognew(&binary_toggle_dat_start, &delay);
        }
    
    
    //------------------------------------------------------------------------------------------------
    void drawSomethingOnTheScreen()
        {
        Graph_colorwidth(2,0);
        Graph_textmode(1,1,6,0);
        Graph_text(120,0,"Menu ->");
    }
    

    The compiler settings are:
    EEPROM
    C
    CMM
    -O1 Mixed



    I have also tried tucking the toggle cog stuff into the graphics demo program. The graphics portion runs but the toggle won't. If I take all of the graphics and TV stuff out of the project manager and put it right back in then the LED blinks but there are no graphics....
Sign In or Register to comment.