Beau,
Are you sure that's correct? Chip posted a very different short assembly routine that mostly made sure the clock was set according to what's specified in the SPIN program, but had a very different COGINIT operand that pointed to the SPIN interpreter in ROM so it gets loaded into the COG to begin interpreting the SPIN program in RAM from the beginning. Would you please explain how your example works because the assembly piece doesn't make sense from what I've gleaned from the manual and forum threads.
Mike
Yeah, unfortunately, it's more complicated than Beau's example. You must set up some word pointers, have some stack allocated and initialized, and then launch the interpreter pointing to the word pointers. I really like Beau's approach, though. That could be a goal for the next chip.
After discussing with Chip on the phone this evening what was really happening with the code that I posted, it seems that there is no easy way
to do this.
From a learning perspective, here is what my code IS doing that makes it "appear" to function properly....
[b]cognew[/b](CallSpinFromAsm,LEDTest1)
' OR
[b]cognew[/b](CallSpinFromAsm,LEDTest2)
This line never actually runs the Assembly code pointed to at 'CallSpinFromAsm'. Because the syntax for 'cognew' used in this way....
[i]COGNEW(AsmAddress, Parameter)[/i]
...COGNEW evaluates the 'Parameter' argument as 'LEDTest1' or 'LEDTest2' essentially looking at it as a function awaiting a value to
be returned so that it can be passed on to the Assembly program.
In doing so, 'LEDTest1' or 'LEDTest2' get launched but never return to the "COGNEW" command which originally called it.
To help prove this, the original program could have looked like this, and it still would have appeared to function properly...
If you loosen your definition of "call" slightly, you can call a Spin routine from assembly by using a dispatch table. This is the same technique used to call assembly routines from Spin, but in reverse. Here's an example:
The dispatch loop just waits for the command to become non-zero, then calls the associated subroutine with the arguments passed by the assembly routine and returns the return value in the first argument. (Return values are not used in the example.) Finally, the command is cleared to signal the assembly routine that it's done.
Notice that I did not call the pr.str routine in the example. To do so requires the hub address of a string, and this would require passing the address of a more complicated data structure in par.
Comments
Edit: Updated see below...
[s][b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL[/b]1 + [b]PLL[/b]16X [b]_XINFREQ[/b] = 5_000_000 LEDPin = 16 [b]PUB[/b] MainLoop 'cognew(CallSpinFromAsm,LEDTest1) <----Pass address of Spin program here [b]cognew[/b](CallSpinFromAsm,LEDTest2) [b]PUB[/b] LEDTest1 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]PUB[/b] LEDTest2 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 - [b]Ina[/b][noparse][[/noparse]LEDPin] [b]DAT[/b] [b]org[/b] CallSpinFromAsm 'PG 366 'Table 5-1: Destination Register Fields 'Bits 31:18 14-bit long address for PAR register 'Bits 17:4 14-bit long address of code to load 'Bit 3 Indicates a NEW cog 'Bit 2:0 Cog ID [b]rdlong[/b] Destination, [b]par[/b] 'Pass address location of Spin program [b]shl[/b] Destination, #4 'Shift 14-bit Long address left by 4-bits [b]add[/b] Destination, $F 'Set Bits 0-3 High ; CogID = 7 New = 1 [b]COGINIT[/b] Destination Destination [b]res[/b] 1[/s]▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 7/26/2006 7:36:08 AM GMT
Are you sure that's correct? Chip posted a very different short assembly routine that mostly made sure the clock was set according to what's specified in the SPIN program, but had a very different COGINIT operand that pointed to the SPIN interpreter in ROM so it gets loaded into the COG to begin interpreting the SPIN program in RAM from the beginning. Would you please explain how your example works because the assembly piece doesn't make sense from what I've gleaned from the manual and forum threads.
Mike
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
You are right.
After discussing with Chip on the phone this evening what was really happening with the code that I posted, it seems that there is no easy way
to do this.
From a learning perspective, here is what my code IS doing that makes it "appear" to function properly....
This line never actually runs the Assembly code pointed to at 'CallSpinFromAsm'. Because the syntax for 'cognew' used in this way....
...COGNEW evaluates the 'Parameter' argument as 'LEDTest1' or 'LEDTest2' essentially looking at it as a function awaiting a value to
be returned so that it can be passed on to the Assembly program.
In doing so, 'LEDTest1' or 'LEDTest2' get launched but never return to the "COGNEW" command which originally called it.
To help prove this, the original program could have looked like this, and it still would have appeared to function properly...
[b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL[/b]1 + [b]PLL[/b]16X [b]_XINFREQ[/b] = 5_000_000 LEDPin = 16 [b]PUB[/b] MainLoop 'cognew(CallSpinFromAsm,LEDTest1) <----Pass address of Spin program here [b]cognew[/b](CallSpinFromAsm,LEDTest2) [b]PUB[/b] LEDTest1 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]PUB[/b] LEDTest2 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 - [b]Ina[/b][noparse][[/noparse]LEDPin] [b]DAT[/b] [b]org[/b] CallSpinFromAsmNotice that there is nothing in the Assembly section other than a label? The code could be further equated to...
[b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL[/b]1 + [b]PLL[/b]16X [b]_XINFREQ[/b] = 5_000_000 LEDPin = 16 [b]PUB[/b] MainLoop 'LEDTest1 LEDTest2 [b]PUB[/b] LEDTest1 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]PUB[/b] LEDTest2 [b]Dira[/b][noparse][[/noparse]LEDPin] := 1 [b]repeat[/b] [b]Outa[/b][noparse][[/noparse]LEDPin] := 1 - [b]Ina[/b][noparse][[/noparse]LEDPin]...Once again proving that there was no Assembly code that was actually executed.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
[b]CON[/b] [b]_clkmode[/b] = [b]xtal[/b]1 + [b]pll[/b]16x [b]_xinfreq[/b] = 5_000_000 call_out = 1 call_str = 2 call_dec = 3 call_hex = 4 [b]VAR[/b] [b]long[/b] args[noparse][[/noparse]3] [b]OBJ[/b] pr : "tv_text" [b]PUB[/b] dispatcher | cmd pr.start(12) [b]cognew[/b](@asm_code, @args) [b]repeat[/b] [b]repeat[/b] [b]until[/b] cmd := args[noparse][[/noparse]0] [b]case[/b] cmd call_out: args[noparse][[/noparse]1] := pr.out(args[noparse][[/noparse]1]) call_str: args[noparse][[/noparse]1] := pr.[b]str[/b](args[noparse][[/noparse]1]) call_dec: args[noparse][[/noparse]1] := pr.dec(args[noparse][[/noparse]1]) call_hex: args[noparse][[/noparse]1] := pr.hex(args[noparse][[/noparse]1], args[noparse][[/noparse]2]) args[noparse][[/noparse]0]~ [b]DAT[/b] [b]org[/b] 0 asm_code [b]mov[/b] command,[b]par[/b] [b]mov[/b] arg1,[b]par[/b] [b]add[/b] arg1,#4 [b]mov[/b] arg2,[b]par[/b] [b]add[/b] arg2,#8 [b]mov[/b] counter,#0 main_loop [b]wrlong[/b] HOME,arg1 [b]call[/b] #pr_out [b]wrlong[/b] counter,arg1 [b]call[/b] #pr_dec [b]add[/b] counter,#1 [b]jmp[/b] #main_loop pr_out [b]wrlong[/b] _call_out,command [b]jmp[/b] #wait_return pr_dec [b]wrlong[/b] _call_dec,command wait_return [b]rdlong[/b] tst,command [b]wz[/b] [b]if_nz[/b] [b]jmp[/b] #wait_return pr_out_ret pr_dec_ret [b]ret[/b] _call_out [b]long[/b] call_out _call_dec [b]long[/b] call_dec HOME [b]long[/b] 1 counter [b]res[/b] 1 command [b]res[/b] 1 arg1 [b]res[/b] 1 arg2 [b]res[/b] 1 tst [b]res[/b] 1The dispatch loop just waits for the command to become non-zero, then calls the associated subroutine with the arguments passed by the assembly routine and returns the return value in the first argument. (Return values are not used in the example.) Finally, the command is cleared to signal the assembly routine that it's done.
Notice that I did not call the pr.str routine in the example. To do so requires the hub address of a string, and this would require passing the address of a more complicated data structure in par.
-Phil
any way to change the forum width? Some of these threads are hard to read [noparse]:)[/noparse]
Robin