Global variables in assembler
John_B
Posts: 16
Hi,
I have an assembly routine reading the 'a' and 'b' counters in a cog. How do I set up global vars that can be set by the assembler with the count values and read by spin which will then display the two counts.
I have it working with one counter using the 'par' as the var pointer, but I can not figure out how to transfere both counts.
John
I have an assembly routine reading the 'a' and 'b' counters in a cog. How do I set up global vars that can be set by the assembler with the count values and read by spin which will then display the two counts.
I have it working with one counter using the 'par' as the var pointer, but I can not figure out how to transfere both counts.
John
Comments
1. Instead of two vars a and b you could have an array a
or
Use 2 vars which are defined one behind the other. They have to be the same type!
So you still have to pass one adress. Please be aware that using PAR for passing adresses only works in case your adress is long alligned. Due to the fact that PAR will clear the 2 LSBs. Your PASM code then accesses the first variable as before and uses PAR+4 for the next long / PAR+2 for the next word or PAR+1 for the next byte.
2. If you one day have to pass vars of different types an array of pointers would do the job. The PAR then holds the adress of that array.
3. You can use SPIN to write the adresses into your PASM code before you start it. No need to use PAR at all.
it works ok, displaying counter 'a' value, including this line and everything goes to pot. Adding 4 to the value in PAR so that it points to the 2nd element in freq1 array - Am I doing this correct.
VAR
long freq1
PUB Main | tmDelay
cognew(@entry, @freq1)
Init
tmDelay := cnt
repeat
waitcnt(tmDelay += clkfreq)
!outa[noparse][[/noparse]INTEG_LED]
DispFreqs(freq1[noparse][[/noparse]0], freq1)
DAT
org
entry mov ctra, ctra_ 'set mode and start counter
mov frqa, #1 'increment for each incomming pos edge
mov ctrb, ctrb_ 'same for b
mov frqb, #1
mov cnt_, cnt 'setup time delay
add cnt_, cntadd
:loop waitcnt cnt_, cntadd 'wait for next sample
mov new_a, phsa 'record 'a' and 'b' couints
mov new_b, phsb
mov temp, new_a 'make second copy
sub new_a, old_a
mov old_a, temp
wrlong new_a, par 'save new 'a' count
mov temp, new_b 'do the same for 'b'
sub new_b, old_b
mov old_b, temp
'wrlong new_b, par+4 '<<<<<<<<<<<<<<<<<<<<<<<<<<<
jmp #:loop
ctra_ long %01010 << 26 + 7 'mode + APIN
ctrb_ long %01010 << 26 + 8 'mode + APIN
cntadd long 16_384_000 + 85 'wait 1 second, apply xtal error compensation.
cnt_ res 1
new_a res 1
new_b res 1
old_a res 1
old_b res 1
temp res 1
wrlong new_a, par
par is nothing else but a replacement of a memory adress in COG-RAM ( $49? - I forgot the right adress ;o).
The wrlong instruction fetches the data inside of that RAM-adress. That's the pointer to your variable.
If you tell the compiler to do this:
wrlong new_b, par+4
you add the 4 to the memory adress of PAR ( $49x+4) - which is then a completely different special purpose register - and read it's content. That's no longer the pointer to HUB-RAM.
You have to do:
add PAR, #4
wrlong new_b, PAR
sub PAR, #4 -> for the next loop
That won't work either because PAR is a read-only register. You have to move the value to some other location to add to it like:
This is identical to Mike's suggestion except that I'm only using par at the entry of the program; both strategies work.
par+4 was an error on my part, and of course·I can't alter its value with being read only. Made a copy of par, used it for 'a' then added 4 and used it·for 'b', then sub 4.
All makes sense now - again thanks.