Shop OBEX P1 Docs P2 Docs Learn Events
Assembly language issue?? — Parallax Forums

Assembly language issue??

Jack BuffingtonJack Buffington Posts: 115
edited 2013-05-28 22:58 in Propeller 1
I'm working with the C compiler to make a device that can read VITC timecode, drive a display, receive and send serial data, and read three quadrature encoders. The propeller is making that pretty easy for the most part. I'm hitting one snag though and I think it isn't anything to do with the C compiler so I am posting it over here.

I'm writing some code to read my encoders and am having an issue. For some reason, I have to add a small amount of delay in or the whole cog hangs.

Here is my C code (simplified to the minimum amount to still have the issue still happen:
#include <propeller.h>


static _COGMEM unsigned int nextcnt;
static _COGMEM unsigned int waitdelay;


extern unsigned int iris;


_NATIVE
void main ()
    {
    waitdelay = 48;  // 48 works, 47 doesn't
    nextcnt = _CNT + waitdelay;


    while(1)
        {
        iris = INA & 0b11;
        nextcnt = waitcnt2(nextcnt, waitdelay);
        }
    }

Here is the assembly listing that I get from that:
   1                      .text
   2                  .Ltext0
   3                      .balign    4
   4                      .global    _main
   5                      .global    _main_ret
   6                  _main
   7                  .LFB0
   8                      .file 1 "encoder.cogc"
   1:encoder.cogc  **** #include <propeller.h>
   2:encoder.cogc  **** 
   3:encoder.cogc  **** static _COGMEM unsigned int nextcnt;
   4:encoder.cogc  **** static _COGMEM unsigned int waitdelay;
   5:encoder.cogc  **** 
   6:encoder.cogc  **** extern unsigned int iris;
   7:encoder.cogc  **** 
   8:encoder.cogc  **** _NATIVE
   9:encoder.cogc  **** void main ()
  10:encoder.cogc  ****     {
   9                      .loc 1 10 0
  11:encoder.cogc  ****     waitdelay = 48;  // 48 works, 47 doesn't
  12:encoder.cogc  ****     nextcnt = _CNT + waitdelay;
  10                      .loc 1 12 0
  11 0000 0000BCA0         mov    r7, CNT
  11:encoder.cogc  ****     waitdelay = 48;  // 48 works, 47 doesn't
  12                      .loc 1 11 0
  13 0004 3000FCA0         mov    _waitdelay, #48
  14                      .loc 1 12 0
  15 0008 3000FC80         add    r7, #48
  16                  .L3
  17 000c 0000BCA0         mov    _nextcnt, r7
  13:encoder.cogc  **** 
  14:encoder.cogc  ****     while(1)
  15:encoder.cogc  ****         {
  16:encoder.cogc  ****         iris = INA & 0b11;
  18                      .loc 1 16 0
  19 0010 0000BCA0         mov    r7, INA
  20 0014 0300FC60         and    r7, #3
  21 0018 00003C08         wrlong    r7, .LC0
  17:encoder.cogc  ****         nextcnt = waitcnt2(nextcnt, waitdelay);
  22                      .loc 1 17 0
  23 001c 0000BCA0         mov    r7, _nextcnt
  24 0020 0000BCF8         waitcnt    r7,_waitdelay
  25 0024 00007C5C         jmp    #.L3
  26                  .LFE0
  27                      .balign    4
  28                  .LC0
  29 0028 00000000         long    _iris
  30                  _waitdelay
  31 002c 00000000         long    0
  32                  _nextcnt
  33 0030 00000000         long    0
  61                  .Letext0
  62                      .file 2 "c:\\propgcc\\bin\\../lib/gcc/propeller-elf/4.6.1/../../../../propeller-elf/include/cog.h"



If I modify things so that I do a bit more calculation, I need to add more delay. Here I copy my port into a temp variable that I then multiply by 3 before writing to my HUB variable. In this case, I have to wait 112 clock ticks for the program to work.
1                      .text   2                  .Ltext0
   3                      .balign    4
   4                      .global    _main
   5                      .global    _main_ret
   6                  _main
   7                  .LFB0
   8                      .file 1 "encoder.cogc"
   1:encoder.cogc  **** #include <propeller.h>
   2:encoder.cogc  **** 
   3:encoder.cogc  **** static _COGMEM unsigned int nextcnt;
   4:encoder.cogc  **** static _COGMEM unsigned int waitdelay;
   5:encoder.cogc  **** static _COGMEM unsigned int temp;
   6:encoder.cogc  **** 
   7:encoder.cogc  **** 
   8:encoder.cogc  **** extern unsigned int iris;
   9:encoder.cogc  **** 
  10:encoder.cogc  **** _NATIVE
  11:encoder.cogc  **** void main ()
  12:encoder.cogc  ****     {
   9                      .loc 1 12 0
  13:encoder.cogc  ****     waitdelay = 112; 
  14:encoder.cogc  ****     nextcnt = _CNT + waitdelay;
  10                      .loc 1 14 0
  11 0000 0000BCA0         mov    r7, CNT
  13:encoder.cogc  ****     waitdelay = 112; 
  12                      .loc 1 13 0
  13 0004 7000FCA0         mov    _waitdelay, #112
  14                      .loc 1 14 0
  15 0008 7000FC80         add    r7, #112
  16                  .L3
  15:encoder.cogc  **** 
  16:encoder.cogc  ****     while(1)
  17:encoder.cogc  ****         {
  18:encoder.cogc  ****         temp = INA & 0b11;
  17                      .loc 1 18 0
  18 000c 0000BCA0         mov    r0, INA
  14:encoder.cogc  ****     nextcnt = _CNT + waitdelay;
  19                      .loc 1 14 0
  20 0010 0000BCA0         mov    _nextcnt, r7
  19:encoder.cogc  ****         temp *= 3;
  21                      .loc 1 19 0
  22 0014 0300FCA0         mov    r1, #3
  18:encoder.cogc  ****         temp = INA & 0b11;
  23                      .loc 1 18 0
  24 0018 0300FC60         and    r0, #3
  25                      .loc 1 19 0
  26 001c 0000FC5C         call    #__MULSI
  20:encoder.cogc  ****         iris = temp;
  21:encoder.cogc  ****         nextcnt = waitcnt2(nextcnt, waitdelay);
  27                      .loc 1 21 0
  28 0020 0000BCA0         mov    r7, _nextcnt
  19:encoder.cogc  ****         temp *= 3;
  29                      .loc 1 19 0
  30 0024 0000BCA0         mov    _temp, r0
  20:encoder.cogc  ****         iris = temp;
  31                      .loc 1 20 0
  32 0028 00003C08         wrlong    r0, .LC0
  33                      .loc 1 21 0
  34 002c 0000BCF8         waitcnt    r7,_waitdelay
  35 0030 00007C5C         jmp    #.L3
  36                  .LFE0
  37                      .balign    4
  38                  .LC0
  39 0034 00000000         long    _iris
  40                  _waitdelay
  41 0038 00000000         long    0
  42                  _nextcnt
  43 003c 00000000         long    0
  44                  _temp
  45 0040 00000000         long    0
  73                  .Letext0
  74                      .file 2 "c:\\propgcc\\bin\\../lib/gcc/propeller-elf/4.6.1/../../../../propeller-elf/include/cog.h"



The problem doesn't have anything to do with my code (on another COG) that displays my values. That is still working because I am seeing some simulated timecode ticking away, which is generated by a third COG. There shouldn't be any issue with two COGs working with my 'iris' value because it is just one long and it isn't possible for two cogs to access it simultaneously. Does anyone have any idea what is going on here?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-05-28 15:59
    What exactly is the question? Clearly the loop takes time to run, IOW if it takes longer than your waitcnt advancement allows for then it gets stuck until rollover ... Can you elaborate?
  • SRLMSRLM Posts: 5,045
    edited 2013-05-28 16:16
    I'm missing the question too.

    If you want the loop to execute as fast as possible, then you might as well remove the waitcnt. If you loop has to be deterministic, then you'll need to figure out at what frequency you want it to run at, and set nextcnt appropriately. At 112 clock ticks per loop, that's 714kHz. As you have it (with the minimum non-locking value in nextcnt) your waitcnt doesn't actually add much delay, if any.
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-05-28 16:35
    Ah. I see what is going on. I made an example to show that it didn't work without the waitcnt instruction in there but when I looked at the assembly listing, it wasn't even copying it to the HUB at all (or ANDing it with #3). So it was a combination of two things: It compiled properly if I stuck the waitcnt instruction in but didn't compile properly if I didn't have it in there. The second thing was that I was mis-remembering how waitcnt worked. I was thinking that it was pausing for N counts before continuing but really it is adding waitdelay to the last CNT and waiting until that time came around. That explains the hanging.

    Thanks!
  • David BetzDavid Betz Posts: 14,516
    edited 2013-05-28 17:03
    Ah. I see what is going on. I made an example to show that it didn't work without the waitcnt instruction in there but when I looked at the assembly listing, it wasn't even copying it to the HUB at all (or ANDing it with #3). So it was a combination of two things: It compiled properly if I stuck the waitcnt instruction in but didn't compile properly if I didn't have it in there. The second thing was that I was mis-remembering how waitcnt worked. I was thinking that it was pausing for N counts before continuing but really it is adding waitdelay to the last CNT and waiting until that time came around. That explains the hanging.

    Thanks!
    If two COGs are sharing the same variable you'll have to declare it as "volatile".
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-05-28 22:58
    Thanks David,

    When I originally read your reply, I thought "but I did declare it as volatile", since I thought that it only mattered in my main C file that launches the other cogs. Now that I have declared it in both files it is working.
Sign In or Register to comment.