I/O glitch when setting pin direction?
ags
Posts: 386
I'm debugging an intermittent problem communicating to an external (SPI) device. I'm seeing a ~16us glitch on an IO pin. That pin has a 50kOhm pullup.
I'm just prototyping and am using SPIN (eventually to be converted to PASM for speed). I'm first setting the outa[pinNum] to 1, then setting dira[pinNum] to 1. I expected that this would drive pinNum high immediately. Is there some delay between setting the pin direction to output and when it is actually driven high, even if the output value is set high before the pin direction is set to output?
In other words, with this code:
I'm just prototyping and am using SPIN (eventually to be converted to PASM for speed). I'm first setting the outa[pinNum] to 1, then setting dira[pinNum] to 1. I expected that this would drive pinNum high immediately. Is there some delay between setting the pin direction to output and when it is actually driven high, even if the output value is set high before the pin direction is set to output?
In other words, with this code:
outputPinMask:= |<clkPin | |<mosiPin | |<csPin outa |= |<mosiPin | |<csPin dira |= outputPinMaskand a 50k pullup on csPin, can I expect that the csPin would not experience any glitch (low) when changed from being an input to an output, if the output register is "preset" with a high value for that pin?
Comments
I find it best to start with overtly-obvious code in the beginning, then optimize once things are working.
Almost nothing else. I do test ina to see if the csPin pullup is present (to detect the external device).
I may have some noise, this is a messy prototype on a breadboard with jumpers. I'll have to see if I can capture this with a scope to see if it's really a clean signal driving low or noise. That won't be easy, so I thought I'd check my understanding of ina and dira before beginning that headache of a task.
As to the direction reg being OR'ed, that's what I thought from the specs. Let me see if I can set up an example for you of what I was getting, much to my surprise, where I could not toggle an out pin after it had been set as an output in another cog. We agree it shouldn't be this way? Maybe I was doing something wrong, but let me see.
No, setting pins and directions is not a HUB operation. They happen as soon as they are executed at normal PASM instruction speed. If they were dependent on HUB timing then handling I/O pins would be 8 times slower which would be a disaster.
No we don't agree. You have to set DIR from the same COG has you are doing OUT from That is clearly explained with nice diagrams in the manual.
If you have a 16us delay in there somewhere that is a lot. Like 320 instructions worth. Even if things were tied to HUB timing that would be huge. You have some other problem going on here.
Of course Spin is slow so those 3 lines of code will take 100's of instruction cycle times. Perhaps your code really does take 320 instructions (16us) to execute.
But bear with me, for that bit of a miracle to be possible, in the end it's easy for multiple cogs to read a pin, but for output it seems that something like a semaphore, latch, or exclusivity lock would be in place for the operation to atomically complete, especially if dira[ ] is being changed, hence my naive thinking that it could be Hub-related. Are you saying that all the I/O registers, timers etc are shared by 8 cogs with everything taking place at gate propagation speed - no latches, no clocked sequencing? Thanks.
For "that bit of a miracle to be possible" it does not require any semaphores, latches, or exclusivity locks (Apart from the latches that are the DIR and OUT registers). All that is needed is AND and OR gates.
Yes.
If we look at page 20 of the Propeller Manual (v1.2) we see that there is an I/O output and direction register in each cog. It shows how each bit of a COGs output and direction registers are ORed together with those corresponding bits of every other COG to determine the final pin direction and output drive.
Clearly there is no need to go through the HUB round robin access scheme to use those.
On page 21 we see another diagram again showing the same I/O logic. Again there is no interaction with the HUB timing here either.
This is spelled out in the text on page 26:
Why do we have to set DIR from the same COG that is driving an output then?
Have a look at the diagrams again. In that logic tree driving each final output and direction we see that in each COG the is an AND gate. It ANDs the bits from the COGs direction register with the bits of the output register.
So, if a COG does not set it's DIR it cannot drive any outputs into the OR logic that combines direction and outputs from all the other COGs.
I think that is all clear enough.
I have to repeat my question: "How are you measuring that 16us "glitch"?"
The code you show us so far is not enough. If you are using an LSA you must be watching some pin changing state that is the eventual cause of the output you expect. And I guess there is some other code involved to at least read that input.
OK, so you drive an output, some kind of CS, then you drive some other pin and the LSA shows you want is happening. Good stuff. Now all we need to know about is all the code you have between those two pin events.
We also need to be sure there is no other code, on other COGs, accidentally tweaking those same pins.
As both these events are driven my your code they should be 100% predictable.
why don't you just post the complete minimum code to produce the effect?
Then others either can reproduce or find the problem in the code ...
I started from scratch and reimplemented this section of code and I no longer see this problem. So I'm going to remove the unsolved notation from this post (still not solved, though, since I can't explain the cause). I'd still like confirmation, if possible, of what I've come to take for granted regarding control of output pins (even in SPIN). That is, if a pin is configured as an input (high impedance), when dira is modified to configure that pin to an output, there will only be one transition on that pin, either directly to a high or low state (based on the value of outa). In other words, for pin 0, if outa[0]==0, then when dira[0]:=1, pin 0 will not drive high and then settle to a low state, it will move from hiZ to low state direclty; similarly, if outa[1]==1, when dira[0]:=1, pin0 will not drive low then settle to a high state, it will move from hiZ to high state directly.
If you are still not convinced then a simple test program, your external circuit, and an LSA are sufficient to demonstrate it for yourself.
Without a glimpse at your code we are unable to diagonse anything.
Given that you seem to have code that "works" now and code that does not I don't see why you cannot post that little part.
And it would help to know what is connected externally.
If OUTA[n] is 1 and DIRA[n] is changed from 0 to 1, the I/O pin will go from a hiZ state to a high state without any other transitions. Similarly, if OUTA[n] is 0, the I/O pin will go directly to a low state. Depending on what's connected to the I/O pin, there may be RC delays or reflected pulses that may distort the waveform seen at the I/O pin, but it doesn't sound like that's what you're seeing. I suspect a software problem.
There are several commonly used objects that use this technique including some that I've written and have been in use for years. Occasionally people have looked at the output signals using a scope and they don't behave the way you describe. In addition, they would likely not work correctly.