PASM2 noob issue
jrullan
Posts: 168
It's been a while since I wetted my toes in PASM2 and I wanted to create a seemingly simple program just to go over some concepts of PASM2. So, I created this small program to calculate the length of a zero terminating string in hub memory.
I expected STRSIZE to give the same result as the counter value in the PASM program running on the other cog, but they are not. If anyone could point out what's wrong I would appreciate it (I'm 99% sure it's a misconception on my part)
CON _CLKFREQ = 160_000_000 MAX_CHARACTERS = 10 VAR byte size byte text[MAX_CHARACTERS+1] PUB main() set_text(String("Hello")) coginit(COGEXEC_NEW, @sizeof, @size) waitms(1) debug(ZSTR(@text)) debug(udec(STRSIZE(@text))) debug(UDEC(size)) PUB set_text(addr)|c,i 'Clear text repeat i from 0 to MAX_CHARACTERS text[i] := 0 'Set new text repeat i from 0 to MAX_CHARACTERS-1 'Reserve last character place for the terminating 0 c := BYTE[addr][i] debug(udec(c)) if c <> 0 text[i] := c else quit text[i] := 0 DAT ORG sizeof 'get the address of size MOV retpointer, PTRA 'get the address of text[0] MOV pointer, PTRA ADD pointer, #1 .loop 'checks if text[pointer] is 0, if it is jumps to .return RDBYTE charvalue, pointer '<--- Read the value of the hub memory location pointer and copy it to charvalue TJZ charvalue, #.return ADD pointer, #1 ADD counter, #1 JMP #.loop .return 'copy the value of counter to the address of the return value variable WRBYTE counter, retpointer ' local variables counter byte 0 ALIGNL charvalue byte 0 pointer res 1 retpointer res 1 FIT 496
Comments
Your program is missing an ending, so it's running off and executing garbage. Put a
JMP #$
at the end to trap it in an infinite loop.Also, all cog ram variables must be long, since that's how the CPU addresses them (unless you use the special GETBYTE/SETBYTE instructions)
Thank you @Wuerfel_21 !
Added the
JMP #$
at the end of the program and it worked as expected.I'll get into the GETBYTE/SETBYTE instructions next.
Also, you if you wanted to do this same thing but better:
When reading memory at incrementing addresses, use the RDFAST mechanism where possible, it saves you from having to increment the pointer and is also significantly faster. You can also combine the increment of the counter with the branch.
Actually, there's a really cracked way to do a count like this that's even more fasterer (4 cycles per byte instead of 6).
Nice, thanks!
I got another noob question.
I don't understand why this wont work:
My assumption was that once I have the hub address of the variable
send_value
, if I add 4 to it I would get the address of the next long which isreturn_value
.However, if I just refer to PTRA[0] and PTRA[1] in the RDLONG and WRLONG instructions respectively it does work as expected:
If someone knows what I'm doing wrong, please let me know. Thanks.
It acts like an array index. It's built into the RDLONG/WRLONG instructions themselves. PTRA holds the base address, the index is then multiplied by 4 before being added to the base. RDWORD/WRWORD are x2. RDBYTE/WRBYTE are x1.
However, this feature is limited to PTRA/PTRB special registers, and also max index of +31 -32 I think.
Further reading under HubRAM Interface sub-section RANDOM ACCESS INTERFACE in the Silicon Doc.
EDIT: Oh, I see. You already know that. You're right, the first approach should also work. Dunno why it doesn't.
EDIT2: Found it after typing each line in and getting a compile error because I'd renamed "services" to "loop". The
coginit(COGEXEC_NEW, @services, @send_value)
call is not correct as is. You need a label for starting the cog at the ORG point. It didn't matter for the second example since that part of the code was redundant then.Oh right! I suspected it was something trivial!! Thanks @evanh !!