2 or more COG's running assembler
I want to launch 2 COG's that each toggle different I/O pins ad infinitum at different frequencies in assembler using consecutive Spin statements
coginit(6,@routine1,var)
coginit(7,@routine2,var)
Not particularly useful (given the counters) but just want to demonstrate that it works OK (in assembler) before attempting something more interesting....
My routine1 and 2 work fine with 1 COG operating but not 2.
Can someone out there tell me how the DAT section of my program should be structured to get this to work properly ?
Thanks
coginit(6,@routine1,var)
coginit(7,@routine2,var)
Not particularly useful (given the counters) but just want to demonstrate that it works OK (in assembler) before attempting something more interesting....
My routine1 and 2 work fine with 1 COG operating but not 2.
Can someone out there tell me how the DAT section of my program should be structured to get this to work properly ?
Thanks

Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
The second org is commented out at the moment.· When·this code·runs P0 has the expected square wave.
If I include the second org·only P1·appears to produce output, at a lower frequency, of course.· I am running this on a PropStick.
So how do we make both·COG's run simultaneously ?
A related·question would be - what happens if one's assembler segment needs to exceed 512 longs ??·- OK we could use a second, or third COG but how then should the DAT segment of the program be structured ?
Can't wait for the assembler manual to appear - who knows when this might be ?
I havent had a chance to get to the assembly section myself, I am still enjoying reading over the tutorial at this moment.
-JLBShecky
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-JLBShecky
Fantastic to see this made available. Thanks Parallax !! Hopefully should shed light on this issue.
-Phil
I think this is what Phil is trying to describe, only I did not seperate t1 from t2..... I tested this code, and on pin0 I read a 500kHz square and on pin1 I read a 50kHz square.
Note: You don't need the second DAT, I just did this as visual symetry.
' 2 COG assembler program, July 8th, 2006 ' Produce square waves on pins P1, P0 ' ' Pin Utilization ' ' P0 controlled by COG 6 ' P1 controlled by COG 7 [b]CON[/b] [b]_clkmode[/b] = [b]xtal[/b]1 + [b]pll[/b]16x [b]_xinfreq[/b] = 5_000_000 [b]VAR[/b] [b]long[/b] param [b]PUB[/b] start param := 0 [b]coginit[/b](6,@cog6, param) 'launch assembly program in 1st COG [b]waitcnt[/b]([b]cnt[/b] + 2_000) [b]coginit[/b](7,@cog7, param) 'launch assembly program in 2nd COG [b]waitcnt[/b]([b]cnt[/b] + 2_000) [b]DAT[/b] [b]org[/b] cog6 [b]or[/b] [b]dira[/b],#$01 [b]mov[/b] t1,[b]cnt[/b] [b]add[/b] t1,delay1 [b]repeat[/b]1 [b]waitcnt[/b] t1,delay1 [b]xor[/b] [b]outa[/b],data1 [b]jmp[/b] #[b]repeat[/b]1 ' Initialized data delay1 [b]long[/b] 80 data1 [b]long[/b] 1 [b]DAT[/b] [b]org[/b] cog7 [b]or[/b] [b]dira[/b],#$02 [b]mov[/b] t2,[b]cnt[/b] [b]add[/b] t2,delay2 [b]repeat[/b]2 [b]waitcnt[/b] t2,delay2 [b]xor[/b] [b]outa[/b],data2 [b]jmp[/b] #[b]repeat[/b]2 ' Initialized data delay2 [b]long[/b] 800 data2 [b]long[/b] 2 ' Uninitialized data t1 [b]res[/b] 1 t2 [b]res[/b] 1▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
I believe your solution will work so long as cog6's code is no longer than cog7's. But if it's longer, t1 will have an address that collides with cog6's code, because it's referenced to the second org. This is one place where the "put all res statements last" rule needs to be broken. t1 belongs after data1. It won't interfere with cog7 there because cog7 will be loaded into a different cog. (Referencing addresses accross org boundaries is something the assembler ought to be flagging with a warning.)
Richard, I would encourage you to use cognew instead of coginit, BTW. Your programs will be more portable if they don't depend on which cogs actually contain your code.
-Phil
I confirmed Beau's modification works but also proved that Phil is correct too - adding just one NOP after the first XOR instruction while having both t1 and t2 in the same uninitialized data section at the very end of the program after the second org causes the high frequency square wave to get clobbered - so do separate all variables used by different COG's as Phil suggests (sounds like one for the Tricks and Traps Phil)
Thanks for the heads up on merits of COGNEW vs COGINIT too...
assembly parts with their interactions trough the PAR register.
SPIN_vs_ASM:
CON 'Set clock speed to 80 MHz _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ Usart: "Simple_Serial" Numbr: "Simple_Numbers" VAR long LNum1, LNum2 PUB Start Usart.start(-1, 0, 19_200) WaitCnt(50_000_000 + Cnt) Usart.str(string("Usart object started",13,10)) LNum1 := $123456 LNum2 := $654321 Usart.str(Numbr.ihex(LNum1, 6)) Usart.tx(13) Usart.tx(10) Usart.str(Numbr.ihex(LNum2, 6)) Usart.tx(13) Usart.tx(10) cognew(@TestAsm, @LNum1) 'Start new cog with address of var waitcnt(cnt + 200_000) 'Wait for cog to run Usart.str(Numbr.ihex(LNum1, 6)) Usart.tx(13) Usart.tx(10) Usart.str(Numbr.ihex(LNum2, 6)) Usart.tx(13) Usart.tx(10) DAT org 0 TestAsm mov ParPtr, PAR 'Get address of SPIN var into local ParPtr RdLong Num, ParPtr 'Read Value of SPIN var into local var Num add Num, #5 'Add local 5 into local var Num WrLong Num, ParPtr 'Write local var Num back into SPIN var add ParPtr, #4 'Prepare for getting next SPIN var RdLong Num, ParPtr 'Read Value of SPIN var into local var Num add Num, #3 'Add local 3 into local var Num WrLong Num, ParPtr 'Write local var Num back into SPIN var Wt jmp #Wt 'Wait infinitely ' Uninitialized data ParPtr res 1 Num res 1TwoPinsToggleWithTwoCogs.spin:
CON 'Set clock speed to 80 MHz _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ Usart: "Simple_Serial" Numbr: "Simple_Numbers" VAR long LNum1, LNum2 PUB Start Usart.start(-1, 0, 19_200) WaitCnt(50_000_000 + Cnt) Usart.str(string("Usart object started",13,10)) LNum1 := $123456 LNum2 := $654321 Usart.str(Numbr.ihex(LNum1, 6)) Usart.tx(13) Usart.tx(10) Usart.str(Numbr.ihex(LNum2, 6)) Usart.tx(13) Usart.tx(10) cognew(@TestAsm, @LNum1) 'Start new cog with address of var waitcnt(cnt + 200_000) 'Wait for cog to run Usart.str(Numbr.ihex(LNum1, 6)) Usart.tx(13) Usart.tx(10) Usart.str(Numbr.ihex(LNum2, 6)) Usart.tx(13) Usart.tx(10) DAT org 0 TestAsm mov ParPtr, PAR 'Get address of SPIN var into local ParPtr RdLong Num, ParPtr 'Read Value of SPIN var into local var Num add Num, #5 'Add local 5 into local var Num WrLong Num, ParPtr 'Write local var Num back into SPIN var add ParPtr, #4 'Prepare for getting next SPIN var RdLong Num, ParPtr 'Read Value of SPIN var into local var Num add Num, #3 'Add local 3 into local var Num WrLong Num, ParPtr 'Write local var Num back into SPIN var Wt jmp #Wt 'Wait infinitely ' Uninitialized data ParPtr res 1 Num res 1These two programs are only ment to show using cognew with parameter passing.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
What God wants, God gets . . .
Her is the other one:
TwoPinsToggleWithTwoCogs.spin:
' 4 COG assembler program, July 11th, 2006 ' Produce square waves on pins P16+17,18+19,20+21 and 22+23 CON _clkmode = xtal1 + pll16x ' 80 MHz _xinfreq = 5_000_000 P16 = |< 16 P17 = |< 17 Del1 = 500 ' millisec P18 = |< 18 P19 = |< 19 Del2 = 2000 P20 = |< 20 P21 = |< 21 Del3 = 4000 P22 = |< 22 P23 = |< 23 Del4 = 8000 VAR long HPins1, HDlay1 long HPins2, HDlay2 long HPins3, HDlay3 long HPins4, HDlay4 PUB start HPins1 := P16 | P17 HDlay1 := CLKFREQ / 1000 * Del1 HPins2 := P18 | P19 HDlay2 := CLKFREQ / 1000 * Del2 HPins3 := P20 | P21 HDlay3 := CLKFREQ / 1000 * Del3 HPins4 := P22 | P23 HDlay4 := CLKFREQ / 1000 * Del4 cognew(@cogBlink, @HPins1) 'launch assembly program in new COG waitcnt(cnt + 2_000) cognew(@cogBlink, @HPins2) waitcnt(cnt + 2_000) cognew(@cogBlink, @HPins3) waitcnt(cnt + 2_000) cognew(@cogBlink, @HPins4) waitcnt(cnt + 2_000) DAT org 0 CogBlink mov ParPtr, PAR RdLong Pins, ParPtr add ParPtr, #4 RdLong Dlay, ParPtr mov dira, Pins mov Tmp, cnt add Tmp, Dlay RptBlink xor outa, Pins waitcnt Tmp, Dlay jmp #RptBlink ' Uninitialized data ParPtr res 1 Pins res 1 Dlay res 1 Tmp res 1▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
What God wants, God gets . . .