waitpxx & jmp
average joe
Posts: 795
While working on a particular piece of PASM I ran into problems. It took me a while to figure out the cause but it comes down to not being able to jump to a waitpxx.
This is what I started with, does not work :
This code fails after the first iteration of the loop. Correcting was as simple as adding a nop as such :
Still, I could not find any information in the manual about this. My thought is it comes down to the pipelining? This took me a while to figure out. (and quite a bit of frustration.) Maybe I'm missing something? Any help would be greatly appreciated!
This is what I started with, does not work :
:loop waitpeq zero, trigger ' wait for trigger pin to be idle waitpne zero, trigger ' wait for trigger pin to be active ... 'do something ... jmp :loop ' repeat
This code fails after the first iteration of the loop. Correcting was as simple as adding a nop as such :
:loop nop waitpeq zero, trigger ' wait for trigger pin to be idle waitpne zero, trigger ' wait for trigger pin to be active ... 'do something ... jmp :loop ' repeat
Still, I could not find any information in the manual about this. My thought is it comes down to the pipelining? This took me a while to figure out. (and quite a bit of frustration.) Maybe I'm missing something? Any help would be greatly appreciated!
Comments
While working on this I realized that if I take a sample within 4 clock of a wrap, the high 32 bits would increment. I tried using the commented out code, but does not seem to work properly. I'm still trying to figure out the right way to handle this.
*edit*
Think I've got it. Easier (and quicker) to do in PASM.
Next, internal overhead. Let's assume you read $FFFFFFFC for the low part (high is 0). This means not carry and therefore the high part is not modified. However, the high part is read 4 cycles later (low is 0). During this clock the link output goes low. Another cycle later this low makes it into the A1 counter flipflop. In the next cycle the counter increment logic sees the !A1&A2 condition which finally causes it to increment the high part. This means the change you're hoping to read is two cycles late. That said, you could use a 6 cycle DMZ to adjust for internal delays (my initial implementation) but this wouldn't protect you from external delays. In the end I increased the DMZ and simply re-read both values in case of a wrap collision (see posted example code).
In propgcc another solution is used. IIRC, high is read first followed by low. Then high is read again, if it has changed the low part is re-read then this value is reported. I'll post a link later if I can find it again.
*edit*
So I come up with something like this :
Not sure if I can compensate for the small delay, or if it's even necessary at this point.
Above version slightly shorter. What delay are you worried about? The compensation? That's only 12 extra cycles (which you probably already get by waiting for hub windows). You could move the long_2 adjustment between both wrlongs though.