inline pasm interrupt routine local variables
was playing with an interrupt routine created with inline code. I thought that if I stayed in the method that it was created with, I could use the 15 local variables to communicate with the interrupt routine after the inline ends. Turns out you can't, the 15 local variables get sent back to the hub. But the PR0-PR7 cog variables work between the spin method and the interrupt... They probably work even from outside the method, as long as it's the same spin cog... Something else that seems to work is taking the address of a inline variable, pTick, and assigning that to one of the 15 locals, "MOV Tick , #pTick" and once the inline ends, use LONG[Tick] := NewValue
That gets data from spin to pasm...
The new pointer type may make this even cleaner.
Any other better ways to get data to/from the interrupt?`` I know rdlong and wrlong would work but that's messy...
PUB Interrupt()|Tick
org
mov Tick,#pTick
mov pr1,##200_000_000
mov ijmp1,#isr1
getct pr0
addct1 pr0,pr1
setint1 #1 'when ct passes ct1
ret
isr1 add pr2,#1
addct1 pr0,pTick 'pr1
reti1
pTick long 200_000_000
end
repeat
waitms(1)
if !(pr2==pr3) 'if interupt count changes, stage a new random count
debug(udec(pr2),udec(pr4))
pr3 := pr2
pr4 := getrnd()
pr4 := (pr4 >> 3) + 10_000_000 'random time delay between 1/20 sec and 5 seconds
pr1 := pr4
long[Tick] := pr4

Comments
PR0..PR7 will remain at all times, even accessible from other methods.
If you loaded a local variable with the address of a VAR long (localvar := @longvar) and had the interrupt-setup inline code remember it in one of the upper free registers, like $0FF, the innterrupt routine could always use that pointer for RDLONG/WRLONG to access the VAR long.
I think inline PASM is for transient code only. That said, there are a couple ways to put code into the interpreter cog user space and leave it there. Chip was coaching me on this a couple years ago. I dusted this off -- and it seems to work -- but the code does hard-wire hub address $0000 and $0001, and I don't know if this is a problem with the current interpreter. Still, it may help you with your projects. In this case a 10ms interrupt timer is setup to drive an RTC. When running it looks like this:
Note that the code we want to leave in the interpreter cog is put into the upper region so that we can still load PASM from inline code into the lower area of the user memory.
Yes, follow Jon's solution, using a REGEXEC() statement and DAT section, to install the ISR into the middle of cogRAM space. This avoids "inline" address space in the first half of cogRAM.
As for local variables, Pnut based compilers don't use cogRAM for locals. Yes, PRx global registers are always there on each cog.
Flexspin uses cogRAM for locals but then it doesn't support interrupts, nor REGEXEC(), with Spin2 on the same cog. Flexspin can do interrupts as a Pasm2 program launched on it's own cog. Of course you're basically writing a driver then. I did this with PropSPI - https://obex.parallax.com/obex/propspi/
The spin manual says:
● Each object's first 15 longs of variable memory are accessed via special bytecodes for improved efficiency.
For my ISR, the pasm can read or write to the hub with a rdlong or wrlong instruction, but may take 2 to 8 clocks for the hub to rotate around... and then I'm tempted to read a few by putting a setq in front...
The ISR can read or write a cog register in 2 clocks.
So, I can do it either way in the ISR...
I don't know how fast spin can read/write cog registers (pr0-pr7 or long[0..511] vs. hub variables... Spin is executing interpreter from LUT usually streaming program from Hub... I think...
So, I'm not sure what would be the fastest/most efficient two way communication between ISR and spin?
This isn't for any pressing issue, but been wondering these things for a while...
That's sounding more like a desire for multitasking than a special ISR.