Problems starting cogs from spin&asm

ManAtWorkManAtWork Posts: 427
edited 2019-12-23 - 15:56:05 in Propeller 1
I used cognew in spin for many times but now I need to start a cog from assembler for the first time. The following simple test program starts one cog from spin which executes assembler at label start1. This cog in turn starts a second cog which should execute assembler at label start2.
CON
  _clkmode = xinput + pll16x     'external oscillator, frequency = 5MHz * 16 = 80MHz
  _xinfreq = 5_000_000
  baudRate = 115_200


OBJ
  com : "FullDuplexSerial"

VAR
  byte  cog

PUB Start
  WaitMs (2000)
  com.Start(31, 30, 0, baudRate)
  cogInfo:= @result3 << 18 + @start2 << 4 
  
  com.str (string ("cogInfo=" ) )
  com.hex (cogInfo, 8)
  com.str (string (" @result3=" ) )
  com.hex (@result3, 8)
  com.str (string (" @start2=" ) )
  com.hex (@start2, 8)
  com.tx (13)
  
  cog:= cognew (@start1, @result1)

  WaitMs (100)  ' wait for cogs to startup...
  com.str (string ("cog="))
  com.hex (cog, 8)
  com.str (string (" result1="))
  com.hex (result1, 8)
  com.str (string (" result2="))
  com.hex (result2, 8)
  com.str (string (" result3="))
  com.hex (result3, 8)
  com.tx (13)
  repeat

PRI WaitMs (Duration)
  waitcnt(((clkfreq / 1_000 * Duration - 3932)) + cnt)

DAT
ORG
start1
              mov   adr,PAR
              add   adr,#4
              or    cogNo,cogInfo               ' or cogInfo + number
              wrlong cogNo,PAR                  ' write to result1

              coginit cogNo wr                  ' remember ID of started cog
              wrlong cogNo,adr                  ' write ID to result2

stop1         jmp #stop1

adr           long      0
cogInfo       long      0       ' @result3<<18 + @start2<<4 set from spin
cogNo         long      1<<3    ' No 8 means next free cog
result1       long      0             
result2       long      0

DAT
ORG
start2
              wrlong flag,PAR                   ' write #1 to result3
stop2         jmp #stop2

flag          long      1
result3       long      0

So I'd normally expect that the output is something like...
cog=2 (cog#0 and serial driver already running, cog#2 started by cognew)
result1=destination field for coginit
result2=3 (next free cog started by coginit)
result3=1 (test flag written by last cog)

However, this doesn't work. The output is
cogInfo=01700500 @result3=0000005C @start2=00000050
cog=00000002 result1=01700508 result2=00000003 result3=00000000
Result2 is written as 3 so it seems that coginit starts a cog. But the final flag is not written to result3. Depending on the length of code (inserting or commenting out some commands...) I sometimes get crashes so that the second line is not printed at all. So I guess that coginit does something but not the right thing, i.e. PAR or start adress point to something invalid. What have I done wrong?

Comments

  • ManAtWork wrote: »
    cogInfo:= @result3 << 18 + @start2 << 4
    

    The address bits of the coginit argument are the upper 14 bits only, you need to mask the lower two bits for each address (start and par) and adjust the bit shift.
    Something like:
    cogInfo:= ((@result3 >> 2) << 18) | ((@start2 >> 2) << 4)
    

    I haven't tested the code above so it is possible that I missed something, but that's the concept.
  • RaymanRayman Posts: 10,068
    edited 2019-12-23 - 16:41:48
    Yes, that's it. I just figured that out too...
    cogInfo:= (@result3 >> 2) << 18 + (@start2 >> 2) << 4
    
  • Ouch, yes, you are right. That's something you can read a 100 times and don't see the error... I thought I did it exactly like in the manual, but only the valid address bits have to be stuffed into the 14 bit fields.

    Thanks a lot. Now it works.
Sign In or Register to comment.