Forcing exit of 'waitpeq' if no match occurs
Harley
Posts: 997
Don't know if this subject has been discussed before.
In case a match doesn't happen for a 'waitpeq', is there a way for SPIN to kill the cog in question (say via COGSTOP)?
And if so, can the same assembly routine be reinvoked after the stop?
If so, how much time does it take for this to be available again? (Hopefully the whole program doesn't have to be downloaded from EEPROM again; that takes seconds)
If there are any threads on this subject, steer me to them please.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
In case a match doesn't happen for a 'waitpeq', is there a way for SPIN to kill the cog in question (say via COGSTOP)?
And if so, can the same assembly routine be reinvoked after the stop?
If so, how much time does it take for this to be available again? (Hopefully the whole program doesn't have to be downloaded from EEPROM again; that takes seconds)
If there are any threads on this subject, steer me to them please.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
Comments
You can kill a cog with waitstop, no problem, and you can anytime relaunch with the same code in another cog or the same. I do not see a problem, but you will need two threads, one to wait and one of timeout and a shared variable to indicate that the waitpeq stopped waiting or not.
A possibility would be to do a waitpne (with a reversed bit in the state), and add an additional pin (not used externally) in the mask, with the corresponding state at 0. Another cog could set this pin to trigger the end of the waitpne, for example on a timeout or whatever other condition. The waiting cog should check if the waited pin was changed or if the timeout pin was set.
Depending on the interface circuit, you could even use the same input pin, with another cog making it an output and forcing a value so that the waiting cog continues.
I hope this help finding an alternative solution to a brutal stop and reload.
--- Jean-Marc
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jean-Marc
lots of interesting ideas - all have their obvious grave drawbacks...
But that depends on the specific situation.
The original idea to reload the same COG is not as bad as it may sound... The question is: What is exactly the situation when you encounter a time-out?
It takes around 500 * 16 ticks * 12,5 ns = 100 µs to reload a COG (this happens from the HUB RAM of course , not from the EEPROM).
@ Ale, I didn't find a 'waitstop' in SPIN but the COGSTOP is probably what you meant. That instruction doesn't imply that the same cog can't be reused. Because hanging on a waitpeq (like waiting for a breakpoint to occur) might happen many times. And there aren't enough cogs left if they cannot be reused.
From reading the Spin pages on COGINIT and COGSTOP, it appears there should be a way to stop a hung up waitpeq cog, then restart it with COGINIT.
Mike Green, anyone else, does this sound right?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
So, does all of the code downloaded from EEPROM stay in hub RAM to be used over and over if needed? Like the assembly code which the waitpeq resides in?
That 100 µsec wouldn't be noticable for the user; human reaction times aren't that quick. ("Wanna see it again?")
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
Post Edited (Harley) : 12/19/2007 9:40:08 PM GMT
When you need to relaod it use COGINIT(cid,...)
That's what COGINIT has been made for
My solution on this is.
Have one pin dedicated to timeout with litle external hardware.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nothing is impossible, there are only different degrees of difficulty.
Sapieha
Beginning to comprehend this situation.
@Sapieha,
Even with using two Props, I'm short on cogs and I/O pins. So the suggestion is appreciated, but must not do that unless nothing else works.
Now, back to the coding 'drawing board' to solve this problem.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
If you can spare just one more pin, you can do what you want in the same cog. The idea is to use WAITPNE, masking to two pins: your input pin, and a second pin set as as output and controlled by one of the counters. Set up the counter for for NCO mode with an output on the second pin. Set its FRQx register to be 1. Just before the WAITPNE, set the counter's PHSx register to $8000_0000 - timeout_clocks. When the timer times out, the pin will change state from 0 to 1, which your WAITPNE will catch. You can then check the state of the counter's output pin to see if a timeout occurred. If not, it was your input pin.
-Phil
ViewPort v2 uses waitpne to trigger on signals. If the required signal isn't found, ViewPort can reset the trigger- by stopping the measuring cogs (up to 4 when sampling at 80mhz) and then restarting. As deSilva pointed out, stopping and starting cogs is very fast.
Hanno
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
That's certainly more appealing than the only single-pin, single-cog solution I could come up with. (It involved burning out the p-cbannel driver on the pin, thus converting it to open-drain so it could be shared with a counter. )
Of course, one could reuse a pin for the counter, like SCL perhaps, that's only used at startup (unless the app itself accesses EEPROM).
-Phil
A "second cog watch dog" comes closer to "exception handling" which causes no delay in the common case.
Post Edited (deSilva) : 12/20/2007 5:08:31 PM GMT
The key-sentence is:
"A pin is an output if *any* active cog sets it to an output"
Now if you protect the input-pin with an R so it doesn't short circuit when it suddenly becomes an output, you can have the watchdog-cog set that pin to output and switch it to such a state, that the timed-out cog reads the level he needs to break the waitpeq.
Didn't verify that, so maybe you've got something to laugh.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
In the Propeller, each cog can act as an "interrupt system". It would be easy to implement both a pin-change "ISR" cog and a timer "ISR" cog. The pin-change cog simply waits, using a masked WAITPNE with the last pin states observed. When a pin changes state, that fact would be processed by the "ISR" the same as it would be in a traditional processor, with the information it produces communicated to hub variables for other cogs to read. If it never excutes, because nothing changed, so what? It can just sit there, no harm is done, and it doesn't need to be restarted. The timer "interrupt" can handle any watchdogging that needs to take place. This is more in line with deSilva's approach.
Whether a two-extra-cog "interrupt" solution is wasteful of precious resources or has too high a latency depends entirely on the overall application. For Harley's app, we really don't have enough information to make that judgement.
-Phil
COGs can be used for four purposes (though maybe even more...)
(1) Running parallel code to increase algorithmic performance
(2) Supervising hard- or software states by polling
(3) Activating additional timer/counter/video logic
(4) Depositing machine code to take advantage of the generic processor speed
So what is waste? You can argue that waste is all which does not take advantage of all four offers. But the propeller way is just to use overkill!
It is the same waste as using a Controller with CAN-bus and not using the CAN-bus. Stupid, isn't it? Why pay $3 more for it rather than use the version without CAN!
Don't think I have forgotten the original problem! Why use WAITxxx in the first place? It gives you a VERY PRECISE return wrt to the event, within a fraction of an instruction time. This is "Hardware Polling". There is no other way (of course you can always wish for a combined WAITCNTPEQPNE ).
"Software Polling" takes at least some instructions
Post Edited (deSilva) : 12/20/2007 5:54:21 PM GMT
"But the waitpeq has to be no longer than that one instruction takes;"
So you can't have loops. And I have to reason, that there is no time left for communication between cogs.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
-Phil
In my example I need 12 to 16 ticks before I can act according to the event waited for...
Counter A is set to increment whenever the pin is of the desired state. Counter B is set as an NCO and increments continuously to zero. Its "ouput pin" is set (as a dummy) to the pin being tested. Since DIRA for this pin will equal zero, the NCO output will affect only OUTA and not the pin itself. The last three bits of FRQB have to be set in such a way that PHSB reaches zero when it's tested. I don't know, without further analysis or testing, what this value (for phase in the above program fragment) would be.
-Phil
Update: Corrected to add # to the jump targets. Not that it matters since, as deSilva points out below, PHSx won't read properly in the destination field (TJZ and TJNZ instructions, above).
Post Edited (Phil Pilgrim (PhiPi)) : 12/22/2007 1:06:23 AM GMT
One thing this thread doesn't address is if you've got multiple pins that need to be scanned for changes. I wanted to monitor 8 pins P8-P15. I'm expecting about 2000 transitions per second per pin - which means that in the following code about 98% of the time is spent at the waitpne instruction.·The transitions seen·are written to a circular buffer. A second cog does the processing of the circular buffer - as well as timeouts and additional filtering. The nett result is that the majority of transitions are time-stamped with 12ns accuracy - with about 2% of the transitions being accurate to about only 1us - but this is oK in my case.
I've not shown any of the·FIFO buffer setup and cog initialisation, so you'd need to do that before using this code. The actual code I use does a couple of other things, and is more efficient, but this gives a fair idea of the logic.
I fear it will not work... It's not the missing # with the labels, but you will not read PHSx correctly at the dest-position.
Good work! However, you will not only mis-time 2% of your signals as you say, but loose between 4/10,000 and 1%, depending on the actual distribution. It can be even more, as this is an interarrival time problem, statistically speaking.
This is the setting:
A young man entertains two girl friends, living at different ends of the town. He himself lives in the center taking the underground either to one direction or the other. Both trains leave from the same platform and both run every 10 minutes. He enters the station randomly (and daily!) and takes the first train leaving.
At the end of the month he finds that he has visited one girl friend twice as often as the other one. How can that be?
("She is blond!" is the wrong answer.)
Yup, right on both counts. The # thing is perennially vexatious and, I fear, always will be. (It's one of the reasons I'm so keen on getting preprocessor hooks in the IDE.) And the source register bit — how inconvenient! — is already in Tricks & Traps. Ouch!
-Phil
The trains may run every 10 minutes, but they depart at:
10:00 -· Train A
10:03 -· Train B
10:10 -· Train A
10:13 -· Train B
etc.
So you have a higher probability of catching Train A.
BTW: I've not seen this conundrum before!
·
The timeout test compares the computed compare time to CNT. Again, the value for phase needs to be determined either analytically or empirically so that equality can be reached when the CMP is executed. The subsequent JMP gets executed only if there was no timeout. PHSA is used to hold the target address of the JMP, which normally points back to the beginning of the two-instruction loop. When the pin changes, though, PHSA points to pin_change instead. (For this to work, the time from edge-to-like-edge must be eight clocks or more. Otherwise PHSA could increment twice between tests.)
-Phil
One can stabilize it a little bit more by jumping away in the time-out situation, thus PHSA being 3, so one can add 24 NOPs at the beginning of the signal processing part
Just kidding... In fact this can be utilized to notice the number of events within the 100 ns loop, but it will counterfight the very purpose of your fine example.
I think Mirror's example gives a good and new inside to the nature of the problem.
In fact we are talking about Nyquist, which sometimes gets lost when using "digital talk".
"What frequency can I handle?" ist the same question as: "What interarrival time of pulses can I handle?" When you habe a good idea of pulse length (and glitch characteristic) - as Mirror has - than this is easy.
For the throughput of signal processing it will be of little interest whether you catch the µs-pulse some nanoseconds earlier or later....
However: You sometimes want to know it's precise phase, and then these nano seconds are your accuracy! I think this is the case in Mirror's example and in your exercise: getting the time!
This is where "Capture and Compare" units are used for in standard microcontrollers..
Post Edited (deSilva) : 12/22/2007 7:04:38 PM GMT
It seems troublesome to adjust phase as a compile time constant, and won't it change with the onset of hub instructions and other waitxxx? Can it be determined or forced at run time just before entering the watchdog routine? (I don't know, I'm asking!)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
timeout_cmp always has to be reinitialized before entering the test loop. As long as this is done a fixed number of clocks ahead of the first compare, the value for phase will not change, since it's dependent only on the number of clocks (mod 8) between the initialization and the compare. This can easily be accomplished by jumping to the initialization section after processing each timeout or pin-change.
Initializing FRQA needn't be in this section at all. Initializing CTRA could be eliminated from this section, too, if you're always looking for the same edge. If not, it should remain where it is, and the pin-change routine can flip the polarity bit in modea before jumping back to the beginning.
Here's how things might be rearranged:
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 12/22/2007 10:39:22 PM GMT