Shop OBEX P1 Docs P2 Docs Learn Events
using a local variable in cognew fails — Parallax Forums

using a local variable in cognew fails

David BDavid B Posts: 592
edited 2014-06-23 16:23 in Propeller 1
Is it a known mistake to use a local variable when starting an asm cog?

I ran into a bug over the weekend that I traced to just that, as in this pseudocode.

This asm cog code worked perfectly until the main started setting another completely unrelated variable. When "do_something_else(parameter)" was called, suddenly the emitted frequency was way off.

In the actual code, the "start_nco" and the asm_sine code are in a separate object file from main, and the "do_something_else(parameter)" was also in a separate object file, in case that makes a difference.

I guess that the "start_nco" function starts the cog, then exits, releasing its ownership of the "counts" variable before the cog has initialized far enough along to read it. When the cog finally gets around to reading from that address, the value had been overwritten.

VAR

  long localvar 
  long varcounts  ' <-- the bug was fixed by moving "counts" up to the VAR section

PUB main

  start_nco(400)
  do_something_else(2)
  repeat


PUB start_nco(freq) | counts

  counts := ((53687 * freq)/1000)  
  cognew(@asm_sine, @counts)


PUB do_something_else(parameter)

'  return                     ' asm cog frequency is correct if this return is executed
  localvar := parameter       ' asm cog frequency is wrong if this line executes
  return


DAT

org 0

asm_sine   
        rdlong  frqa, par   
        configure counter to emit a frequency based on counts

Comments

  • Heater.Heater. Posts: 21,230
    edited 2014-06-23 11:42
    Well, local variables live on the stack. They cease to exist after the method exits. Well, except they hang around in memory until something else writes over them.

    So yes, you are asking for trouble.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-06-23 12:01
    It would work OK if asm_sine started running before start_nco returns, assuming you don't access PAR after the initial RDLONG. It takes about 4000 cycles before a cog is loaded and running, so a waitcnt(5000+cnt) after the cognew should work. Or you could use a global variable, which is a better solution.
  • David BDavid B Posts: 592
    edited 2014-06-23 13:25
    Thank you - I thought I knew my way around spin code pretty well, but this was kind of a surprise.
  • Mark_TMark_T Posts: 1,981
    edited 2014-06-23 14:27
    Dave Hein wrote: »
    It would work OK if asm_sine started running before start_nco returns, assuming you don't access PAR after the initial RDLONG. It takes about 4000 cycles before a cog is loaded and running, so a waitcnt(5000+cnt) after the cognew should work. Or you could use a global variable, which is a better solution.
    Over 8192 cycles, 512 hub ram accesses are required to start with and they each use 16 cycles.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-06-23 16:23
    Yes, you are right. Thanks for the correction.
Sign In or Register to comment.